]> git.proxmox.com Git - rustc.git/blob - src/librustc/ty/ivar.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / librustc / ty / ivar.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use dep_graph::DepNode;
12 use hir::def_id::DefId;
13 use ty::{Ty, TyS};
14 use ty::tls;
15
16 use rustc_data_structures::ivar;
17
18 use std::fmt;
19 use std::marker::PhantomData;
20 use core::nonzero::NonZero;
21
22 /// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
23 /// on the lifetime of the IVar. This is required because of variance
24 /// problems: the IVar needs to be variant with respect to 'tcx (so
25 /// it can be referred to from Ty) but can only be modified if its
26 /// lifetime is exactly 'tcx.
27 ///
28 /// Safety invariants:
29 /// (A) self.0, if fulfilled, is a valid Ty<'tcx>
30 /// (B) no aliases to this value with a 'tcx longer than this
31 /// value's 'lt exist
32 ///
33 /// Dependency tracking: each ivar does not know what node in the
34 /// dependency graph it is associated with, so when you get/fulfill
35 /// you must supply a `DepNode` id. This should always be the same id!
36 ///
37 /// NonZero is used rather than Unique because Unique isn't Copy.
38 pub struct TyIVar<'tcx, 'lt: 'tcx>(ivar::Ivar<NonZero<*const TyS<'static>>>,
39 PhantomData<fn(TyS<'lt>)->TyS<'tcx>>);
40
41 impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
42 #[inline]
43 pub fn new() -> Self {
44 // Invariant (A) satisfied because the IVar is unfulfilled
45 // Invariant (B) because 'lt : 'tcx
46 TyIVar(ivar::Ivar::new(), PhantomData)
47 }
48
49 #[inline]
50 pub fn get(&self, dep_node: DepNode<DefId>) -> Option<Ty<'tcx>> {
51 tls::with(|tcx| tcx.dep_graph.read(dep_node));
52 self.untracked_get()
53 }
54
55 /// Reads the ivar without registered a dep-graph read. Use with
56 /// caution.
57 #[inline]
58 pub fn untracked_get(&self) -> Option<Ty<'tcx>> {
59 match self.0.get() {
60 None => None,
61 // valid because of invariant (A)
62 Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
63 }
64 }
65
66 #[inline]
67 pub fn unwrap(&self, dep_node: DepNode<DefId>) -> Ty<'tcx> {
68 self.get(dep_node).unwrap()
69 }
70
71 pub fn fulfill(&self, dep_node: DepNode<DefId>, value: Ty<'lt>) {
72 tls::with(|tcx| tcx.dep_graph.write(dep_node));
73
74 // Invariant (A) is fulfilled, because by (B), every alias
75 // of this has a 'tcx longer than 'lt.
76 let value: *const TyS<'lt> = value;
77 // FIXME(27214): unneeded [as *const ()]
78 let value = value as *const () as *const TyS<'static>;
79 self.0.fulfill(unsafe { NonZero::new(value) })
80 }
81 }
82
83 impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 match self.untracked_get() {
86 Some(val) => write!(f, "TyIVar({:?})", val),
87 None => f.write_str("TyIVar(<unfulfilled>)")
88 }
89 }
90 }