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
));
56 fn untracked_get(&self) -> Option
<Ty
<'tcx
>> {
59 // valid because of invariant (A)
60 Some(v
) => Some(unsafe { &*(*v as *const TyS<'tcx>) }
)
65 pub fn unwrap(&self, dep_node
: DepNode
<DefId
>) -> Ty
<'tcx
> {
66 self.get(dep_node
).unwrap()
69 pub fn fulfill(&self, dep_node
: DepNode
<DefId
>, value
: Ty
<'lt
>) {
70 tls
::with(|tcx
| tcx
.dep_graph
.write(dep_node
));
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) }
)
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>)")