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 hir
::def_id
::DefId
;
16 use rustc_data_structures
::ivar
;
19 use std
::marker
::PhantomData
;
20 use core
::nonzero
::NonZero
;
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.
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
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!
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
>>);
41 impl<'tcx
, 'lt
> TyIVar
<'tcx
, 'lt
> {
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
)
50 pub fn get(&self, dep_node
: DepNode
<DefId
>) -> Option
<Ty
<'tcx
>> {
51 tls
::with(|tcx
| tcx
.dep_graph
.read(dep_node
));
55 /// Reads the ivar without registered a dep-graph read. Use with
58 pub fn untracked_get(&self) -> Option
<Ty
<'tcx
>> {
61 // valid because of invariant (A)
62 Some(v
) => Some(unsafe { &*(*v as *const TyS<'tcx>) }
)
67 pub fn unwrap(&self, dep_node
: DepNode
<DefId
>) -> Ty
<'tcx
> {
68 self.get(dep_node
).unwrap()
71 pub fn fulfill(&self, dep_node
: DepNode
<DefId
>, value
: Ty
<'lt
>) {
72 tls
::with(|tcx
| tcx
.dep_graph
.write(dep_node
));
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) }
)
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>)")