X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc%2Fty%2Fcontext.rs;h=4e255edfe85637164a1c1d80c56cc60fd6e43999;hb=fff08cb04389497d254fb40948674cbbee402908;hp=ff218911ffb8197afca886679b666f392fca5cf2;hpb=74b359373c262506d88fa546c595551c7a4e4277;p=rust.git diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ff218911ffb..4e255edfe85 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -53,7 +53,7 @@ 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; @@ -79,37 +79,20 @@ use crate::hir; -pub struct AllArenas<'tcx> { - pub global: WorkerLocal>, +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, - - // references - generics: TypedArena, - trait_def: TypedArena, - adt_def: TypedArena, - steal_mir: TypedArena>>, - mir: TypedArena>, - tables: TypedArena>, - /// miri allocations - const_allocs: TypedArena, -} - type InternedSet<'tcx, T> = Lock, ()>>; pub struct CtxtInterners<'tcx> { @@ -154,7 +137,7 @@ fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> { /// Intern a type #[inline(never)] fn intern_ty( - local: &CtxtInterners<'tcx>, + local: &CtxtInterners<'gcx>, global: &CtxtInterners<'gcx>, st: TyKind<'tcx> ) -> Ty<'tcx> { @@ -179,6 +162,12 @@ fn intern_ty( &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 { @@ -1027,13 +1016,13 @@ pub struct FreeRegionInfo { /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] -pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> { +pub struct TyCtxt<'gcx: 'tcx, 'tcx> { gcx: &'gcx GlobalCtxt<'gcx>, - interners: &'tcx CtxtInterners<'tcx>, - dummy: PhantomData<&'a ()>, + interners: &'gcx CtxtInterners<'gcx>, + dummy: PhantomData<&'tcx ()>, } -impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> { +impl<'gcx> Deref for TyCtxt<'gcx, '_> { type Target = &'gcx GlobalCtxt<'gcx>; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -1043,8 +1032,9 @@ fn deref(&self) -> &Self::Target { pub struct GlobalCtxt<'tcx> { pub arena: WorkerLocal>, - global_arenas: &'tcx WorkerLocal>, + global_interners: CtxtInterners<'tcx>, + local_interners: CtxtInterners<'tcx>, cstore: &'tcx CrateStoreDyn, @@ -1081,11 +1071,6 @@ pub struct GlobalCtxt<'tcx> { 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>, - maybe_unused_trait_imports: FxHashSet, maybe_unused_extern_crates: Vec<(DefId, Span)>, /// A map of glob use to a set of names it actually imports. Currently only @@ -1134,10 +1119,10 @@ pub struct GlobalCtxt<'tcx> { output_filenames: Arc, } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { +impl<'gcx, 'tcx> TyCtxt<'gcx, 'tcx> { /// Gets the global `TyCtxt`. #[inline] - pub fn global_tcx(self) -> TyCtxt<'gcx, 'gcx, 'gcx> { + pub fn global_tcx(self) -> TyCtxt<'gcx, 'gcx> { TyCtxt { gcx: self.gcx, interners: &self.gcx.global_interners, @@ -1146,28 +1131,12 @@ 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> { - 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, @@ -1177,32 +1146,32 @@ 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) }) } @@ -1250,7 +1219,7 @@ pub fn create_global_ctxt( 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>, @@ -1262,6 +1231,7 @@ pub fn create_global_ctxt( 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, @@ -1319,8 +1289,8 @@ pub fn create_global_ctxt( 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, @@ -1333,12 +1303,6 @@ pub fn create_global_ctxt( }).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() @@ -1505,7 +1469,7 @@ pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc { } #[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, @@ -1702,7 +1666,7 @@ pub fn has_strict_asm_symbol_naming(&self) -> bool { } } -impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { +impl<'tcx> TyCtxt<'tcx, 'tcx> { pub fn encode_metadata(self) -> EncodedMetadata { @@ -1714,20 +1678,14 @@ impl<'gcx> GlobalCtxt<'gcx> { /// Call the closure with a local `TyCtxt` using the given arena. /// `interners` is a slot passed so we can create a CtxtInterners /// with the same lifetime as `arena`. - pub fn enter_local<'tcx, F, R>( - &'gcx self, - arena: &'tcx SyncDroplessArena, - interners: &'tcx mut Option>, - f: F - ) -> R + pub fn enter_local<'tcx, F, R>(&'gcx self, f: F) -> R where - F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R, + F: FnOnce(TyCtxt<'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| { @@ -1745,67 +1703,67 @@ pub fn enter_local<'tcx, F, R>( } } -/// 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; + fn lift_to_tcx<'gcx>(&self, tcx: TyCtxt<'gcx, 'tcx>) -> Option; } macro_rules! nop_lift { ($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 { - 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()) - } else { - None + type Lifted = $lifted; + fn lift_to_tcx<'gcx>(&self, tcx: TyCtxt<'gcx, 'tcx>) -> Option { + 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()) + } else { + None + } + } } - } - } }; } macro_rules! nop_list_lift { ($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 { - if self.is_empty() { - 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()) - } else { - None + type Lifted = &'tcx List<$lifted>; + fn lift_to_tcx<'gcx>(&self, tcx: TyCtxt<'gcx, 'tcx>) -> Option { + if self.is_empty() { + 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()) + } else { + None + } + } } - } - } }; } @@ -1854,7 +1812,7 @@ pub mod tls { pub struct ImplicitCtxt<'a, 'gcx: 'tcx, 'tcx> { /// The current TyCtxt. Initially created by `enter_global` and updated /// by `enter_local` with a new local interner - pub tcx: TyCtxt<'tcx, 'gcx, 'tcx>, + pub tcx: TyCtxt<'gcx, 'tcx>, /// The current query job, if any. This is updated by JobOwner::start in /// ty::query::plumbing when executing a query @@ -1980,7 +1938,8 @@ pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx /// This happens once per rustc session and TyCtxts only exists /// inside the `f` function. pub fn enter_global<'gcx, F, R>(gcx: &'gcx GlobalCtxt<'gcx>, f: F) -> R - where F: FnOnce(TyCtxt<'gcx, 'gcx, 'gcx>) -> R + where + F: FnOnce(TyCtxt<'gcx, 'gcx>) -> R, { // Update GCX_PTR to indicate there's a GlobalCtxt available GCX_PTR.with(|lock| { @@ -2017,7 +1976,8 @@ pub fn enter_global<'gcx, F, R>(gcx: &'gcx GlobalCtxt<'gcx>, f: F) -> R /// 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: F) -> R - where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R + where + F: for<'gcx, 'tcx> FnOnce(TyCtxt<'gcx, 'tcx>) -> R, { let gcx = GCX_PTR.with(|lock| *lock.lock()); assert!(gcx != 0); @@ -2069,8 +2029,9 @@ pub fn with_context(f: F) -> R /// 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 - where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R + pub fn with_related_context<'gcx, 'tcx1, F, R>(tcx: TyCtxt<'gcx, 'tcx1>, f: F) -> R + where + F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R, { with_context(|context| { unsafe { @@ -2087,8 +2048,9 @@ pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, /// 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 - where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R + pub fn with_fully_related_context<'gcx, 'tcx, F, R>(tcx: TyCtxt<'gcx, 'tcx>, f: F) -> R + where + F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R, { with_context(|context| { unsafe { @@ -2104,7 +2066,8 @@ pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 't /// Panics if there is no ImplicitCtxt available #[inline] pub fn with(f: F) -> R - where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R + where + F: for<'gcx, 'tcx> FnOnce(TyCtxt<'gcx, 'tcx>) -> R, { with_context(|context| f(context.tcx)) } @@ -2113,7 +2076,8 @@ pub fn with(f: F) -> R /// The closure is passed None if there is no ImplicitCtxt available #[inline] pub fn with_opt(f: F) -> R - where F: for<'a, 'gcx, 'tcx> FnOnce(Option>) -> R + where + F: for<'gcx, 'tcx> FnOnce(Option>) -> R, { with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx))) } @@ -2137,7 +2101,7 @@ struct DebugStat { all_infer: usize, } - pub fn go(tcx: TyCtxt<'_, '_, '_>) { + pub fn go(tcx: TyCtxt<'_, '_>) { let mut total = DebugStat { total: 0, lt_infer: 0, @@ -2190,7 +2154,7 @@ pub fn go(tcx: TyCtxt<'_, '_, '_>) { }} } -impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { +impl<'tcx> TyCtxt<'tcx, 'tcx> { pub fn print_debug_stats(self) { sty_debug_print!( self, @@ -2329,10 +2293,21 @@ macro_rules! intern_method { $alloc_method:expr, $alloc_to_key:expr, $keep_in_local_tcx:expr) -> $ty:ty) => { - impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { + impl<'gcx, $lt_tcx> TyCtxt<'gcx, $lt_tcx> { 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. @@ -2346,18 +2321,11 @@ pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { 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 } } @@ -2435,7 +2403,7 @@ macro_rules! slice_interners { ) -> List } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { +impl<'gcx, 'tcx> TyCtxt<'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. @@ -3059,7 +3027,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { 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) };