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.
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.
11 use dep_graph::DepNode;
12 use middle::ty::{Ty, TyS};
15 use rustc_data_structures::ivar;
18 use std::marker::PhantomData;
19 use core::nonzero::NonZero;
21 /// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
22 /// on the lifetime of the IVar. This is required because of variance
23 /// problems: the IVar needs to be variant with respect to 'tcx (so
24 /// it can be referred to from Ty) but can only be modified if its
25 /// lifetime is exactly 'tcx.
27 /// Safety invariants:
28 /// (A) self.0, if fulfilled, is a valid Ty<'tcx>
29 /// (B) no aliases to this value with a 'tcx longer than this
32 /// Dependency tracking: each ivar does not know what node in the
33 /// dependency graph it is associated with, so when you get/fulfill
34 /// you must supply a `DepNode` id. This should always be the same id!
36 /// NonZero is used rather than Unique because Unique isn't Copy.
37 pub struct TyIVar<'tcx, 'lt: 'tcx>(ivar::Ivar<NonZero<*const TyS<'static>>>,
38 PhantomData<fn(TyS<'lt>)->TyS<'tcx>>);
40 impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
42 pub fn new() -> Self {
43 // Invariant (A) satisfied because the IVar is unfulfilled
44 // Invariant (B) because 'lt : 'tcx
45 TyIVar(ivar::Ivar::new(), PhantomData)
49 pub fn get(&self, dep_node: DepNode) -> Option<Ty<'tcx>> {
50 tls::with(|tcx| tcx.dep_graph.read(dep_node));
55 fn untracked_get(&self) -> Option<Ty<'tcx>> {
58 // valid because of invariant (A)
59 Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
64 pub fn unwrap(&self, dep_node: DepNode) -> Ty<'tcx> {
65 self.get(dep_node).unwrap()
68 pub fn fulfill(&self, dep_node: DepNode, value: Ty<'lt>) {
69 tls::with(|tcx| tcx.dep_graph.write(dep_node));
71 // Invariant (A) is fulfilled, because by (B), every alias
72 // of this has a 'tcx longer than 'lt.
73 let value: *const TyS<'lt> = value;
74 // FIXME(27214): unneeded [as *const ()]
75 let value = value as *const () as *const TyS<'static>;
76 self.0.fulfill(unsafe { NonZero::new(value) })
80 impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 match self.untracked_get() {
83 Some(val) => write!(f, "TyIVar({:?})", val),
84 None => f.write_str("TyIVar(<unfulfilled>)")