-// ignore-tidy-filelength
-
//! Type context book-keeping.
use crate::arena::Arena;
use std::iter;
use std::sync::mpsc;
use std::sync::Arc;
-use std::marker::PhantomData;
use rustc_target::spec::abi;
use rustc_macros::HashStable;
use syntax::ast;
pub struct AllArenas {
pub interner: SyncDroplessArena,
- pub local_interner: SyncDroplessArena,
}
impl AllArenas {
pub fn new() -> Self {
AllArenas {
interner: SyncDroplessArena::default(),
- local_interner: SyncDroplessArena::default(),
}
}
}
/// Intern a type
#[inline(never)]
- fn intern_ty(
- local: &CtxtInterners<'tcx>,
- global: &CtxtInterners<'tcx>,
- st: TyKind<'tcx>,
+ fn intern_ty(&self,
+ st: TyKind<'tcx>
) -> Ty<'tcx> {
- let flags = super::flags::FlagComputation::for_sty(&st);
-
- // HACK(eddyb) Depend on flags being accurate to
- // determine that all contents are in the global tcx.
- // See comments on Lift for why we can't use that.
- if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
- local.type_.borrow_mut().intern(st, |st| {
- let ty_struct = TyS {
- sty: st,
- flags: flags.flags,
- outer_exclusive_binder: flags.outer_exclusive_binder,
- };
+ self.type_.borrow_mut().intern(st, |st| {
+ let flags = super::flags::FlagComputation::for_sty(&st);
- // Make sure we don't end up with inference
- // types/regions in the global interner
- if ptr_eq(local, global) {
- bug!("Attempted to intern `{:?}` which contains \
- inference types/regions in the global type context",
- &ty_struct);
- }
-
- // This is safe because all the types the ty_struct can point to
- // already is in the local arena or the global arena
- let ty_struct: TyS<'tcx> = unsafe {
- mem::transmute(ty_struct)
- };
-
- Interned(local.arena.alloc(ty_struct))
- }).0
- } else {
- global.type_.borrow_mut().intern(st, |st| {
- let ty_struct = TyS {
- sty: st,
- flags: flags.flags,
- outer_exclusive_binder: flags.outer_exclusive_binder,
- };
+ let ty_struct = TyS {
+ sty: st,
+ flags: flags.flags,
+ outer_exclusive_binder: flags.outer_exclusive_binder,
+ };
- // This is safe because all the types the ty_struct can point to
- // already is in the global arena
- let ty_struct: TyS<'tcx> = unsafe {
- mem::transmute(ty_struct)
- };
- Interned(global.arena.alloc(ty_struct))
- }).0
- }
+ Interned(self.arena.alloc(ty_struct))
+ }).0
}
}
impl<'tcx> CommonTypes<'tcx> {
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
- let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
+ let mk = |sty| interners.intern_ty(sty);
CommonTypes {
unit: mk(Tuple(List::empty())),
#[derive(Copy, Clone)]
pub struct TyCtxt<'tcx> {
gcx: &'tcx GlobalCtxt<'tcx>,
- interners: &'tcx CtxtInterners<'tcx>,
- dummy: PhantomData<&'tcx ()>,
}
impl<'tcx> Deref for TyCtxt<'tcx> {
pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>,
- global_interners: CtxtInterners<'tcx>,
- local_interners: CtxtInterners<'tcx>,
+ interners: CtxtInterners<'tcx>,
cstore: &'tcx CrateStoreDyn,
pub fn global_tcx(self) -> TyCtxt<'tcx> {
TyCtxt {
gcx: self.gcx,
- interners: &self.gcx.global_interners,
- dummy: PhantomData,
}
}
value.lift_to_tcx(self.global_tcx())
}
- /// Returns `true` if self is the same as self.global_tcx().
- fn is_global(self) -> bool {
- ptr_eq(self.interners, &self.global_interners)
- }
-
/// Creates a type context and call the closure with a `TyCtxt` reference
/// to the context. The closure enforces that the type context and any interned
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
s.fatal(&err);
});
let interners = CtxtInterners::new(&arenas.interner);
- let local_interners = CtxtInterners::new(&arenas.local_interner);
let common = Common {
empty_predicates: ty::GenericPredicates {
parent: None,
sess: s,
cstore,
arena: WorkerLocal::new(|_| Arena::default()),
- global_interners: interners,
- local_interners: local_interners,
+ interners,
dep_graph,
common,
types: common_types,
{
let tcx = TyCtxt {
gcx: self,
- interners: &self.local_interners,
- dummy: PhantomData,
};
ty::tls::with_related_context(tcx.global_tcx(), |icx| {
let new_icx = ty::tls::ImplicitCtxt {
type Lifted = $lifted;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
+ Some(unsafe { mem::transmute(*self) })
} else {
None
}
return Some(List::empty());
}
if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
+ Some(unsafe { mem::transmute(*self) })
} else {
None
}
use std::fmt;
use std::mem;
- use std::marker::PhantomData;
use syntax_pos;
use crate::ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
let tcx = TyCtxt {
gcx,
- interners: &gcx.global_interners,
- dummy: PhantomData,
};
let icx = ImplicitCtxt {
tcx,
let gcx = &*(gcx as *const GlobalCtxt<'_>);
let tcx = TyCtxt {
gcx,
- interners: &gcx.global_interners,
- dummy: PhantomData,
};
let icx = ImplicitCtxt {
query: None,
})
}
- /// Allows access to the current ImplicitCtxt whose tcx field has the same global
- /// interner and local interner as the tcx argument passed in. This means the closure
- /// is given an ImplicitCtxt with the same 'tcx and 'tcx lifetimes as the TyCtxt passed in.
- /// This will panic if you pass it a TyCtxt which has a different global interner or
- /// a different local interner from the current ImplicitCtxt's tcx field.
- #[inline]
- pub fn with_fully_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
- where
- F: for<'b> FnOnce(&ImplicitCtxt<'b, 'tcx>) -> R,
- {
- with_context(|context| {
- unsafe {
- assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
- assert!(ptr_eq(context.tcx.interners, tcx.interners));
- let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
- f(context)
- }
- })
- }
-
/// Allows access to the TyCtxt in the current ImplicitCtxt.
/// Panics if there is no ImplicitCtxt available
#[inline]
macro_rules! intern_method {
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
$alloc_method:expr,
- $alloc_to_key:expr,
- $keep_in_local_tcx:expr) -> $ty:ty) => {
+ $alloc_to_key:expr) -> $ty:ty) => {
impl<$lt_tcx> TyCtxt<$lt_tcx> {
pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
let key = ($alloc_to_key)(&v);
- // HACK(eddyb) Depend on flags being accurate to
- // determine that all contents are in the global tcx.
- // See comments on Lift for why we can't use that.
- if ($keep_in_local_tcx)(&v) {
- self.interners.$name.borrow_mut().intern_ref(key, || {
- // Make sure we don't end up with inference
- // types/regions in the global tcx.
- if self.is_global() {
- bug!("Attempted to intern `{:?}` which contains \
- inference types/regions in the global type context",
- v);
- }
+ self.interners.$name.borrow_mut().intern_ref(key, || {
+ Interned($alloc_method(&self.interners.arena, v))
- Interned($alloc_method(&self.interners.arena, v))
- }).0
- } else {
- self.global_interners.$name.borrow_mut().intern_ref(key, || {
- Interned($alloc_method(&self.global_interners.arena, v))
- }).0
- }
+ }).0
}
}
}
}
macro_rules! direct_interners {
- ($lt_tcx:tt, $($name:ident: $method:ident($keep_in_local_tcx:expr) -> $ty:ty),+) => {
+ ($lt_tcx:tt, $($name:ident: $method:ident($ty:ty)),+) => {
$(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
$lt_tcx,
$name: $method($ty,
|a: &$lt_tcx SyncDroplessArena, v| -> &$lt_tcx $ty { a.alloc(v) },
- |x| x,
- $keep_in_local_tcx) -> $ty);)+
+ |x| x) -> $ty);)+
}
}
}
direct_interners!('tcx,
- region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
- goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
- const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
+ region: mk_region(RegionKind),
+ goal: mk_goal(GoalKind<'tcx>),
+ const_: mk_const(Const<'tcx>)
);
macro_rules! slice_interners {
$(intern_method!( 'tcx, $field: $method(
&[$ty],
|a, v| List::from_arena(a, v),
- Deref::deref,
- |xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty>);)+
+ Deref::deref) -> List<$ty>);)+
);
}
canonical_var_infos: _intern_canonical_var_infos(
&[CanonicalVarInfo],
|a, v| List::from_arena(a, v),
- Deref::deref,
- |_xs: &[CanonicalVarInfo]| -> bool { false }
+ Deref::deref
) -> List<CanonicalVarInfo>
}
#[inline]
pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
- CtxtInterners::intern_ty(&self.interners, &self.global_interners, st)
+ self.interners.intern_ty(st)
}
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {