use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
StableHasher, StableHasherResult,
StableVec};
-use arena::{TypedArena, SyncDroplessArena};
+use arena::SyncDroplessArena;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
use std::any::Any;
use crate::hir;
-pub struct AllArenas<'tcx> {
- pub global: WorkerLocal<GlobalArenas<'tcx>>,
+pub struct AllArenas {
pub interner: SyncDroplessArena,
+ pub local_interner: SyncDroplessArena,
}
-impl<'tcx> AllArenas<'tcx> {
+impl AllArenas {
pub fn new() -> Self {
AllArenas {
- global: WorkerLocal::new(|_| GlobalArenas::default()),
interner: SyncDroplessArena::default(),
+ local_interner: SyncDroplessArena::default(),
}
}
}
-/// Internal storage
-#[derive(Default)]
-pub struct GlobalArenas<'tcx> {
- // internings
- layout: TypedArena<LayoutDetails>,
-
- // references
- generics: TypedArena<ty::Generics>,
- trait_def: TypedArena<ty::TraitDef>,
- adt_def: TypedArena<ty::AdtDef>,
- steal_mir: TypedArena<Steal<Body<'tcx>>>,
- mir: TypedArena<Body<'tcx>>,
- tables: TypedArena<ty::TypeckTables<'tcx>>,
- /// miri allocations
- const_allocs: TypedArena<interpret::Allocation>,
-}
-
type InternedSet<'tcx, T> = Lock<FxHashMap<Interned<'tcx, T>, ()>>;
pub struct CtxtInterners<'tcx> {
/// Intern a type
#[inline(never)]
fn intern_ty(
- local: &CtxtInterners<'tcx>,
+ local: &CtxtInterners<'gcx>,
global: &CtxtInterners<'gcx>,
st: TyKind<'tcx>
) -> Ty<'tcx> {
&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<'gcx> = unsafe {
+ mem::transmute(ty_struct)
+ };
+
Interned(local.arena.alloc(ty_struct))
}).0
} else {
#[derive(Copy, Clone)]
pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> {
gcx: &'gcx GlobalCtxt<'gcx>,
- interners: &'tcx CtxtInterners<'tcx>,
- dummy: PhantomData<&'a ()>,
+ interners: &'gcx CtxtInterners<'gcx>,
+ dummy: PhantomData<(&'a (), &'tcx ())>,
}
impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> {
pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>,
- global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
+
global_interners: CtxtInterners<'tcx>,
+ local_interners: CtxtInterners<'tcx>,
cstore: &'tcx CrateStoreDyn,
pub queries: query::Queries<'tcx>,
- // Records the captured variables referenced by every closure
- // expression. Do not track deps for this, just recompute it from
- // scratch every time.
- upvars: FxHashMap<DefId, Vec<hir::Upvar>>,
-
maybe_unused_trait_imports: FxHashSet<DefId>,
maybe_unused_extern_crates: Vec<(DefId, Span)>,
/// A map of glob use to a set of names it actually imports. Currently only
output_filenames: Arc<OutputFilenames>,
}
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+impl<'gcx, 'tcx> TyCtxt<'tcx, 'gcx, 'tcx> {
/// Gets the global `TyCtxt`.
#[inline]
pub fn global_tcx(self) -> TyCtxt<'gcx, 'gcx, 'gcx> {
}
#[inline(always)]
- pub fn hir(self) -> &'a hir_map::Map<'gcx> {
+ pub fn hir(self) -> &'tcx hir_map::Map<'gcx> {
&self.hir_map
}
- pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
- self.global_arenas.generics.alloc(generics)
- }
-
pub fn alloc_steal_mir(self, mir: Body<'gcx>) -> &'gcx Steal<Body<'gcx>> {
- self.global_arenas.steal_mir.alloc(Steal::new(mir))
- }
-
- pub fn alloc_mir(self, mir: Body<'gcx>) -> &'gcx Body<'gcx> {
- self.global_arenas.mir.alloc(mir)
- }
-
- pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> {
- self.global_arenas.tables.alloc(tables)
- }
-
- pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
- self.global_arenas.trait_def.alloc(def)
+ self.arena.alloc(Steal::new(mir))
}
pub fn alloc_adt_def(self,
repr: ReprOptions)
-> &'gcx ty::AdtDef {
let def = ty::AdtDef::new(self, did, kind, variants, repr);
- self.global_arenas.adt_def.alloc(def)
+ self.arena.alloc(def)
}
pub fn intern_const_alloc(self, alloc: Allocation) -> &'gcx Allocation {
self.allocation_interner.borrow_mut().intern(alloc, |alloc| {
- self.global_arenas.const_allocs.alloc(alloc)
+ self.arena.alloc(alloc)
})
}
/// Allocates a byte or string literal for `mir::interpret`, read-only
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
// create an allocation that just contains these bytes
- let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ());
+ let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
let alloc = self.intern_const_alloc(alloc);
- self.alloc_map.lock().allocate(alloc)
+ self.alloc_map.lock().create_memory_alloc(alloc)
}
pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
self.stability_interner.borrow_mut().intern(stab, |stab| {
- self.global_interners.arena.alloc(stab)
+ self.arena.alloc(stab)
})
}
pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
self.layout_interner.borrow_mut().intern(layout, |layout| {
- self.global_arenas.layout.alloc(layout)
+ self.arena.alloc(layout)
})
}
cstore: &'tcx CrateStoreDyn,
local_providers: ty::query::Providers<'tcx>,
extern_providers: ty::query::Providers<'tcx>,
- arenas: &'tcx AllArenas<'tcx>,
+ arenas: &'tcx AllArenas,
resolutions: ty::Resolutions,
hir: hir_map::Map<'tcx>,
on_disk_query_result_cache: query::OnDiskCache<'tcx>,
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_arenas: &arenas.global,
global_interners: interners,
+ local_interners: local_interners,
dep_graph,
common,
types: common_types,
}).collect();
(k, exports)
}).collect(),
- upvars: resolutions.upvars.into_iter().map(|(k, v)| {
- let vars: Vec<_> = v.into_iter().map(|e| {
- e.map_id(|id| hir.node_to_hir_id(id))
- }).collect();
- (hir.local_def_id(k), vars)
- }).collect(),
maybe_unused_trait_imports:
resolutions.maybe_unused_trait_imports
.into_iter()
}
#[inline(always)]
- pub fn create_stable_hashing_context(self) -> StableHashingContext<'a> {
+ pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
let krate = self.gcx.hir_map.forest.untracked_krate();
StableHashingContext::new(self.sess,
}
}
-impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+impl<'tcx> TyCtxt<'tcx, 'tcx, 'tcx> {
pub fn encode_metadata(self)
-> EncodedMetadata
{
/// with the same lifetime as `arena`.
pub fn enter_local<'tcx, F, R>(
&'gcx self,
- arena: &'tcx SyncDroplessArena,
- interners: &'tcx mut Option<CtxtInterners<'tcx>>,
f: F
) -> R
where
F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R,
'gcx: 'tcx,
{
- *interners = Some(CtxtInterners::new(&arena));
let tcx = TyCtxt {
gcx: self,
- interners: interners.as_ref().unwrap(),
+ interners: &self.local_interners,
dummy: PhantomData,
};
ty::tls::with_related_context(tcx.global_tcx(), |icx| {
}
}
-/// A trait implemented for all X<'a> types which can be safely and
-/// efficiently converted to X<'tcx> as long as they are part of the
-/// provided TyCtxt<'tcx>.
-/// This can be done, for example, for Ty<'tcx> or SubstsRef<'tcx>
+/// A trait implemented for all `X<'a>` types that can be safely and
+/// efficiently converted to `X<'tcx>` as long as they are part of the
+/// provided `TyCtxt<'tcx>`.
+/// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>`
/// by looking them up in their respective interners.
///
/// However, this is still not the best implementation as it does
/// need to compare the components, even for interned values.
-/// It would be more efficient if TypedArena provided a way to
+/// It would be more efficient if `TypedArena` provided a way to
/// determine whether the address is in the allocated range.
///
/// None is returned if the value or one of the components is not part
/// of the provided context.
-/// For Ty, None can be returned if either the type interner doesn't
-/// contain the TyKind key or if the address of the interned
+/// For `Ty`, `None` can be returned if either the type interner doesn't
+/// contain the `TyKind` key or if the address of the interned
/// pointer differs. The latter case is possible if a primitive type,
/// e.g., `()` or `u8`, was interned in a different context.
pub trait Lift<'tcx>: fmt::Debug {
type Lifted: fmt::Debug + 'tcx;
- fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>;
+ fn lift_to_tcx<'gcx>(&self, tcx: TyCtxt<'tcx, 'gcx, 'tcx>) -> Option<Self::Lifted>;
}
($ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for $ty {
type Lifted = $lifted;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ fn lift_to_tcx<'gcx>(&self, tcx: TyCtxt<'tcx, 'gcx, 'tcx>) -> Option<Self::Lifted> {
if tcx.interners.arena.in_arena(*self as *const _) {
return Some(unsafe { mem::transmute(*self) });
}
($ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
type Lifted = &'tcx List<$lifted>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ fn lift_to_tcx<'gcx>(&self, tcx: TyCtxt<'tcx, 'gcx, 'tcx>) -> Option<Self::Lifted> {
if self.is_empty() {
return Some(List::empty());
}
/// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local.
/// This is used in the deadlock handler.
pub unsafe fn with_global<F, R>(f: F) -> R
- where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+ where F: for<'gcx, 'tcx> FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R
{
let gcx = GCX_PTR.with(|lock| *lock.lock());
assert!(gcx != 0);
/// This will panic if you pass it a TyCtxt which has a different global interner from
/// the current ImplicitCtxt's tcx field.
#[inline]
- pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R
+ pub fn with_related_context<'gcx, 'tcx1, F, R>(tcx: TyCtxt<'tcx1, 'gcx, 'tcx1>, f: F) -> R
where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R
{
with_context(|context| {
/// 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<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R
+ pub fn with_fully_related_context<'gcx, 'tcx, F, R>(tcx: TyCtxt<'tcx, 'gcx, 'tcx>, f: F) -> R
where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R
{
with_context(|context| {
/// Panics if there is no ImplicitCtxt available
#[inline]
pub fn with<F, R>(f: F) -> R
- where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+ where F: for<'gcx, 'tcx> FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R
{
with_context(|context| f(context.tcx))
}
/// The closure is passed None if there is no ImplicitCtxt available
#[inline]
pub fn with_opt<F, R>(f: F) -> R
- where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R
+ where F: for<'gcx, 'tcx> FnOnce(Option<TyCtxt<'tcx, 'gcx, 'tcx>>) -> R
{
with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
}
}}
}
-impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+impl<'tcx> TyCtxt<'tcx, 'tcx, 'tcx> {
pub fn print_debug_stats(self) {
sty_debug_print!(
self,
pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
let key = ($alloc_to_key)(&v);
+ let alloc = |v, interners: &'gcx CtxtInterners<'gcx>| {
+ // This transmutes $alloc<'tcx> to $alloc<'gcx>
+ let v = unsafe {
+ mem::transmute(v)
+ };
+ let i: &$lt_tcx $ty = $alloc_method(&interners.arena, v);
+ // Cast to 'gcx
+ let i = unsafe { mem::transmute(i) };
+ Interned(i)
+ };
+
// 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.
v);
}
- Interned($alloc_method(&self.interners.arena, v))
+ alloc(v, &self.interners)
}).0
} else {
self.global_interners.$name.borrow_mut().intern_ref(key, || {
- // This transmutes $alloc<'tcx> to $alloc<'gcx>
- let v = unsafe {
- mem::transmute(v)
- };
- let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
- // Cast to 'gcx
- let i = unsafe { mem::transmute(i) };
- Interned(i)
+ alloc(v, &self.global_interners)
}).0
}
}
) -> List<CanonicalVarInfo>
}
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+impl<'gcx, 'tcx> TyCtxt<'tcx, 'gcx, 'tcx> {
/// Given a `fn` type, returns an equivalent `unsafe fn` type;
/// that is, a `fn` type that is equivalent in every way for being
/// unsafe.
assert_eq!(id, LOCAL_CRATE);
tcx.arena.alloc(middle::lang_items::collect(tcx))
};
- providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id).map(|v| &v[..]);
providers.maybe_unused_trait_import = |tcx, id| {
tcx.maybe_unused_trait_imports.contains(&id)
};