]> git.proxmox.com Git - rustc.git/blob - src/librustc/ty/ivar.rs
Imported Upstream version 1.9.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 #[inline]
56 fn untracked_get(&self) -> Option<Ty<'tcx>> {
57 match self.0.get() {
58 None => None,
59 // valid because of invariant (A)
60 Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
61 }
62 }
63
64 #[inline]
65 pub fn unwrap(&self, dep_node: DepNode<DefId>) -> Ty<'tcx> {
66 self.get(dep_node).unwrap()
67 }
68
69 pub fn fulfill(&self, dep_node: DepNode<DefId>, value: Ty<'lt>) {
70 tls::with(|tcx| tcx.dep_graph.write(dep_node));
71
72 // Invariant (A) is fulfilled, because by (B), every alias
73 // of this has a 'tcx longer than 'lt.
74 let value: *const TyS<'lt> = value;
75 // FIXME(27214): unneeded [as *const ()]
76 let value = value as *const () as *const TyS<'static>;
77 self.0.fulfill(unsafe { NonZero::new(value) })
78 }
79 }
80
81 impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83 match self.untracked_get() {
84 Some(val) => write!(f, "TyIVar({:?})", val),
85 None => f.write_str("TyIVar(<unfulfilled>)")
86 }
87 }
88 }