diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 955cab1d93f76..bff5f4b8dd43b 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -35,7 +35,8 @@ extern crate alloc; extern crate rustc_data_structures; -use rustc_data_structures::sync::MTLock; +use rustc_data_structures::defer_deallocs::DeferDeallocs; +use rustc_data_structures::sync::{MTLock, WorkerLocal}; use std::cell::{Cell, RefCell}; use std::cmp; @@ -44,7 +45,6 @@ use std::marker::{PhantomData, Send}; use std::mem; use std::ptr; use std::slice; - use alloc::raw_vec::RawVec; /// An arena that can hold objects of only one type. @@ -132,30 +132,54 @@ impl TypedArena { /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] pub fn alloc(&self, object: T) -> &mut T { - if self.ptr == self.end { - self.grow(1) - } + // Zero sized path + if mem::size_of::() == 0 { + if self.ptr == self.end { + self.grow(1) + } - unsafe { - if mem::size_of::() == 0 { + unsafe { self.ptr .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T); let ptr = mem::align_of::() as *mut T; // Don't drop the object. This `write` is equivalent to `forget`. ptr::write(ptr, object); - &mut *ptr + return &mut *ptr; + } + } + + let ptr = self.ptr.get(); + + unsafe { + if std::intrinsics::unlikely(ptr == self.end.get()) { + self.grow_and_alloc(object) } else { - let ptr = self.ptr.get(); - // Advance the pointer. - self.ptr.set(self.ptr.get().offset(1)); - // Write into uninitialized memory. - ptr::write(ptr, object); - &mut *ptr + self.alloc_unchecked(ptr, object) } } } + #[inline(always)] + unsafe fn alloc_unchecked(&self, ptr: *mut T, object: T) -> &mut T { + // Advance the pointer. + self.ptr.set(ptr.offset(1)); + // Write into uninitialized memory. + ptr::write(ptr, object); + &mut *ptr + } + + #[inline(never)] + #[cold] + fn grow_and_alloc(&self, object: T) -> &mut T { + // We move the object in this function so if it has a destructor + // the fast path need not have an unwind handler to destroy it + self.grow(1); + unsafe { + self.alloc_unchecked(self.ptr.get(), object) + } + } + /// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable /// reference to it. Will panic if passed a zero-sized types. /// @@ -174,7 +198,7 @@ impl TypedArena { let available_capacity_bytes = self.end.get() as usize - self.ptr.get() as usize; let at_least_bytes = slice.len() * mem::size_of::(); if available_capacity_bytes < at_least_bytes { - self.grow(slice.len()); + self.grow_slice(slice.len()); } unsafe { @@ -186,9 +210,14 @@ impl TypedArena { } } - /// Grows the arena. #[inline(never)] #[cold] + fn grow_slice(&self, n: usize) { + self.grow(n) + } + + /// Grows the arena. + #[inline(always)] fn grow(&self, n: usize) { unsafe { let mut chunks = self.chunks.borrow_mut(); @@ -283,6 +312,22 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena { unsafe impl Send for TypedArena {} +type BackingType = usize; +const BLOCK_SIZE: usize = std::mem::size_of::(); + +#[inline(always)] +fn required_backing_types(bytes: usize) -> usize { + assert!(BLOCK_SIZE.is_power_of_two()); + // FIXME: This addition could overflow + (bytes + BLOCK_SIZE - 1) / BLOCK_SIZE +} + +#[inline(always)] +fn align(val: usize, align: usize) -> usize { + assert!(align.is_power_of_two()); + (val + align - 1) & !(align - 1) +} + pub struct DroplessArena { /// A pointer to the next object to be allocated. ptr: Cell<*mut u8>, @@ -292,7 +337,42 @@ pub struct DroplessArena { end: Cell<*mut u8>, /// A vector of arena chunks. - chunks: RefCell>>, + chunks: RefCell>>, +} + +#[no_mangle] +pub fn tatest1(a: &TypedArena) -> &usize { + a.alloc(64usize) +} + +#[no_mangle] +pub fn atest1(a: &DroplessArena) -> &usize { + a.alloc(64usize) +} + +#[no_mangle] +pub fn atest2(a: &SyncDroplessArena, b: Box) -> &Box { + a.promote(b) +} + +#[no_mangle] +pub fn atest6(a: &SyncDroplessArena, b: usize) -> &usize { + a.promote(b) +} + +#[no_mangle] +pub fn atest3(a: &DroplessArena) { + a.align(8); +} + +#[no_mangle] +pub fn atest4(a: &DroplessArena) { + a.align(16); +} + +#[no_mangle] +pub fn atest5(a: &DroplessArena) { + a.align(4); } unsafe impl Send for DroplessArena {} @@ -310,7 +390,7 @@ impl Default for DroplessArena { impl DroplessArena { pub fn in_arena(&self, ptr: *const T) -> bool { - let ptr = ptr as *const u8 as *mut u8; + let ptr = ptr as *const u8 as *mut BackingType; for chunk in &*self.chunks.borrow() { if chunk.start() <= ptr && ptr < chunk.end() { return true; @@ -322,62 +402,93 @@ impl DroplessArena { #[inline] fn align(&self, align: usize) { + // FIXME: The addition of `align` could overflow, in which case final_address + // will be 0. Do we have any guarantee that our chunk won't end up as the final + // bytes in our memory space? let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1); self.ptr.set(final_address as *mut u8); - assert!(self.ptr <= self.end); + + // Aligning to the block_size cannot go outside our current chuck, just to its end + if align > BLOCK_SIZE { + // For larger alignments we have to check that we didn't go out of bounds + assert!(self.ptr <= self.end); + } } - #[inline(never)] - #[cold] fn grow(&self, needed_bytes: usize) { unsafe { + let needed_vals = required_backing_types(needed_bytes); let mut chunks = self.chunks.borrow_mut(); let (chunk, mut new_capacity); if let Some(last_chunk) = chunks.last_mut() { let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize; + let used_vals = required_backing_types(used_bytes); if last_chunk .storage - .reserve_in_place(used_bytes, needed_bytes) + .reserve_in_place(used_vals, needed_vals) { - self.end.set(last_chunk.end()); + self.end.set(last_chunk.end() as *mut u8); return; } else { new_capacity = last_chunk.storage.cap(); loop { new_capacity = new_capacity.checked_mul(2).unwrap(); - if new_capacity >= used_bytes + needed_bytes { + if new_capacity >= used_vals + needed_vals { break; } } } } else { - new_capacity = cmp::max(needed_bytes, PAGE); + new_capacity = cmp::max(needed_vals, required_backing_types(PAGE)); } - chunk = TypedArenaChunk::::new(new_capacity); - self.ptr.set(chunk.start()); - self.end.set(chunk.end()); + chunk = TypedArenaChunk::::new(new_capacity); + self.ptr.set(chunk.start() as *mut u8); + self.end.set(chunk.end() as *mut u8); chunks.push(chunk); } } + #[inline(never)] + #[cold] + fn grow_and_alloc_raw(&self, bytes: usize) -> &mut [u8] { + self.grow(bytes); + unsafe { + self.alloc_raw_unchecked(self.ptr.get(), bytes) + } + } + + #[inline(always)] + unsafe fn alloc_raw_unchecked(&self, start: *mut u8, bytes: usize) -> &mut [u8] { + // Tell LLVM that `start` is aligned to BLOCK_SIZE + std::intrinsics::assume(start as usize == align(start as usize, BLOCK_SIZE)); + + // Set the pointer past ourselves and align it + let end = start.offset(bytes as isize) as usize; + let end = align(end, BLOCK_SIZE) as *mut u8; + self.ptr.set(end); + + // Return the result + slice::from_raw_parts_mut(start, bytes) + } + #[inline] pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] { + // FIXME: Always align to 8 bytes here? Or usize alignment unsafe { assert!(bytes != 0); + assert!(align <= BLOCK_SIZE); + assert!(std::mem::align_of::() == std::mem::size_of::()); + // FIXME: Check that `bytes` fit in a isize - self.align(align); - - let future_end = intrinsics::arith_offset(self.ptr.get(), bytes as isize); - if (future_end as *mut u8) >= self.end.get() { - self.grow(bytes); - } - + // FIXME: arith_offset could overflow here. + // Find some way to guarantee this doesn't happen for small fixed size types let ptr = self.ptr.get(); - // Set the pointer past ourselves - self.ptr.set( - intrinsics::arith_offset(self.ptr.get(), bytes as isize) as *mut u8, - ); - slice::from_raw_parts_mut(ptr, bytes) + let future_end = intrinsics::arith_offset(ptr, bytes as isize); + if std::intrinsics::unlikely((future_end as *mut u8) >= self.end.get()) { + self.grow_and_alloc_raw(bytes) + } else { + self.alloc_raw_unchecked(ptr, bytes) + } } } @@ -452,12 +563,39 @@ impl SyncTypedArena { } } -#[derive(Default)] +struct DropType { + drop_fn: unsafe fn(*mut u8), + obj: *mut u8, +} + +unsafe fn drop_for_type(to_drop: *mut u8) { + std::ptr::drop_in_place(to_drop as *mut T) +} + +impl Drop for DropType { + fn drop(&mut self) { + unsafe { + (self.drop_fn)(self.obj) + } + } +} + pub struct SyncDroplessArena { + // Ordered so `deferred` gets dropped before the arena + // since its destructor can reference memory in the arena + deferred: WorkerLocal>, lock: MTLock, } impl SyncDroplessArena { + #[inline] + pub fn new() -> Self { + SyncDroplessArena { + lock: Default::default(), + deferred: WorkerLocal::new(|_| Default::default()), + } + } + #[inline(always)] pub fn in_arena(&self, ptr: *const T) -> bool { self.lock.lock().in_arena(ptr) @@ -483,6 +621,28 @@ impl SyncDroplessArena { // Extend the lifetime of the result since it's limited to the lock guard unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) } } + + #[inline] + pub fn promote(&self, object: T) -> &T { + let mem = self.alloc_raw(mem::size_of::(), mem::align_of::()) as *mut _ as *mut T; + let result = unsafe { + // Write into uninitialized memory. + ptr::write(mem, object); + &mut *mem + }; + // Record the destructor after doing the allocation as that may panic + // and would cause `object` destuctor to run twice if it was recorded before + self.deferred.alloc(DropType { + drop_fn: drop_for_type::, + obj: result as *mut T as *mut u8, + }); + result + } + + #[inline(always)] + pub fn promote_vec(&self, vec: Vec) -> &[T] { + &self.promote(vec)[..] + } } #[cfg(test)] diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 50922ee601daf..fd9eb68a4e559 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -230,6 +230,8 @@ pub struct Export { pub vis: ty::Visibility, } +impl_defer_dellocs_for_no_drop_type!([] Export); + impl CtorKind { pub fn from_ast(vdata: &ast::VariantData) -> CtorKind { match *vdata { diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 319d63f66c465..6e4447d6edbe5 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -35,6 +35,8 @@ pub enum CrateNum { Index(CrateId), } +impl_defer_dellocs_for_no_drop_type!([] CrateNum); + impl ::std::fmt::Debug for CrateNum { fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { match self { @@ -131,6 +133,8 @@ pub struct DefIndex(u32); /// thanks to `NodeCollector::new`. pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0); +impl_defer_dellocs_for_no_drop_type!([] DefIndex); + impl fmt::Debug for DefIndex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, @@ -223,6 +227,8 @@ pub struct DefId { pub index: DefIndex, } +impl_defer_dellocs_for_no_drop_type!([] DefId); + impl fmt::Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "DefId({}/{}:{}", @@ -271,6 +277,8 @@ impl serialize::UseSpecializedDecodable for DefId {} #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct LocalDefId(DefIndex); +impl_defer_dellocs_for_no_drop_type!([] LocalDefId); + impl LocalDefId { #[inline] pub fn from_def_id(def_id: DefId) -> LocalDefId { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1674320165e65..756da5bd38a3d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -85,6 +85,8 @@ pub struct HirId { pub local_id: ItemLocalId, } +impl_defer_dellocs_for_no_drop_type!([] HirId); + impl HirId { pub fn owner_def_id(self) -> DefId { DefId::local(self.owner) @@ -135,6 +137,8 @@ mod item_local_id_inner { } } +impl_defer_dellocs_for_no_drop_type!([] ItemLocalId); + pub use self::item_local_id_inner::ItemLocalId; /// The `HirId` corresponding to CRATE_NODE_ID and CRATE_DEF_INDEX @@ -1269,6 +1273,8 @@ pub struct BodyId { pub node_id: NodeId, } +impl_defer_dellocs_for_no_drop_type!([] BodyId); + /// The body of a function, closure, or constant value. In the case of /// a function, the body contains not only the function body itself /// (which is an expression), but also the argument patterns, since @@ -2379,6 +2385,8 @@ impl Freevar { } } +impl_defer_dellocs_for_no_drop_type!([] Freevar); + pub type FreevarMap = NodeMap>; pub type CaptureModeMap = NodeMap; @@ -2389,6 +2397,8 @@ pub struct TraitCandidate { pub import_id: Option, } +impl_defer_dellocs_for_no_drop_type!([] TraitCandidate); + // Trait method resolution pub type TraitMap = NodeMap>; diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e6a7c20f79379..09f60f746d595 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -847,16 +847,12 @@ impl_stable_hash_for!(struct ty::Destructor { did }); -impl_stable_hash_for!(struct ty::CrateVariancesMap { +impl_stable_hash_for!(struct ty::CrateVariancesMap<'tcx> { variances, - // This is just an irrelevant helper value. - empty_variance -> _, }); impl_stable_hash_for!(struct ty::CratePredicatesMap<'tcx> { predicates, - // This is just an irrelevant helper value. - empty_predicate -> _, }); impl_stable_hash_for!(struct ty::AssociatedItem { @@ -1235,6 +1231,15 @@ impl<'a, 'tcx> HashStable> for traits::Clause<'tcx> { } } +impl<'a, 'tcx, T: ?Sized> HashStable> for ty::util::Bx<'tcx, T> +where T: HashStable> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.0.hash_stable(hcx, hasher); + } +} + impl_stable_hash_for!(enum traits::QuantifierKind { Universal, Existential diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 6b0fa79b201fc..c199c372670a2 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -32,15 +32,15 @@ //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin}; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::sync::Lrc; use serialize::UseSpecializedDecodable; use smallvec::SmallVec; use std::ops::Index; use syntax::source_map::Span; use ty::fold::TypeFoldable; use ty::subst::Kind; -use ty::{self, BoundVar, Lift, List, Region, TyCtxt}; +use ty::{self, Bx, BoundVar, Lift, List, Region, TyCtxt}; mod canonicalizer; @@ -58,6 +58,13 @@ pub struct Canonical<'gcx, V> { pub value: V, } +unsafe impl<'gcx, V: DeferDeallocs> DeferDeallocs for Canonical<'gcx, V> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.max_universe.defer(deferred); + self.value.defer(deferred); + } +} + pub type CanonicalVarInfos<'gcx> = &'gcx List; impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {} @@ -76,6 +83,12 @@ pub struct CanonicalVarValues<'tcx> { pub var_values: IndexVec>, } +unsafe impl<'tcx> DeferDeallocs for CanonicalVarValues<'tcx> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.var_values.defer(deferred); + } +} + /// When we canonicalize a value to form a query, we wind up replacing /// various parts of it with canonical variables. This struct stores /// those replaced bits to remember for when we process the query @@ -192,10 +205,19 @@ pub struct QueryResponse<'tcx, R> { pub value: R, } +unsafe impl<'tcx, R: DeferDeallocs> DeferDeallocs for QueryResponse<'tcx, R> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.var_values.defer(deferred); + self.region_constraints.defer(deferred); + self.certainty.defer(deferred); + self.value.defer(deferred); + } +} + pub type Canonicalized<'gcx, V> = Canonical<'gcx, >::Lifted>; pub type CanonicalizedQueryResponse<'gcx, T> = - Lrc>::Lifted>>>; + Bx<'gcx, Canonical<'gcx, QueryResponse<'gcx, >::Lifted>>>; /// Indicates whether or not we were able to prove the query to be /// true. @@ -219,6 +241,8 @@ pub enum Certainty { Ambiguous, } +impl_defer_dellocs_for_no_drop_type!([] Certainty); + impl Certainty { pub fn is_proven(&self) -> bool { match self { diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 8d2b1d74c554b..58769c5c660f8 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -25,9 +25,9 @@ use infer::canonical::{ use infer::region_constraints::{Constraint, RegionConstraintData}; use infer::InferCtxtBuilder; use infer::{InferCtxt, InferOk, InferResult}; +use rustc_data_structures::defer_deallocs::DeferDeallocs; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::sync::Lrc; use std::fmt::Debug; use syntax_pos::DUMMY_SP; use traits::query::{Fallible, NoSolution}; @@ -63,6 +63,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> { where K: TypeFoldable<'tcx>, R: Debug + Lift<'gcx> + TypeFoldable<'tcx>, + >::Lifted: DeferDeallocs, { self.enter_with_canonical( DUMMY_SP, @@ -104,6 +105,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { ) -> Fallible> where T: Debug + Lift<'gcx> + TypeFoldable<'tcx>, + >::Lifted: DeferDeallocs, { let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?; let canonical_result = self.canonicalize_response(&query_response); @@ -113,7 +115,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { canonical_result ); - Ok(Lrc::new(canonical_result)) + Ok(self.tcx.bx(canonical_result)) } /// Helper for `make_canonicalized_query_response` that does diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index d8beae45b0ad4..baadf981bab06 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -478,7 +478,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { InferCtxtBuilder { global_tcx: self, - arena: SyncDroplessArena::default(), + arena: SyncDroplessArena::new(), fresh_tables: None, } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index cfb9f04c4c6d1..823cf6bf1f169 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -16,6 +16,7 @@ use ich::StableHashingContext; use lint::builtin; use lint::context::CheckLintNameResult; use lint::{self, Lint, LintId, Level, LintSource}; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; use session::Session; @@ -31,6 +32,13 @@ pub struct LintLevelSets { lint_cap: Level, } +unsafe impl DeferDeallocs for LintLevelSets { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.list.defer(deferred); + self.lint_cap.defer(deferred); + } +} + enum LintSet { CommandLine { // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which @@ -44,6 +52,15 @@ enum LintSet { }, } +unsafe impl DeferDeallocs for LintSet { + fn defer(&self, deferred: &mut DeferredDeallocs) { + match self { + LintSet::CommandLine { specs } | + LintSet::Node { specs, parent: _ } => specs.defer(deferred), + } + } +} + impl LintLevelSets { pub fn new(sess: &Session) -> LintLevelSets { let mut me = LintLevelSets { @@ -516,6 +533,13 @@ pub struct LintLevelMap { id_to_set: FxHashMap, } +unsafe impl DeferDeallocs for LintLevelMap { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.sets.defer(deferred); + self.id_to_set.defer(deferred); + } +} + impl LintLevelMap { /// If the `id` was previously registered with `register_id` when building /// this `LintLevelMap` this returns the corresponding lint level and source diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 4b878b862526b..15722204a60c1 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -31,7 +31,7 @@ pub use self::Level::*; pub use self::LintSource::*; -use rustc_data_structures::sync::{self, Lrc}; +use rustc_data_structures::sync; use errors::{DiagnosticBuilder, DiagnosticId}; use hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -48,7 +48,7 @@ use syntax::edition::Edition; use syntax::symbol::Symbol; use syntax::visit as ast_visit; use syntax_pos::Span; -use ty::TyCtxt; +use ty::{Bx, TyCtxt}; use ty::query::Providers; use util::nodemap::NodeMap; @@ -393,6 +393,8 @@ pub struct LintId { lint: &'static Lint, } +impl_defer_dellocs_for_no_drop_type!([] LintId); + impl PartialEq for LintId { fn eq(&self, other: &LintId) -> bool { ptr::eq(self.lint, other.lint) @@ -432,6 +434,8 @@ pub enum Level { Allow, Warn, Deny, Forbid, } +impl_defer_dellocs_for_no_drop_type!([] Level); + impl_stable_hash_for!(enum self::Level { Allow, Warn, @@ -482,6 +486,8 @@ impl_stable_hash_for!(enum self::LintSource { CommandLine(text) }); +impl_defer_dellocs_for_no_drop_type!([] LintSource); + pub type LevelSource = (Level, LintSource); pub mod builtin; @@ -636,7 +642,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session, } fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Lrc + -> Bx<'tcx, LintLevelMap> { assert_eq!(cnum, LOCAL_CRATE); let mut builder = LintLevelMapBuilder { @@ -649,7 +655,7 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) intravisit::walk_crate(builder, krate); }); - Lrc::new(builder.levels.build_map()) + tcx.bx(builder.levels.build_map()) } struct LintLevelMapBuilder<'a, 'tcx: 'a> { diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs index 633c584137806..843a342e37836 100644 --- a/src/librustc/middle/borrowck.rs +++ b/src/librustc/middle/borrowck.rs @@ -12,12 +12,15 @@ use ich::StableHashingContext; use hir::HirId; use util::nodemap::FxHashSet; +use rustc_data_structures::defer_deallocs::{DeferredDeallocs, DeferDeallocs}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] pub enum SignalledError { SawSomeError, NoErrorsSeen } +impl_defer_dellocs_for_no_drop_type!([] SignalledError); + impl Default for SignalledError { fn default() -> SignalledError { SignalledError::NoErrorsSeen @@ -32,6 +35,13 @@ pub struct BorrowCheckResult { pub signalled_any_error: SignalledError, } +unsafe impl DeferDeallocs for BorrowCheckResult { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.used_mut_nodes.defer(deferred); + self.signalled_any_error.defer(deferred); + } +} + impl<'a> HashStable> for BorrowCheckResult { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4720bb2954963..ee3a23e2cd5e3 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -36,6 +36,7 @@ use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::sync::{self, MetadataRef, Lrc}; pub use self::NativeLibraryKind::*; @@ -105,6 +106,8 @@ pub enum LinkagePreference { RequireStatic, } +impl_defer_dellocs_for_no_drop_type!([] LinkagePreference); + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum NativeLibraryKind { /// native static library (.a archive) @@ -132,6 +135,13 @@ pub struct ForeignModule { pub def_id: DefId, } +unsafe impl DeferDeallocs for ForeignModule { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.foreign_items.defer(deferred); + self.def_id.defer(deferred); + } +} + #[derive(Copy, Clone, Debug)] pub struct ExternCrate { pub src: ExternCrateSource, @@ -149,6 +159,8 @@ pub struct ExternCrate { pub direct: bool, } +impl_defer_dellocs_for_no_drop_type!([] ExternCrate); + #[derive(Copy, Clone, Debug)] pub enum ExternCrateSource { /// Crate is loaded by `extern crate`. @@ -272,8 +284,8 @@ pub fn used_crates(tcx: TyCtxt<'_, '_, '_>, prefer: LinkagePreference) Some((cnum, path)) }) .collect::>(); - let mut ordering = tcx.postorder_cnums(LOCAL_CRATE); - Lrc::make_mut(&mut ordering).reverse(); + let mut ordering = (*tcx.postorder_cnums(LOCAL_CRATE)).clone(); + ordering.reverse(); libs.sort_by_cached_key(|&(a, _)| { ordering.iter().position(|x| *x == a) }); diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index 44572a1977ab4..0c7339131779d 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -28,6 +28,8 @@ pub enum SymbolExportLevel { Rust, } +impl_defer_dellocs_for_no_drop_type!([] SymbolExportLevel); + impl_stable_hash_for!(enum self::SymbolExportLevel { C, Rust diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5b92bfe6ad3c4..f140366a9651d 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -27,7 +27,6 @@ use middle::region; use ty::{self, TyCtxt, adjustment}; use hir::{self, PatKind}; -use rustc_data_structures::sync::Lrc; use std::rc::Rc; use syntax::ast; use syntax::ptr::P; @@ -280,7 +279,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, - rvalue_promotable_map: Option>) + rvalue_promotable_map: Option<&'tcx ItemLocalSet>) -> Self { ExprUseVisitor { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index e7a8baf738395..579f911b321c6 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -21,6 +21,7 @@ pub use self::LangItem::*; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use hir::def_id::DefId; use hir::check_attr::Target; use ty::{self, TyCtxt}; @@ -55,6 +56,8 @@ impl LangItem { } } +impl_defer_dellocs_for_no_drop_type!([] LangItem); + pub struct LanguageItems { pub items: Vec>, pub missing: Vec, @@ -95,6 +98,13 @@ impl LanguageItems { )* } +unsafe impl DeferDeallocs for LanguageItems { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.items.defer(deferred); + self.missing.defer(deferred); + } +} + struct LanguageItemCollector<'a, 'tcx: 'a> { items: LanguageItems, tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 7d65d412e01d7..fe2564237fb29 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -14,6 +14,7 @@ // and `#[unstable (..)]`), but are not declared in one single location // (unlike lang features), which means we need to collect them instead. +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use ty::TyCtxt; use syntax::symbol::Symbol; use syntax::ast::{Attribute, MetaItem, MetaItemKind}; @@ -28,6 +29,13 @@ pub struct LibFeatures { pub unstable: FxHashSet, } +unsafe impl DeferDeallocs for LibFeatures { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.stable.defer(deferred); + self.unstable.defer(deferred); + } +} + impl LibFeatures { fn new() -> LibFeatures { LibFeatures { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index cadf0c42d228f..bb8785233c32a 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -87,7 +87,6 @@ use syntax_pos::Span; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; -use rustc_data_structures::sync::Lrc; use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; use util::nodemap::ItemLocalSet; @@ -300,7 +299,7 @@ pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub region_scope_tree: &'a region::ScopeTree, pub tables: &'a ty::TypeckTables<'tcx>, - rvalue_promotable_map: Option>, + rvalue_promotable_map: Option<&'tcx ItemLocalSet>, infcx: Option<&'a InferCtxt<'a, 'gcx, 'tcx>>, } @@ -410,7 +409,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, - rvalue_promotable_map: Option>) + rvalue_promotable_map: Option<&'tcx ItemLocalSet>) -> MemCategorizationContext<'a, 'tcx, 'tcx> { MemCategorizationContext { tcx, diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 880d428e7a580..8f8fb53199785 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -12,6 +12,7 @@ //! outside their scopes. This pass will also generate a set of exported items //! which are available for use externally when compiled as a library. +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use util::nodemap::{DefIdSet, FxHashMap}; use std::hash::Hash; @@ -34,12 +35,20 @@ pub enum AccessLevel { Public, } +impl_defer_dellocs_for_no_drop_type!([] AccessLevel); + // Accessibility levels for reachable HIR nodes #[derive(Clone)] pub struct AccessLevels { pub map: FxHashMap } +unsafe impl DeferDeallocs for AccessLevels { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.map.defer(deferred); + } +} + impl AccessLevels { pub fn is_reachable(&self, id: Id) -> bool { self.map.get(&id) >= Some(&AccessLevel::Reachable) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 35d1a4dd2cb7c..4c43fb35f09cf 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -22,7 +22,6 @@ use ty; use std::mem; use std::fmt; -use rustc_data_structures::sync::Lrc; use syntax::source_map; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; @@ -34,6 +33,7 @@ use hir::Node; use hir::def_id::DefId; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -106,6 +106,8 @@ pub struct Scope { pub data: ScopeData, } +impl_defer_dellocs_for_no_drop_type!([] Scope); + impl fmt::Debug for Scope { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.data { @@ -349,6 +351,18 @@ pub struct ScopeTree { body_expr_count: FxHashMap, } +unsafe impl DeferDeallocs for ScopeTree { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.parent_map.defer(deferred); + self.var_map.defer(deferred); + self.destruction_scopes.defer(deferred); + self.rvalue_scopes.defer(deferred); + self.closure_tree.defer(deferred); + self.yield_in_scope.defer(deferred); + self.body_expr_count.defer(deferred); + } +} + #[derive(Debug, Copy, Clone)] pub struct Context { /// the root of the current region tree. This is typically the id @@ -1329,7 +1343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { } fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc + -> &'tcx ScopeTree { let closure_base_def_id = tcx.closure_base_def_id(def_id); if closure_base_def_id != def_id { @@ -1371,7 +1385,7 @@ fn region_scope_tree<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ScopeTree::default() }; - Lrc::new(scope_tree) + tcx.promote(scope_tree) } pub fn provide(providers: &mut Providers<'_>) { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 07054ee99af76..de386686cddf4 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -19,11 +19,11 @@ use hir::def::Def; use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use hir::map::Map; use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, Node, ParamName}; -use ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; +use ty::{self, Bx, DefIdTree, GenericParamDefKind, TyCtxt}; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use errors::{Applicability, DiagnosticBuilder}; use rustc::lint; -use rustc_data_structures::sync::Lrc; use session::Session; use std::borrow::Cow; use std::cell::Cell; @@ -89,6 +89,8 @@ pub enum Region { Free(DefId, /* lifetime decl */ DefId), } +impl_defer_dellocs_for_no_drop_type!([] Region); + impl Region { fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam) -> (ParamName, Region) { let i = *index; @@ -195,6 +197,8 @@ impl Set1 { pub type ObjectLifetimeDefault = Set1; +impl_defer_dellocs_for_no_drop_type!([] ObjectLifetimeDefault); + /// Maps the id of each lifetime reference to the lifetime decl /// that it corresponds to. /// @@ -220,10 +224,18 @@ struct NamedRegionMap { /// See `NamedRegionMap`. #[derive(Default)] pub struct ResolveLifetimes { - defs: FxHashMap>>, - late_bound: FxHashMap>>, + defs: FxHashMap>, + late_bound: FxHashMap>, object_lifetime_defaults: - FxHashMap>>>>, + FxHashMap>>, +} + +unsafe impl DeferDeallocs for ResolveLifetimes { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.defs.defer(deferred); + self.late_bound.defer(deferred); + self.object_lifetime_defaults.defer(deferred); + } } impl_stable_hash_for!(struct ::middle::resolve_lifetime::ResolveLifetimes { @@ -358,23 +370,23 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { named_region_map: |tcx, id| { let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id).cloned() + tcx.resolve_lifetimes(LOCAL_CRATE).0.defs.get(&id).map(|m| Bx(m)) }, is_late_bound_map: |tcx, id| { let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE) + tcx.resolve_lifetimes(LOCAL_CRATE).0 .late_bound .get(&id) - .cloned() + .map(|m| Bx(m)) }, object_lifetime_defaults_map: |tcx, id| { let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE) + tcx.resolve_lifetimes(LOCAL_CRATE).0 .object_lifetime_defaults .get(&id) - .cloned() + .map(|m| Bx(m)) }, ..*providers @@ -390,7 +402,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { fn resolve_lifetimes<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, for_krate: CrateNum, -) -> Lrc { +) -> Bx<'tcx, ResolveLifetimes> { assert_eq!(for_krate, LOCAL_CRATE); let named_region_map = krate(tcx); @@ -400,26 +412,24 @@ fn resolve_lifetimes<'tcx>( for (k, v) in named_region_map.defs { let hir_id = tcx.hir.node_to_hir_id(k); let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default(); - Lrc::get_mut(map).unwrap().insert(hir_id.local_id, v); + map.insert(hir_id.local_id, v); } for k in named_region_map.late_bound { let hir_id = tcx.hir.node_to_hir_id(k); let map = rl.late_bound .entry(hir_id.owner_local_def_id()) .or_default(); - Lrc::get_mut(map).unwrap().insert(hir_id.local_id); + map.insert(hir_id.local_id); } for (k, v) in named_region_map.object_lifetime_defaults { let hir_id = tcx.hir.node_to_hir_id(k); let map = rl.object_lifetime_defaults .entry(hir_id.owner_local_def_id()) .or_default(); - Lrc::get_mut(map) - .unwrap() - .insert(hir_id.local_id, Lrc::new(v)); + map.insert(hir_id.local_id, v); } - Lrc::new(rl) + tcx.bx(rl) } fn krate<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> NamedRegionMap { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 543d1053b55e6..8fb8bf0ccb009 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -13,6 +13,7 @@ pub use self::StabilityLevel::*; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use lint; use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; @@ -66,6 +67,8 @@ pub struct DeprecationEntry { origin: Option, } +impl_defer_dellocs_for_no_drop_type!([] DeprecationEntry); + impl_stable_hash_for!(struct self::DeprecationEntry { attr, origin @@ -108,6 +111,15 @@ pub struct Index<'tcx> { active_features: FxHashSet, } +unsafe impl<'tcx> DeferDeallocs for Index<'tcx> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.stab_map.defer(deferred); + self.stab_map.defer(deferred); + self.staged_api.defer(deferred); + self.active_features.defer(deferred); + } +} + impl_stable_hash_for!(struct self::Index<'tcx> { stab_map, depr_map, diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 768d4f1e5fb65..3e81d72103796 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -32,6 +32,8 @@ pub enum PathKind { All, } +impl_defer_dellocs_for_no_drop_type!([] PathKind); + impl SearchPaths { pub fn new() -> SearchPaths { SearchPaths { paths: Vec::new() } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index ab2fa68ab5f89..a97b7ae8c0313 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -31,7 +31,6 @@ use ty::fold::{TypeFolder, TypeFoldable, TypeVisitor}; use infer::{InferCtxt}; use util::common::ErrorReported; -use rustc_data_structures::sync::Lrc; use std::fmt::Debug; use std::rc::Rc; use syntax::ast; @@ -959,11 +958,11 @@ fn substitute_normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx fn vtable_methods<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) - -> Lrc)>>> + -> &'tcx [Option<(DefId, &'tcx Substs<'tcx>)>] { debug!("vtable_methods({:?})", trait_ref); - Lrc::new( + tcx.promote_vec( supertraits(tcx, trait_ref).flat_map(move |trait_ref| { let trait_methods = tcx.associated_items(trait_ref.def_id()) .filter(|item| item.kind == ty::AssociatedKind::Method); diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b8bf0fcc15307..c49ecd9721da7 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use infer::at::At; use infer::InferOk; use infer::canonical::OriginalQueryValues; @@ -95,6 +96,13 @@ pub struct DropckOutlivesResult<'tcx> { pub overflows: Vec>, } +unsafe impl<'tcx> DeferDeallocs for DropckOutlivesResult<'tcx> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.kinds.defer(deferred); + self.overflows.defer(deferred); + } +} + impl<'tcx> DropckOutlivesResult<'tcx> { pub fn report_overflows( &self, diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 91b2ba301c312..ac8a7115a9390 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -83,6 +83,8 @@ pub struct NormalizationResult<'tcx> { pub normalized_ty: Ty<'tcx>, } +impl_defer_dellocs_for_no_drop_type!([<'tcx>] NormalizationResult<'tcx>); + struct QueryNormalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, cause: &'cx ObligationCause<'tcx>, diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index b3fae3bab3471..8e07ac16278a9 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -35,6 +35,8 @@ pub enum OutlivesBound<'tcx> { RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), } +impl_defer_dellocs_for_no_drop_type!([<'tcx>] OutlivesBound<'tcx>); + EnumLiftImpl! { impl<'a, 'tcx> Lift<'tcx> for self::OutlivesBound<'a> { type Lifted = self::OutlivesBound<'tcx>; diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 19ef3171b13fc..102faaf143eb9 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -28,9 +28,8 @@ use infer::{InferCtxt, InferOk}; use ty::subst::{Subst, Substs}; use traits::{self, ObligationCause, TraitEngine}; use traits::select::IntercrateAmbiguityCause; -use ty::{self, TyCtxt, TypeFoldable}; +use ty::{self, Bx, TyCtxt, TypeFoldable}; use syntax_pos::DUMMY_SP; -use rustc_data_structures::sync::Lrc; use lint; @@ -287,7 +286,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, // Query provider for `specialization_graph_of`. pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId) - -> Lrc { + -> Bx<'tcx, specialization_graph::Graph> { let mut sg = specialization_graph::Graph::new(); let mut trait_impls = tcx.all_impls(trait_id); @@ -370,7 +369,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx } } - Lrc::new(sg) + tcx.bx(sg) } /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index db0302f3a901d..ea5961188505a 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -12,12 +12,12 @@ use super::OverlapError; use hir::def_id::DefId; use ich::{self, StableHashingContext}; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use traits; use ty::{self, TyCtxt, TypeFoldable}; use ty::fast_reject::{self, SimplifiedType}; -use rustc_data_structures::sync::Lrc; use syntax::ast::Ident; use util::captures::Captures; use util::nodemap::{DefIdMap, FxHashMap}; @@ -47,6 +47,13 @@ pub struct Graph { children: DefIdMap, } +unsafe impl DeferDeallocs for Graph { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.parent.defer(deferred); + self.children.defer(deferred); + } +} + /// Children of a given impl, grouped into blanket/non-blanket varieties as is /// done in `TraitDef`. #[derive(Default, RustcEncodable, RustcDecodable)] @@ -68,6 +75,13 @@ struct Children { blanket_impls: Vec, } +unsafe impl DeferDeallocs for Children { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.nonblanket_impls.defer(deferred); + self.blanket_impls.defer(deferred); + } +} + /// The result of attempting to insert an impl into a group of children. enum Inserted { /// The impl was inserted as a new child in this group of children. @@ -389,13 +403,13 @@ impl<'a, 'gcx, 'tcx> Node { } } -pub struct Ancestors { +pub struct Ancestors<'tcx> { trait_def_id: DefId, - specialization_graph: Lrc, + specialization_graph: &'tcx Graph, current_source: Option, } -impl Iterator for Ancestors { +impl<'tcx> Iterator for Ancestors<'tcx> { type Item = Node; fn next(&mut self) -> Option { let cur = self.current_source.take(); @@ -426,7 +440,7 @@ impl NodeItem { } } -impl<'a, 'gcx, 'tcx> Ancestors { +impl<'a, 'gcx, 'tcx> Ancestors<'gcx> { /// Search the items from the given ancestors, returning each definition /// with the given name and the given kind. #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. @@ -458,11 +472,11 @@ impl<'a, 'gcx, 'tcx> Ancestors { /// Walk up the specialization ancestors of a given impl, starting with that /// impl itself. -pub fn ancestors(tcx: TyCtxt<'_, '_, '_>, +pub fn ancestors(tcx: TyCtxt<'_, 'tcx, '_>, trait_def_id: DefId, start_from_impl: DefId) - -> Ancestors { - let specialization_graph = tcx.specialization_graph_of(trait_def_id); + -> Ancestors<'tcx> { + let specialization_graph = tcx.specialization_graph_of(trait_def_id).0; Ancestors { trait_def_id, specialization_graph, diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 8738f57414823..1c493a0d52d49 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -19,10 +19,11 @@ use hir::def_id::{DefId, CrateNum}; use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::defer_deallocs::DeferDeallocs; use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque}; use std::hash::Hash; use std::intrinsics; -use ty::{self, Ty, TyCtxt}; +use ty::{self, Ty, TyCtxt, Bx}; use ty::subst::Substs; use mir::interpret::Allocation; @@ -212,6 +213,26 @@ pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result, D Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?)) } +#[inline] +pub fn decode_bx<'a, 'tcx, D, T: DeferDeallocs + Decodable>( + decoder: &mut D +) -> Result, D::Error> + where D: TyDecoder<'a, 'tcx>, + 'tcx: 'a, +{ + Ok(Bx(decoder.tcx().promote(Decodable::decode(decoder)?))) +} + +#[inline] +pub fn decode_bx_slice<'a, 'tcx, D, T: DeferDeallocs + Decodable>( + decoder: &mut D +) -> Result, D::Error> + where D: TyDecoder<'a, 'tcx>, + 'tcx: 'a, +{ + Ok(Bx(decoder.tcx().promote_vec( as Decodable>::decode(decoder)?))) +} + #[inline] pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx ty::List>, D::Error> @@ -293,7 +314,8 @@ macro_rules! implement_ty_decoder { use $crate::ty::codec::*; use $crate::ty::subst::Substs; use $crate::hir::def_id::{CrateNum}; - use rustc_serialize::{Decoder, SpecializedDecoder}; + use rustc_data_structures::defer_deallocs::DeferDeallocs; + use rustc_serialize::{Decoder, Decodable, SpecializedDecoder}; use std::borrow::Cow; impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { @@ -361,6 +383,20 @@ macro_rules! implement_ty_decoder { } } + impl<$($typaram),*, T: DeferDeallocs + Decodable> SpecializedDecoder> + for $DecoderName<$($typaram),*> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + decode_bx(self) + } + } + + impl<$($typaram),*, T: DeferDeallocs + Decodable> SpecializedDecoder> + for $DecoderName<$($typaram),*> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + decode_bx_slice(self) + } + } + impl<$($typaram),*> SpecializedDecoder> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) -> Result, Self::Error> { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 42a4de1682c39..cb9d9b5ef98bb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -38,7 +38,7 @@ use ty::ReprOptions; use traits; use traits::{Clause, Clauses, GoalKind, Goal, Goals}; use ty::{self, Ty, TypeAndMut}; -use ty::{TyS, TyKind, List}; +use ty::{Bx, TyS, TyKind, List}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const}; use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use ty::RegionKind; @@ -55,6 +55,7 @@ use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::interner::HashInterner; use smallvec::SmallVec; +use rustc_data_structures::defer_deallocs::DeferDeallocs; use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, StableVec}; @@ -92,7 +93,7 @@ impl<'tcx> AllArenas<'tcx> { pub fn new() -> Self { AllArenas { global: WorkerLocal::new(|_| GlobalArenas::default()), - interner: SyncDroplessArena::default(), + interner: SyncDroplessArena::new(), } } } @@ -896,12 +897,12 @@ pub struct GlobalCtxt<'tcx> { /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. - trait_map: FxHashMap>>>>, + trait_map: &'tcx FxHashMap>>, /// Export map produced by name resolution. - export_map: FxHashMap>>, + export_map: &'tcx FxHashMap>, pub hir: hir_map::Map<'tcx>, @@ -914,7 +915,7 @@ pub struct GlobalCtxt<'tcx> { // Records the free variables referenced by every closure // expression. Do not track deps for this, just recompute it from // scratch every time. - freevars: FxHashMap>>, + freevars: &'tcx FxHashMap>, maybe_unused_trait_imports: FxHashSet, maybe_unused_extern_crates: Vec<(DefId, Span)>, @@ -971,6 +972,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + #[inline(always)] + pub fn promote(&self, object: T) -> &'gcx T { + self.gcx.global_interners.arena.promote(object) + } + + #[inline(always)] + pub fn promote_vec(&self, vec: Vec) -> &'gcx [T] { + self.gcx.global_interners.arena.promote_vec(vec) + } + + #[inline(always)] + pub fn bx(&self, object: T) -> Bx<'gcx, T> { + Bx(self.promote(object)) + } + + #[inline(always)] + pub fn bx_vec(&self, vec: Vec) -> Bx<'gcx, [T]> { + Bx(self.promote_vec(vec)) + } + pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { self.global_arenas.generics.alloc(generics) } @@ -1152,13 +1173,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { None }; - let mut trait_map: FxHashMap<_, Lrc>> = FxHashMap::default(); + let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); - Lrc::get_mut(map).unwrap() - .insert(hir_id.local_id, - Lrc::new(StableVec::new(v))); + map.insert(hir_id.local_id, StableVec::new(v)); } let gcx = &GlobalCtxt { @@ -1168,13 +1187,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { global_interners: interners, dep_graph, types: common_types, - trait_map, - export_map: resolutions.export_map.into_iter().map(|(k, v)| { - (k, Lrc::new(v)) - }).collect(), - freevars: resolutions.freevars.into_iter().map(|(k, v)| { - (hir.local_def_id(k), Lrc::new(v)) - }).collect(), + trait_map: arenas.interner.promote(trait_map), + export_map: arenas.interner.promote(resolutions.export_map), + freevars: arenas.interner.promote(resolutions.freevars.into_iter().map(|(k, v)| { + (hir.local_def_id(k), v) + }).collect()), maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports .into_iter() @@ -1216,12 +1233,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.sess.consider_optimizing(&cname, msg) } - pub fn lib_features(self) -> Lrc { - self.get_lib_features(LOCAL_CRATE) + pub fn lib_features(self) -> &'gcx middle::lib_features::LibFeatures { + self.get_lib_features(LOCAL_CRATE).0 } - pub fn lang_items(self) -> Lrc { - self.get_lang_items(LOCAL_CRATE) + pub fn lang_items(self) -> &'gcx middle::lang_items::LanguageItems { + self.get_lang_items(LOCAL_CRATE).0 } /// Due to missing llvm support for lowering 128 bit math to software emulation @@ -1258,16 +1275,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { else { None } } - pub fn stability(self) -> Lrc> { - self.stability_index(LOCAL_CRATE) + pub fn stability(self) -> &'gcx stability::Index<'tcx> { + self.stability_index(LOCAL_CRATE).0 } - pub fn crates(self) -> Lrc> { - self.all_crate_nums(LOCAL_CRATE) + pub fn crates(self) -> &'gcx [CrateNum] { + self.all_crate_nums(LOCAL_CRATE).0 } - pub fn features(self) -> Lrc { - self.features_query(LOCAL_CRATE) + pub fn features(self) -> &'gcx feature_gate::Features { + self.features_query(LOCAL_CRATE).0 } pub fn def_key(self, id: DefId) -> hir_map::DefKey { @@ -2944,9 +2961,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { lint::struct_lint_level(self.sess, lint, level, src, None, msg) } - pub fn in_scope_traits(self, id: HirId) -> Option>> { + pub fn in_scope_traits(self, id: HirId) -> Option<&'gcx StableVec> { self.in_scope_traits_map(id.owner) - .and_then(|map| map.get(&id.local_id).cloned()) + .and_then(|map| map.0.get(&id.local_id)) } pub fn named_region(self, id: HirId) -> Option { @@ -2961,10 +2978,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn object_lifetime_defaults(self, id: HirId) - -> Option>> + -> Option<&'gcx [ObjectLifetimeDefault]> { self.object_lifetime_defaults_map(id.owner) - .and_then(|map| map.get(&id.local_id).cloned()) + .and_then(|map| map.0.get(&id.local_id).map(|v| &**v)) } } @@ -3016,32 +3033,32 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { // FIXME(#44234) - almost all of these queries have no sub-queries and // therefore no actual inputs, they're just reading tables calculated in // resolve! Does this work? Unsure! That's what the issue is about - providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned(); - providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned(); + providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).map(|m| Bx(m)); + providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).map(|m| Bx(m)); providers.crate_name = |tcx, id| { assert_eq!(id, LOCAL_CRATE); tcx.crate_name }; providers.get_lib_features = |tcx, id| { assert_eq!(id, LOCAL_CRATE); - Lrc::new(middle::lib_features::collect(tcx)) + tcx.bx(middle::lib_features::collect(tcx)) }; providers.get_lang_items = |tcx, id| { assert_eq!(id, LOCAL_CRATE); - Lrc::new(middle::lang_items::collect(tcx)) + tcx.bx(middle::lang_items::collect(tcx)) }; - providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned(); + providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).map(|m| Bx(m)); providers.maybe_unused_trait_import = |tcx, id| { tcx.maybe_unused_trait_imports.contains(&id) }; providers.maybe_unused_extern_crates = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(tcx.maybe_unused_extern_crates.clone()) + tcx.bx(tcx.maybe_unused_extern_crates.clone()) }; providers.stability_index = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(stability::Index::new(tcx)) + tcx.bx(stability::Index::new(tcx)) }; providers.lookup_stability = |tcx, id| { assert_eq!(id.krate, LOCAL_CRATE); @@ -3059,11 +3076,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.all_crate_nums = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(tcx.cstore.crates_untracked()) + tcx.bx_vec(tcx.cstore.crates_untracked()) }; providers.postorder_cnums = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(tcx.cstore.postorder_cnums_untracked()) + tcx.bx(tcx.cstore.postorder_cnums_untracked()) }; providers.output_filenames = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); @@ -3071,7 +3088,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.features_query = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(tcx.sess.features_untracked().clone()) + tcx.bx(tcx.sess.features_untracked().clone()) }; providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 8304e36381572..17bd7896d89c0 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -53,6 +53,8 @@ pub enum SimplifiedTypeGen ForeignSimplifiedType(DefId), } +impl_defer_dellocs_for_no_drop_type!([] SimplifiedTypeGen); + /// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. /// The idea is to get something simple that we can use to quickly decide if two types could unify /// during method lookup. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4633ab1166347..a6876722a759f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -24,7 +24,6 @@ use ich::Fingerprint; use ich::StableHashingContext; use infer::canonical::Canonical; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; -use middle::privacy::AccessLevels; use middle::resolve_lifetime::ObjectLifetimeDefault; use mir::Mir; use mir::interpret::{GlobalId, ErrorHandled}; @@ -57,6 +56,7 @@ use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use smallvec; +use rustc_data_structures::defer_deallocs::{DeferredDeallocs, DeferDeallocs}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, HashStable}; @@ -90,6 +90,8 @@ pub use self::trait_def::TraitDef; pub use self::query::queries; +pub use self::util::Bx; + pub mod adjustment; pub mod binding; pub mod cast; @@ -120,6 +122,36 @@ mod instance; mod structural_impls; mod sty; +#[no_mangle] +pub fn test1<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, vec: Vec) -> Bx<'tcx, [u32]> { + tcx.bx_vec(vec) +} + +#[no_mangle] +pub fn test2<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Bx<'tcx, u32> { + tcx.bx(45) +} + +#[no_mangle] +pub fn test3<'tcx>( + allocs: &mut DeferredDeallocs, ptr: std::ptr::NonNull, + layout: std::alloc::Layout) { + allocs.add(ptr, layout); +} + +#[no_mangle] +pub fn test4<'tcx>( + allocs: &mut DeferredDeallocs, vec: Vec) { + vec.defer(allocs); +} + +#[no_mangle] +pub fn test5<'tcx>( + allocs: &rustc_data_structures::sync::WorkerLocal>, + vec: &Vec) { + vec.defer(&mut *allocs.borrow_mut()); +} + // Data types /// The complete set of all analyses described in this module. This is @@ -129,7 +161,6 @@ mod sty; /// *on-demand* infrastructure. #[derive(Clone)] pub struct CrateAnalysis { - pub access_levels: Lrc, pub name: String, pub glob_map: Option, } @@ -338,22 +369,26 @@ pub enum Variance { Bivariant, // T <: T -- e.g., unused type parameter } +impl_defer_dellocs_for_no_drop_type!([] Variance); + /// The crate variances map is computed during typeck and contains the /// variance of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the /// HIR of every item in the local crate. Instead, use /// `tcx.variances_of()` to get the variance for a *particular* /// item. -pub struct CrateVariancesMap { +pub struct CrateVariancesMap<'tcx> { /// For each item with generics, maps to a vector of the variance /// of its generics. If an item has no generics, it will have no /// entry. - pub variances: FxHashMap>>, - - /// An empty vector, useful for cloning. - pub empty_variance: Lrc>, + pub variances: FxHashMap, } +unsafe impl<'tcx> DeferDeallocs for CrateVariancesMap<'tcx> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.variances.defer(deferred); + } +} impl Variance { /// `a.xform(b)` combines the variance of a context with the /// variance of a type with the following meaning. If we are in a @@ -995,6 +1030,13 @@ pub struct GenericPredicates<'tcx> { pub predicates: Vec<(Predicate<'tcx>, Span)>, } +unsafe impl<'tcx> DeferDeallocs for GenericPredicates<'tcx> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.parent.defer(deferred); + self.predicates.defer(deferred); + } +} + impl<'tcx> serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {} impl<'tcx> serialize::UseSpecializedDecodable for GenericPredicates<'tcx> {} @@ -1087,6 +1129,8 @@ pub enum Predicate<'tcx> { ConstEvaluatable(DefId, &'tcx Substs<'tcx>), } +impl_defer_dellocs_for_no_drop_type!([<'tcx>] Predicate<'tcx>); + /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the @@ -1097,10 +1141,13 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - pub predicates: FxHashMap>>>, + pub predicates: FxHashMap]>, +} - /// An empty vector, useful for cloning. - pub empty_predicate: Lrc>>, +unsafe impl<'tcx> DeferDeallocs for CratePredicatesMap<'tcx> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.predicates.defer(deferred); + } } impl<'tcx> AsRef> for Predicate<'tcx> { @@ -1233,6 +1280,14 @@ impl<'tcx> PolyTraitPredicate<'tcx> { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct OutlivesPredicate(pub A, pub B); // `A: B` + +unsafe impl DeferDeallocs for OutlivesPredicate { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.0.defer(deferred); + self.1.defer(deferred); + } +} + pub type PolyOutlivesPredicate = ty::Binder>; pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; @@ -1547,6 +1602,7 @@ newtype_index! { } } +impl_defer_dellocs_for_no_drop_type!([] UniverseIndex); impl_stable_hash_for!(struct UniverseIndex { private }); impl UniverseIndex { @@ -2202,7 +2258,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } #[inline] - pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc> { + pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Bx<'tcx, GenericPredicates<'gcx>> { tcx.predicates_of(self.did) } @@ -2962,7 +3018,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, - def_ids: Lrc>, + def_ids: &'gcx [DefId], next_index: usize, } @@ -3048,7 +3104,7 @@ fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc> { + -> &'tcx [DefId] { let id = tcx.hir.as_local_node_id(def_id).unwrap(); let item = tcx.hir.expect_item(id); let vec: Vec<_> = match item.node { @@ -3067,7 +3123,7 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir::ItemKind::TraitAlias(..) => vec![], _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait") }; - Lrc::new(vec) + tcx.promote_vec(vec) } fn def_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Span { @@ -3209,7 +3265,13 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { /// (constructing this map requires touching the entire crate). #[derive(Clone, Debug, Default)] pub struct CrateInherentImpls { - pub inherent_impls: DefIdMap>>, + pub inherent_impls: DefIdMap>, +} + +unsafe impl DeferDeallocs for CrateInherentImpls { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.inherent_impls.defer(deferred) + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 699c2d111c639..4b8aeebe07a72 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -45,7 +45,7 @@ use traits::query::normalize::NormalizationResult; use traits::query::outlives_bounds::OutlivesBound; use traits::specialization_graph; use traits::Clauses; -use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; +use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, Bx}; use ty::steal::Steal; use ty::subst::Substs; use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; @@ -127,22 +127,22 @@ define_queries! { <'tcx> /// predicate gets in the way of some checks, which are intended /// to operate over only the actual where-clauses written by the /// user.) - [] fn predicates_of: PredicatesOfItem(DefId) -> Lrc>, + [] fn predicates_of: PredicatesOfItem(DefId) -> Bx<'tcx, ty::GenericPredicates<'tcx>>, /// Maps from the def-id of an item (trait/struct/enum/fn) to the /// predicates (where clauses) directly defined on it. This is /// equal to the `explicit_predicates_of` predicates plus the /// `inferred_outlives_of` predicates. [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) - -> Lrc>, + -> Bx<'tcx, ty::GenericPredicates<'tcx>>, /// Returns the predicates written explicit by the user. [] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) - -> Lrc>, + -> Bx<'tcx, ty::GenericPredicates<'tcx>>, /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). - [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc>>, + [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> &'tcx [ty::Predicate<'tcx>], /// Maps from the def-id of a trait to the list of /// super-predicates. This is a subset of the full list of @@ -150,12 +150,13 @@ define_queries! { <'tcx> /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> Lrc>, + [] fn super_predicates_of: SuperPredicatesOfItem(DefId) + -> Bx<'tcx, ty::GenericPredicates<'tcx>>, /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. [] fn type_param_predicates: type_param_predicates((DefId, DefId)) - -> Lrc>, + -> Bx<'tcx, ty::GenericPredicates<'tcx>>, [] fn trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef, [] fn adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef, @@ -188,22 +189,22 @@ define_queries! { <'tcx> /// Get a map with the variance of every item; use `item_variance` /// instead. - [] fn crate_variances: crate_variances(CrateNum) -> Lrc, + [] fn crate_variances: crate_variances(CrateNum) -> Bx<'tcx, ty::CrateVariancesMap<'tcx>>, /// Maps from def-id of a type or region parameter to its /// (inferred) variance. - [] fn variances_of: ItemVariances(DefId) -> Lrc>, + [] fn variances_of: ItemVariances(DefId) -> &'tcx [ty::Variance], }, TypeChecking { /// Maps from def-id of a type to its (inferred) outlives. [] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum) - -> Lrc>, + -> Bx<'tcx, ty::CratePredicatesMap<'tcx>>, }, Other { /// Maps from an impl/trait def-id to a list of the def-ids of its items - [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Lrc>, + [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> &'tcx [DefId], /// Maps from a trait item to the trait item "descriptor" [] fn associated_item: AssociatedItems(DefId) -> ty::AssociatedItem, @@ -216,19 +217,19 @@ define_queries! { <'tcx> /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. - [] fn inherent_impls: InherentImpls(DefId) -> Lrc>, + [] fn inherent_impls: InherentImpls(DefId) -> &'tcx [DefId], }, Codegen { /// Set of all the def-ids in this crate that have MIR associated with /// them. This includes all the body owners, but also things like struct /// constructors. - [] fn mir_keys: mir_keys(CrateNum) -> Lrc, + [] fn mir_keys: mir_keys(CrateNum) -> &'tcx DefIdSet, /// Maps DefId's that have an associated Mir to the result /// of the MIR qualify_consts pass. The actual meaning of /// the value isn't known except to the pass itself. - [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc>), + [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Bx<'tcx, BitSet>), /// Fetch the MIR for a given def-id right after it's built - this includes /// unreachable code. @@ -271,7 +272,7 @@ define_queries! { <'tcx> }, Other { - [] fn used_trait_imports: UsedTraitImports(DefId) -> Lrc, + [] fn used_trait_imports: UsedTraitImports(DefId) -> Bx<'tcx, DefIdSet>, }, TypeChecking { @@ -281,7 +282,7 @@ define_queries! { <'tcx> }, BorrowChecking { - [] fn borrowck: BorrowCheck(DefId) -> Lrc, + [] fn borrowck: BorrowCheck(DefId) -> Bx<'tcx, BorrowCheckResult>, /// Borrow checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. @@ -293,7 +294,7 @@ define_queries! { <'tcx> /// Not meant to be used directly outside of coherence. /// (Defined only for LOCAL_CRATE) [] fn crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) - -> Lrc, + -> &'tcx CrateInherentImpls, /// Checks all types in the krate for overlap in their inherent impls. Reports errors. /// Not meant to be used directly outside of coherence. @@ -322,7 +323,7 @@ define_queries! { <'tcx> -> Result<(), ErrorReported>, /// Performs the privacy check and computes "access levels". - [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc, + [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Bx<'tcx, AccessLevels>, }, Other { @@ -330,7 +331,7 @@ define_queries! { <'tcx> /// Per-body `region::ScopeTree`. The `DefId` should be the owner-def-id for the body; /// in the case of closures, this will be redirected to the enclosing function. - [] fn region_scope_tree: RegionScopeTree(DefId) -> Lrc, + [] fn region_scope_tree: RegionScopeTree(DefId) -> &'tcx region::ScopeTree, [] fn mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx>, @@ -359,7 +360,7 @@ define_queries! { <'tcx> TypeChecking { [] fn trait_of_item: TraitOfItem(DefId) -> Option, [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, - [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc, + [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> &'tcx ItemLocalSet, }, Codegen { @@ -368,7 +369,7 @@ define_queries! { <'tcx> Other { [] fn vtable_methods: vtable_methods_node(ty::PolyTraitRef<'tcx>) - -> Lrc)>>>, + -> &'tcx [Option<(DefId, &'tcx Substs<'tcx>)>], }, Codegen { @@ -377,9 +378,9 @@ define_queries! { <'tcx> }, TypeChecking { - [] fn trait_impls_of: TraitImpls(DefId) -> Lrc, + [] fn trait_impls_of: TraitImpls(DefId) -> Bx<'tcx, ty::trait_def::TraitImpls>, [] fn specialization_graph_of: SpecializationGraph(DefId) - -> Lrc, + -> Bx<'tcx, specialization_graph::Graph>, [] fn is_object_safe: ObjectSafety(DefId) -> bool, /// Get the ParameterEnvironment for a given item; this environment @@ -403,7 +404,7 @@ define_queries! { <'tcx> Other { [] fn dylib_dependency_formats: DylibDepFormats(CrateNum) - -> Lrc>, + -> Bx<'tcx, Vec<(CrateNum, LinkagePreference)>>, }, Codegen { @@ -416,18 +417,18 @@ define_queries! { <'tcx> [fatal_cycle] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy, [fatal_cycle] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool, - [] fn extern_crate: ExternCrate(DefId) -> Lrc>, + [] fn extern_crate: ExternCrate(DefId) -> Bx<'tcx, Option>, }, TypeChecking { [] fn specializes: specializes_node((DefId, DefId)) -> bool, [] fn in_scope_traits_map: InScopeTraits(DefIndex) - -> Option>>>>, + -> Option>>>, }, Other { - [] fn module_exports: ModuleExports(DefId) -> Option>>, - [] fn lint_levels: lint_levels_node(CrateNum) -> Lrc, + [] fn module_exports: ModuleExports(DefId) -> Option>>, + [] fn lint_levels: lint_levels_node(CrateNum) -> Bx<'tcx, lint::LintLevelMap>, }, TypeChecking { @@ -452,22 +453,22 @@ define_queries! { <'tcx> // Does not include external symbols that don't have a corresponding DefId, // like the compiler-generated `main` function and so on. [] fn reachable_non_generics: ReachableNonGenerics(CrateNum) - -> Lrc>, + -> Bx<'tcx, DefIdMap>, [] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool, [] fn is_unreachable_local_definition: IsUnreachableLocalDefinition(DefId) -> bool, }, Codegen { [] fn upstream_monomorphizations: UpstreamMonomorphizations(CrateNum) - -> Lrc, CrateNum>>>>, + -> Bx<'tcx, DefIdMap, CrateNum>>>>, [] fn upstream_monomorphizations_for: UpstreamMonomorphizationsFor(DefId) - -> Option, CrateNum>>>, + -> Option, CrateNum>>>, }, Other { [] fn native_libraries: NativeLibraries(CrateNum) -> Lrc>, - [] fn foreign_modules: ForeignModules(CrateNum) -> Lrc>, + [] fn foreign_modules: ForeignModules(CrateNum) -> Bx<'tcx, Vec>, [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option, [] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option, @@ -479,14 +480,14 @@ define_queries! { <'tcx> TypeChecking { [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId)) - -> Lrc>, + -> Bx<'tcx, [DefId]>, [] fn all_trait_implementations: AllTraitImplementations(CrateNum) - -> Lrc>, + -> Bx<'tcx, [DefId]>, }, Other { [] fn dllimport_foreign_items: DllimportForeignItems(CrateNum) - -> Lrc>, + -> Bx<'tcx, FxHashSet>, [] fn is_dllimport_foreign_item: IsDllimportForeignItem(DefId) -> bool, [] fn is_statically_included_foreign_item: IsStaticallyIncludedForeignItem(DefId) -> bool, [] fn native_library_kind: NativeLibraryKind(DefId) @@ -494,18 +495,19 @@ define_queries! { <'tcx> }, Linking { + // Uses Lrc since it lives beyond the type arena [] fn link_args: link_args_node(CrateNum) -> Lrc>, }, BorrowChecking { // Lifetime resolution. See `middle::resolve_lifetimes`. - [] fn resolve_lifetimes: ResolveLifetimes(CrateNum) -> Lrc, + [] fn resolve_lifetimes: ResolveLifetimes(CrateNum) -> Bx<'tcx, ResolveLifetimes>, [] fn named_region_map: NamedRegion(DefIndex) -> - Option>>, + Option>>, [] fn is_late_bound_map: IsLateBound(DefIndex) -> - Option>>, + Option>>, [] fn object_lifetime_defaults_map: ObjectLifetimeDefaults(DefIndex) - -> Option>>>>, + -> Option>>>, }, TypeChecking { @@ -515,33 +517,36 @@ define_queries! { <'tcx> Other { [] fn dep_kind: DepKind(CrateNum) -> DepKind, [] fn crate_name: CrateName(CrateNum) -> Symbol, - [] fn item_children: ItemChildren(DefId) -> Lrc>, + [] fn item_children: ItemChildren(DefId) -> Bx<'tcx, [Export]>, [] fn extern_mod_stmt_cnum: ExternModStmtCnum(DefId) -> Option, - [] fn get_lib_features: get_lib_features_node(CrateNum) -> Lrc, + [] fn get_lib_features: get_lib_features_node(CrateNum) -> Bx<'tcx, LibFeatures>, [] fn defined_lib_features: DefinedLibFeatures(CrateNum) - -> Lrc)>>, - [] fn get_lang_items: get_lang_items_node(CrateNum) -> Lrc, - [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Lrc>, - [] fn missing_lang_items: MissingLangItems(CrateNum) -> Lrc>, + -> Bx<'tcx, Vec<(Symbol, Option)>>, + [] fn get_lang_items: get_lang_items_node(CrateNum) -> Bx<'tcx, LanguageItems>, + [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Bx<'tcx, Vec<(DefId, usize)>>, + [] fn missing_lang_items: MissingLangItems(CrateNum) -> Bx<'tcx, Vec>, [] fn visible_parent_map: visible_parent_map_node(CrateNum) - -> Lrc>, + -> Bx<'tcx, DefIdMap>, [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool, + + // Uses Lrc since it lives beyond the type arena [] fn used_crate_source: UsedCrateSource(CrateNum) -> Lrc, - [] fn postorder_cnums: postorder_cnums_node(CrateNum) -> Lrc>, - [] fn freevars: Freevars(DefId) -> Option>>, + [] fn postorder_cnums: postorder_cnums_node(CrateNum) -> Bx<'tcx, Vec>, + + [] fn freevars: Freevars(DefId) -> Option>>, [] fn maybe_unused_trait_import: MaybeUnusedTraitImport(DefId) -> bool, [] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum) - -> Lrc>, + -> Bx<'tcx, Vec<(DefId, Span)>>, - [] fn stability_index: stability_index_node(CrateNum) -> Lrc>, - [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc>, + [] fn stability_index: stability_index_node(CrateNum) -> Bx<'tcx, stability::Index<'tcx>>, + [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Bx<'tcx, [CrateNum]>, /// A vector of every trait accessible in the whole crate /// (i.e. including those from subcrates). This is used only for /// error reporting. - [] fn all_traits: all_traits_node(CrateNum) -> Lrc>, + [] fn all_traits: all_traits_node(CrateNum) -> Bx<'tcx, [DefId]>, }, Linking { @@ -572,7 +577,7 @@ define_queries! { <'tcx> [] fn normalize_projection_ty: NormalizeProjectionTy( CanonicalProjectionGoal<'tcx> ) -> Result< - Lrc>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>>, NoSolution, >, @@ -584,7 +589,7 @@ define_queries! { <'tcx> [] fn implied_outlives_bounds: ImpliedOutlivesBounds( CanonicalTyGoal<'tcx> ) -> Result< - Lrc>>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>>, NoSolution, >, @@ -592,7 +597,7 @@ define_queries! { <'tcx> [] fn dropck_outlives: DropckOutlives( CanonicalTyGoal<'tcx> ) -> Result< - Lrc>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>>, NoSolution, >, @@ -606,7 +611,7 @@ define_queries! { <'tcx> [] fn type_op_ascribe_user_type: TypeOpAscribeUserType( CanonicalTypeOpAscribeUserTypeGoal<'tcx> ) -> Result< - Lrc>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>, NoSolution, >, @@ -614,7 +619,7 @@ define_queries! { <'tcx> [] fn type_op_eq: TypeOpEq( CanonicalTypeOpEqGoal<'tcx> ) -> Result< - Lrc>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>, NoSolution, >, @@ -622,7 +627,7 @@ define_queries! { <'tcx> [] fn type_op_subtype: TypeOpSubtype( CanonicalTypeOpSubtypeGoal<'tcx> ) -> Result< - Lrc>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>, NoSolution, >, @@ -630,7 +635,7 @@ define_queries! { <'tcx> [] fn type_op_prove_predicate: TypeOpProvePredicate( CanonicalTypeOpProvePredicateGoal<'tcx> ) -> Result< - Lrc>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>, NoSolution, >, @@ -638,7 +643,7 @@ define_queries! { <'tcx> [] fn type_op_normalize_ty: TypeOpNormalizeTy( CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>> ) -> Result< - Lrc>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>>, NoSolution, >, @@ -646,7 +651,7 @@ define_queries! { <'tcx> [] fn type_op_normalize_predicate: TypeOpNormalizePredicate( CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>> ) -> Result< - Lrc>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>>, NoSolution, >, @@ -654,7 +659,7 @@ define_queries! { <'tcx> [] fn type_op_normalize_poly_fn_sig: TypeOpNormalizePolyFnSig( CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>> ) -> Result< - Lrc>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>>, NoSolution, >, @@ -662,7 +667,7 @@ define_queries! { <'tcx> [] fn type_op_normalize_fn_sig: TypeOpNormalizeFnSig( CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>> ) -> Result< - Lrc>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>>, NoSolution, >, @@ -672,13 +677,15 @@ define_queries! { <'tcx> Other { [] fn target_features_whitelist: - target_features_whitelist_node(CrateNum) -> Lrc>>, + target_features_whitelist_node( + CrateNum + ) -> Bx<'tcx, FxHashMap>>, // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning. [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>) -> usize, - [] fn features_query: features_node(CrateNum) -> Lrc, + [] fn features_query: features_node(CrateNum) -> Bx<'tcx, feature_gate::Features>, }, TypeChecking { @@ -694,7 +701,7 @@ define_queries! { <'tcx> Linking { [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum) - -> Lrc>, + -> Bx<'tcx, FxHashMap>, }, } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 1b64a686794c0..6564de28b5528 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -70,7 +70,7 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { b_subst); let opt_variances = self.tcx().variances_of(item_def_id); - relate_substs(self, Some(&opt_variances), a_subst, b_subst) + relate_substs(self, Some(opt_variances), a_subst, b_subst) } /// Switch variance for the purpose of relating `a` and `b`. @@ -132,7 +132,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { } pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&Vec>, + variances: Option<&[ty::Variance]>, a_subst: &'tcx Substs<'tcx>, b_subst: &'tcx Substs<'tcx>) -> RelateResult<'tcx, &'tcx Substs<'tcx>> diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 1416cb17feaed..781b4b4ac1b77 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -10,6 +10,7 @@ //! This module contains TyKind and its major components +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use hir::def_id::DefId; use infer::canonical::Canonical; use mir::interpret::ConstValue; @@ -888,6 +889,12 @@ impl Binder { } } +unsafe impl DeferDeallocs for Binder { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.0.defer(deferred); + } +} + /// Represents the projection of an associated type. In explicit UFCS /// form this would be written `>::N`. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -966,6 +973,8 @@ pub struct FnSig<'tcx> { pub abi: abi::Abi, } +impl_defer_dellocs_for_no_drop_type!([<'tcx>] FnSig<'tcx>); + impl<'tcx> FnSig<'tcx> { pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { &self.inputs_and_output[..self.inputs_and_output.len() - 1] @@ -1247,6 +1256,8 @@ newtype_index! { pub struct BoundVar { .. } } +impl_defer_dellocs_for_no_drop_type!([] BoundVar); + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BoundTy { pub var: BoundVar, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 3425203989891..2827d41d4eab9 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -38,6 +38,8 @@ pub struct Kind<'tcx> { marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>)> } +impl_defer_dellocs_for_no_drop_type!([<'tcx>] Kind<'tcx>); + const TAG_MASK: usize = 0b11; const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index af678c3e9924b..aebcf73176a7d 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -15,12 +15,12 @@ use ich::{self, StableHashingContext}; use traits::specialization_graph; use ty::fast_reject; use ty::fold::TypeFoldable; -use ty::{Ty, TyCtxt}; +use ty::{Bx, Ty, TyCtxt}; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; -use rustc_data_structures::sync::Lrc; /// A trait's definition with type information. pub struct TraitDef { @@ -53,6 +53,13 @@ pub struct TraitImpls { non_blanket_impls: FxHashMap>, } +unsafe impl DeferDeallocs for TraitImpls { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.blanket_impls.defer(deferred); + self.non_blanket_impls.defer(deferred); + } +} + impl<'a, 'gcx, 'tcx> TraitDef { pub fn new(def_id: DefId, unsafety: hir::Unsafety, @@ -73,7 +80,7 @@ impl<'a, 'gcx, 'tcx> TraitDef { pub fn ancestors(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, of_impl: DefId) - -> specialization_graph::Ancestors { + -> specialization_graph::Ancestors<'gcx> { specialization_graph::ancestors(tcx, self.def_id, of_impl) } } @@ -157,7 +164,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId) - -> Lrc { + -> Bx<'tcx, TraitImpls> { let mut impls = TraitImpls::default(); { @@ -194,7 +201,7 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - Lrc::new(impls) + tcx.bx(impls) } impl<'a> HashStable> for TraitImpls { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 51b197d7b990b..6b776afeaf05c 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -24,13 +24,49 @@ use ty::layout::{Integer, IntegerExt}; use util::common::ErrorReported; use middle::lang_items; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_data_structures::fx::FxHashMap; use std::{cmp, fmt}; +use std::ops::Deref; use syntax::ast; use syntax::attr::{self, SignedInt, UnsignedInt}; use syntax_pos::{Span, DUMMY_SP}; +#[repr(transparent)] +#[derive(Debug)] +pub struct Bx<'tcx, T: ?Sized>(pub &'tcx T); + +impl<'tcx, T: 'tcx + ?Sized> Clone for Bx<'tcx, T> { + fn clone(&self) -> Self { + Bx(self.0) + } +} +impl<'tcx, T: 'tcx + ?Sized> Copy for Bx<'tcx, T> {} + +impl<'tcx, T: ?Sized> Deref for Bx<'tcx, T> { + type Target = T; + + fn deref(&self) -> &T { + self.0 + } +} + +impl<'tcx, T: DeferDeallocs> serialize::UseSpecializedDecodable for Bx<'tcx, T> {} +impl<'tcx, T: DeferDeallocs> serialize::UseSpecializedDecodable for Bx<'tcx, [T]> {} + +unsafe impl<'tcx, T: DeferDeallocs> DeferDeallocs for Bx<'tcx, T> { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.0.defer(deferred); + } +} + +impl<'tcx, T: DeferDeallocs + serialize::Encodable> serialize::Encodable for Bx<'tcx, T> { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + serialize::Encodable::encode(self.0, s) + } +} + #[derive(Copy, Clone, Debug)] pub struct Discr<'tcx> { /// bit representation of the discriminant, so `-128i8` is `0xFF_u128` diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index d189460d08848..1bd23e52e2c14 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -32,7 +32,7 @@ use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::ImmutabilityBlame; use rustc::middle::region; use rustc::middle::free_region::RegionRelations; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Bx, Ty, TyCtxt}; use rustc::ty::query::Providers; use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; use rustc_mir::util::suggest_ref_mut; @@ -42,7 +42,6 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::fmt; use std::rc::Rc; -use rustc_data_structures::sync::Lrc; use std::hash::{Hash, Hasher}; use syntax::ast; use syntax_pos::{MultiSpan, Span}; @@ -87,7 +86,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> { } fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) - -> Lrc + -> Bx<'tcx, BorrowCheckResult> { assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck()); @@ -102,7 +101,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) // those things (notably the synthesized constructors from // tuple structs/variants) do not have an associated body // and do not need borrowchecking. - return Lrc::new(BorrowCheckResult { + return tcx.bx(BorrowCheckResult { used_mut_nodes: Default::default(), signalled_any_error: SignalledError::NoErrorsSeen, }) @@ -153,7 +152,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) unused::check(&mut bccx, body); } - Lrc::new(BorrowCheckResult { + tcx.bx(BorrowCheckResult { used_mut_nodes: bccx.used_mut_nodes.into_inner(), signalled_any_error: bccx.signalled_any_error.into_inner(), }) @@ -253,7 +252,7 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { // Some in `borrowck_fn` and cleared later tables: &'a ty::TypeckTables<'tcx>, - region_scope_tree: Lrc, + region_scope_tree: &'tcx region::ScopeTree, owner_def_id: DefId, diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 38ab1302cfa7c..f8573fba13c14 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -18,7 +18,6 @@ use rustc::session::config::Sanitizer; use rustc::ty::TyCtxt; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; -use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::PanicStrategy; use rustc_codegen_ssa::traits::*; @@ -269,11 +268,11 @@ pub fn provide(providers: &mut Providers) { if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all - Lrc::new(llvm_util::all_known_features() + tcx.bx(llvm_util::all_known_features() .map(|(a, b)| (a.to_string(), b.map(|s| s.to_string()))) .collect()) } else { - Lrc::new(llvm_util::target_feature_whitelist(tcx.sess) + tcx.bx(llvm_util::target_feature_whitelist(tcx.sess) .iter() .map(|&(a, b)| (a.to_string(), b.map(|s| s.to_string()))) .collect()) @@ -313,7 +312,7 @@ pub fn provide_extern(providers: &mut Providers) { })); } - Lrc::new(ret) + tcx.bx(ret) }; } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 0fb2641a4f82e..17131d331bef5 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc_data_structures::sync::Lrc; use std::sync::Arc; use rustc::ty::Instance; @@ -19,7 +18,7 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name}; use rustc::session::config; -use rustc::ty::{TyCtxt, SymbolName}; +use rustc::ty::{Bx, TyCtxt, SymbolName}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::util::nodemap::{FxHashMap, DefIdMap}; @@ -59,12 +58,12 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExpor fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Lrc> + -> Bx<'tcx, DefIdMap> { assert_eq!(cnum, LOCAL_CRATE); if !tcx.sess.opts.output_types.should_codegen() { - return Default::default(); + return tcx.bx(Default::default()); } // Check to see if this crate is a "special runtime crate". These @@ -167,7 +166,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, reachable_non_generics.insert(def_id, SymbolExportLevel::C); } - Lrc::new(reachable_non_generics) + tcx.bx(reachable_non_generics) } fn is_reachable_non_generic_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -293,7 +292,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn upstream_monomorphizations_provider<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Lrc, CrateNum>>>> + -> Bx<'tcx, DefIdMap, CrateNum>>>> { debug_assert!(cnum == LOCAL_CRATE); @@ -337,20 +336,20 @@ fn upstream_monomorphizations_provider<'a, 'tcx>( } } - Lrc::new(instances.into_iter() - .map(|(key, value)| (key, Lrc::new(value))) + tcx.bx(instances.into_iter() + .map(|(key, value)| (key, tcx.bx(value))) .collect()) } fn upstream_monomorphizations_for_provider<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option, CrateNum>>> + -> Option, CrateNum>>> { debug_assert!(!def_id.is_local()); tcx.upstream_monomorphizations(LOCAL_CRATE) .get(&def_id) - .cloned() + .map(|v| *v) } fn is_unreachable_local_definition_provider(tcx: TyCtxt, def_id: DefId) -> bool { diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 856bb9533c859..e75d2e79c3422 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -53,7 +53,6 @@ use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt}; use mono_item::MonoItem; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::sync::Lrc; use rustc_codegen_utils::{symbol_names_test, check_for_rustc_errors_attr}; use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; @@ -939,7 +938,7 @@ pub fn provide_both(providers: &mut Providers) { .map(|id| &module_map[&id]) .flat_map(|module| module.foreign_items.iter().cloned()) .collect(); - Lrc::new(dllimports) + tcx.bx(dllimports) }; providers.is_dllimport_foreign_item = |tcx, def_id| { diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 046f0cccfee05..d00c02d809874 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -129,8 +129,8 @@ impl CodegenBackend for MetadataOnlyCodegenBackend { fn provide(&self, providers: &mut Providers) { ::symbol_names::provide(providers); - providers.target_features_whitelist = |_tcx, _cnum| { - Default::default() // Just a dummy + providers.target_features_whitelist = |tcx, _cnum| { + tcx.bx(Default::default()) // Just a dummy }; providers.is_reachable_non_generic = |_tcx, _defid| true; providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new()); diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs index 28aad49b09b99..4ff70fdd0657d 100644 --- a/src/librustc_data_structures/bit_set.rs +++ b/src/librustc_data_structures/bit_set.rs @@ -15,6 +15,7 @@ use std::iter; use std::marker::PhantomData; use std::mem; use std::slice; +use defer_deallocs::{DeferDeallocs, DeferredDeallocs}; pub type Word = u64; pub const WORD_BYTES: usize = mem::size_of::(); @@ -189,6 +190,13 @@ impl BitSet { } } +unsafe impl DeferDeallocs for BitSet { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.words.defer(deferred); + } +} + /// This is implemented by all the bitsets so that BitSet::union() can be /// passed any type of bitset. pub trait UnionIntoBitSet { diff --git a/src/librustc_data_structures/defer_deallocs.rs b/src/librustc_data_structures/defer_deallocs.rs new file mode 100644 index 0000000000000..a862217ab927d --- /dev/null +++ b/src/librustc_data_structures/defer_deallocs.rs @@ -0,0 +1,176 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ptr::NonNull; +use std::alloc::{Alloc, Global, Layout}; +use std::collections::{HashMap, HashSet}; +use std::hash::BuildHasherDefault; +use std::mem::{self, needs_drop}; +use std::path::PathBuf; + +#[derive(Default)] +pub struct DeferredDeallocs { + allocations: Vec<(NonNull, Layout)>, +} + +impl DeferredDeallocs { + #[inline] + pub fn add(&mut self, ptr: NonNull, layout: Layout) { + self.allocations.push((ptr, layout)); + } +} + +impl Drop for DeferredDeallocs { + fn drop(&mut self) { + for &(ptr, layout) in &self.allocations { + unsafe { + Global.dealloc(ptr, layout); + } + } + } +} + +pub unsafe trait DeferDeallocs { + fn defer(&self, deferred: &mut DeferredDeallocs); +} + +#[macro_export] +macro_rules! impl_defer_dellocs_for_no_drop_type { + ([$($p:tt)*] $t:ty) => { + unsafe impl $($p)* $crate::defer_deallocs::DeferDeallocs for $t { + #[inline(always)] + fn defer(&self, _: &mut $crate::defer_deallocs::DeferredDeallocs) { + assert!(!::std::mem::needs_drop::()); + } + } + } +} + +unsafe impl DeferDeallocs for Vec { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + if mem::size_of::() == 0 || self.capacity() == 0 { + return; + } + let ptr = unsafe { + NonNull::new_unchecked(self.as_ptr() as *mut u8) + }; + let size = mem::size_of::(); + let align = mem::align_of::(); + let layout = unsafe { + Layout::from_size_align_unchecked(self.capacity() * size, align) + }; + deferred.add(ptr, layout); + if needs_drop::() { + for v in self { + v.defer(deferred) + } + } + } +} + +impl_defer_dellocs_for_no_drop_type!([] ()); +impl_defer_dellocs_for_no_drop_type!([] bool); +impl_defer_dellocs_for_no_drop_type!([] usize); +impl_defer_dellocs_for_no_drop_type!([] u32); +impl_defer_dellocs_for_no_drop_type!([] u64); +impl_defer_dellocs_for_no_drop_type!([] BuildHasherDefault); +impl_defer_dellocs_for_no_drop_type!([<'a, T: ?Sized>] &'a mut T); +impl_defer_dellocs_for_no_drop_type!([<'a, T: ?Sized>] &'a T); + +unsafe impl DeferDeallocs for String { + #[inline] + fn defer(&self, _: &mut DeferredDeallocs) {} +} + +unsafe impl DeferDeallocs for PathBuf { + #[inline] + fn defer(&self, _: &mut DeferredDeallocs) {} +} + +unsafe impl DeferDeallocs for [T] { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + for v in self { + v.defer(deferred) + } + } +} + +unsafe impl DeferDeallocs for Option { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.as_ref().map(|v| v.defer(deferred)); + } +} + +unsafe impl< + T1: DeferDeallocs, + T2: DeferDeallocs, +> DeferDeallocs +for (T1, T2) { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.0.defer(deferred); + self.1.defer(deferred); + } +} + +unsafe impl< + T1: DeferDeallocs, + T2: DeferDeallocs, + T3: DeferDeallocs, +> DeferDeallocs +for (T1, T2, T3) { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.0.defer(deferred); + self.1.defer(deferred); + self.2.defer(deferred); + } +} + +unsafe impl DeferDeallocs for Box { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + let size = mem::size_of_val(&**self); + // FIXME: What happens when `size` is 0 here? Like [T] when T is zero sized + if size == 0 { + return; + } + let layout = unsafe { + Layout::from_size_align_unchecked(size, mem::align_of_val(&**self)) + }; + deferred.add(unsafe { + NonNull::new_unchecked(&**self as *const T as *mut u8) + }, layout); + (**self).defer(deferred); + } +} + +unsafe impl< + K: DeferDeallocs, + V: DeferDeallocs, + S: DeferDeallocs +> DeferDeallocs +for HashMap { + #[inline] + fn defer(&self, _: &mut DeferredDeallocs) { + // FIXME: Check K and V types + } +} + +unsafe impl DeferDeallocs +for HashSet { + #[inline] + fn defer(&self, _: &mut DeferredDeallocs) { + // FIXME: Check T type + } +} diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index a59bf9d530c4d..7a0524a82275c 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use std::fmt::Debug; use std::iter::{self, FromIterator}; use std::slice; @@ -466,6 +467,12 @@ pub struct IndexVec { // not the phantom data. unsafe impl Send for IndexVec where T: Send {} +unsafe impl DeferDeallocs for IndexVec { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.raw.defer(deferred); + } +} + impl serialize::Encodable for IndexVec { fn encode(&self, s: &mut S) -> Result<(), S::Error> { serialize::Encodable::encode(&self.raw, s) diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 96cb235a93362..1cba17f5a4007 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -20,6 +20,9 @@ html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(allocator_api)] +#![feature(alloc_layout_extra)] +#![feature(extract_raw_alloc)] #![feature(in_band_lifetimes)] #![feature(unboxed_closures)] #![feature(fn_traits)] @@ -61,6 +64,7 @@ pub use rustc_serialize::hex::ToHex; pub mod macros; pub mod svh; pub mod base_n; +#[macro_use] pub mod defer_deallocs; pub mod bit_set; pub mod const_cstr; pub mod flock; diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index c85d771a18106..5fffa2974d9b1 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use std::hash::{Hash, Hasher, BuildHasher}; use std::marker::PhantomData; use std::mem; @@ -556,6 +557,13 @@ impl StableVec { } } +unsafe impl DeferDeallocs for StableVec { + #[inline] + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.0.defer(deferred) + } +} + impl ::std::ops::Deref for StableVec { type Target = Vec; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c1705ad2d58ff..cd38509a5ea70 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -20,7 +20,6 @@ use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, AllArenas, Resolutions, TyCtxt}; use rustc::traits; use rustc::util::common::{install_panic_hook, time, ErrorReported}; @@ -49,7 +48,7 @@ use std::fs; use std::io::{self, Write}; use std::iter; use std::path::{Path, PathBuf}; -use rustc_data_structures::sync::{self, Lrc, Lock}; +use rustc_data_structures::sync::{self, Lock}; use std::sync::mpsc; use syntax::{self, ast, attr, diagnostics, visit}; use syntax::early_buffered_lints::BufferedEarlyLint; @@ -796,7 +795,6 @@ where }, analysis: ty::CrateAnalysis { - access_levels: Lrc::new(AccessLevels::default()), name: crate_name.to_string(), glob_map: if resolver.make_glob_map { Some(resolver.glob_map) @@ -1216,7 +1214,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( sess: &'tcx Session, cstore: &'tcx CStore, hir_map: hir_map::Map<'tcx>, - mut analysis: ty::CrateAnalysis, + analysis: ty::CrateAnalysis, resolutions: Resolutions, arenas: &'tcx AllArenas<'tcx>, name: &str, @@ -1298,8 +1296,7 @@ where rvalue_promotion::check_crate(tcx) }); - analysis.access_levels = - time(sess, "privacy checking", || rustc_privacy::check_crate(tcx)); + time(sess, "privacy checking", || rustc_privacy::check_crate(tcx)); time(sess, "intrinsic checking", || { middle::intrinsicck::check_crate(tcx) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d0fa63a6163db..66a15f2fcf552 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -22,7 +22,7 @@ use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::hir::def; use rustc::session::{CrateDisambiguator, Session}; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, Bx, TyCtxt}; use rustc::ty::query::Providers; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::map::{DefKey, DefPath, DefPathHash}; @@ -103,9 +103,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { Lrc::new(cdata.get_predicates(def_id.index, tcx)) } - predicates_defined_on => { Lrc::new(cdata.get_predicates_defined_on(def_id.index, tcx)) } - super_predicates_of => { Lrc::new(cdata.get_super_predicates(def_id.index, tcx)) } + predicates_of => { tcx.bx(cdata.get_predicates(def_id.index, tcx)) } + predicates_defined_on => { tcx.bx(cdata.get_predicates_defined_on(def_id.index, tcx)) } + super_predicates_of => { tcx.bx(cdata.get_super_predicates(def_id.index, tcx)) } trait_def => { tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess)) } @@ -114,12 +114,12 @@ provide! { <'tcx> tcx, def_id, other, cdata, let _ = cdata; tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) } - variances_of => { Lrc::new(cdata.get_item_variances(def_id.index)) } + variances_of => { tcx.promote_vec(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { let mut result = vec![]; cdata.each_child_of_item(def_id.index, |child| result.push(child.def.def_id()), tcx.sess); - Lrc::new(result) + tcx.promote_vec(result) } associated_item => { cdata.get_associated_item(def_id.index) } impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) } @@ -139,10 +139,10 @@ provide! { <'tcx> tcx, def_id, other, cdata, mir } mir_const_qualif => { - (cdata.mir_const_qualif(def_id.index), Lrc::new(BitSet::new_empty(0))) + (cdata.mir_const_qualif(def_id.index), Bx(tcx.promote(BitSet::new_empty(0)))) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } - inherent_impls => { Lrc::new(cdata.get_inherent_implementations_for_type(def_id.index)) } + inherent_impls => { tcx.promote_vec(cdata.get_inherent_implementations_for_type(def_id.index)) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } describe_def => { cdata.get_def(def_id.index) } @@ -167,7 +167,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, } is_mir_available => { cdata.is_item_mir_available(def_id.index) } - dylib_dependency_formats => { Lrc::new(cdata.get_dylib_dependency_formats()) } + dylib_dependency_formats => { tcx.bx(cdata.get_dylib_dependency_formats()) } is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } @@ -176,7 +176,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_profiler_runtime => { cdata.root.profiler_runtime } panic_strategy => { cdata.root.panic_strategy } extern_crate => { - let r = Lrc::new(*cdata.extern_crate.lock()); + let r = tcx.bx(*cdata.extern_crate.lock()); r } is_no_builtins => { cdata.root.no_builtins } @@ -194,10 +194,10 @@ provide! { <'tcx> tcx, def_id, other, cdata, }) .collect(); - Lrc::new(reachable_non_generics) + tcx.bx(reachable_non_generics) } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } - foreign_modules => { Lrc::new(cdata.get_foreign_modules(tcx.sess)) } + foreign_modules => { tcx.bx(cdata.get_foreign_modules(tcx.sess)) } plugin_registrar_fn => { cdata.root.plugin_registrar_fn.map(|index| { DefId { krate: def_id.krate, index } @@ -219,13 +219,13 @@ provide! { <'tcx> tcx, def_id, other, cdata, let mut result = vec![]; let filter = Some(other); cdata.get_implementations_for_trait(filter, &mut result); - Lrc::new(result) + tcx.bx_vec(result) } all_trait_implementations => { let mut result = vec![]; cdata.get_implementations_for_trait(None, &mut result); - Lrc::new(result) + tcx.bx_vec(result) } visibility => { cdata.get_visibility(def_id.index) } @@ -237,11 +237,11 @@ provide! { <'tcx> tcx, def_id, other, cdata, item_children => { let mut result = vec![]; cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess); - Lrc::new(result) + tcx.bx_vec(result) } - defined_lib_features => { Lrc::new(cdata.get_lib_features()) } - defined_lang_items => { Lrc::new(cdata.get_lang_items()) } - missing_lang_items => { Lrc::new(cdata.get_missing_lang_items()) } + defined_lib_features => { tcx.bx(cdata.get_lib_features()) } + defined_lang_items => { tcx.bx(cdata.get_lang_items()) } + missing_lang_items => { tcx.bx(cdata.get_missing_lang_items()) } missing_extern_crate_item => { let r = match *cdata.extern_crate.borrow() { @@ -300,7 +300,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { }, foreign_modules: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(foreign_modules::collect(tcx)) + tcx.bx(foreign_modules::collect(tcx)) }, link_args: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); @@ -337,7 +337,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { // which is to say, its not deterministic in general. But // we believe that libstd is consistently assigned crate // num 1, so it should be enough to resolve #46112. - let mut crates: Vec = (*tcx.crates()).clone(); + let mut crates: Vec = (*tcx.crates()).to_owned(); crates.sort(); for &cnum in crates.iter() { @@ -386,7 +386,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { } } - Lrc::new(visible_parent_map) + tcx.bx(visible_parent_map) }, ..*providers diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4ccd26bee8b88..e79d928745dd8 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -25,7 +25,6 @@ use rustc::ty::{self, DefIdTree}; use rustc::util::ppaux::with_highlight_region_for_bound_region; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; @@ -668,7 +667,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &mut self, context: Context, name: &str, - scope_tree: &Lrc, + scope_tree: &'tcx ScopeTree, borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans, @@ -851,7 +850,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn report_temporary_value_does_not_live_long_enough( &mut self, context: Context, - scope_tree: &Lrc, + scope_tree: &'tcx ScopeTree, borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index c414088b65322..8cbca3ee570b3 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -30,7 +30,6 @@ use syntax::ast; use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; -use rustc_data_structures::sync::Lrc; use hair::constant::{lit_to_const, LitToConstError}; #[derive(Clone)] @@ -44,7 +43,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { /// Identity `Substs` for use with const-evaluation. pub identity_substs: &'gcx Substs<'gcx>, - pub region_scope_tree: Lrc, + pub region_scope_tree: &'gcx region::ScopeTree, pub tables: &'a ty::TypeckTables<'gcx>, /// This is `Constness::Const` if we are compiling a `static`, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index a77e9b502ac26..e7b7880b31ff3 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -18,7 +18,6 @@ use rustc::ty::steal::Steal; use rustc::hir; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::util::nodemap::DefIdSet; -use rustc_data_structures::sync::Lrc; use std::borrow::Cow; use syntax::ast; use syntax_pos::Span; @@ -69,7 +68,7 @@ fn is_mir_available<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> boo /// Finds the full set of def-ids within the current crate that have /// MIR associated with them. fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) - -> Lrc { + -> &'tcx DefIdSet { assert_eq!(krate, LOCAL_CRATE); let mut set = DefIdSet::default(); @@ -104,7 +103,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) set: &mut set, }.as_deep_visitor()); - Lrc::new(set) + tcx.promote(set) } fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index bcee6d75b5a4a..2182b1df53566 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -21,7 +21,7 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::mir::interpret::ConstValue; use rustc::traits::{self, TraitEngine}; -use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; +use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, Bx}; use rustc::ty::cast::CastTy; use rustc::ty::query::Providers; use rustc::mir::*; @@ -34,7 +34,6 @@ use syntax::feature_gate::{UnstableFeatures, feature_err, emit_feature_err, Gate use syntax_pos::{Span, DUMMY_SP}; use std::fmt; -use rustc_data_structures::sync::Lrc; use std::usize; use transform::{MirPass, MirSource}; @@ -321,7 +320,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } /// Qualify a whole const, static initializer or const fn. - fn qualify_const(&mut self) -> (Qualif, Lrc>) { + fn qualify_const(&mut self) -> (Qualif, Bx<'tcx, BitSet>) { debug!("qualifying {} {:?}", self.mode, self.def_id); let mir = self.mir; @@ -441,7 +440,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } } - (self.qualif, Lrc::new(promoted_temps)) + (self.qualif, Bx(self.tcx.promote(promoted_temps))) } fn is_const_panic_fn(&self, def_id: DefId) -> bool { @@ -1258,7 +1257,7 @@ pub fn provide(providers: &mut Providers) { fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> (u8, Lrc>) { + -> (u8, Bx<'tcx, BitSet>) { // NB: This `borrow()` is guaranteed to be valid (i.e., the value // cannot yet be stolen), because `mir_validated()`, which steals // from `mir_const(), forces this query to execute before @@ -1267,7 +1266,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if mir.return_ty().references_error() { tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors"); - return (Qualif::NOT_CONST.bits(), Lrc::new(BitSet::new_empty(0))); + return (Qualif::NOT_CONST.bits(), Bx(tcx.promote(BitSet::new_empty(0)))); } let mut qualifier = Qualifier::new(tcx, def_id, mir, Mode::Const); diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 099c6df32ad18..8891446883f8f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -35,7 +35,6 @@ use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::util::nodemap::{ItemLocalSet, NodeSet}; use rustc::hir; -use rustc_data_structures::sync::Lrc; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; use self::Promotability::*; @@ -72,7 +71,7 @@ fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc + -> &'tcx ItemLocalSet { let outer_def_id = tcx.closure_base_def_id(def_id); if outer_def_id != def_id { @@ -96,7 +95,7 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let body_id = tcx.hir.body_owned_by(node_id); let _ = visitor.check_nested_body(body_id); - Lrc::new(visitor.result) + tcx.promote(visitor.result) } struct CheckCrateVisitor<'a, 'tcx: 'a> { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 6d9abbf5af2ac..5ab5bf67ddc89 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -31,7 +31,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; -use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind}; +use rustc::ty::{self, Bx, TyCtxt, Ty, TypeFoldable, GenericParamDefKind}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; use rustc::ty::subst::UnpackedKind; @@ -43,7 +43,6 @@ use syntax_pos::Span; use std::cmp; use std::mem::replace; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::Lrc; mod diagnostics; @@ -1704,13 +1703,13 @@ pub fn provide(providers: &mut Providers) { }; } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Lrc { +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Bx<'tcx, AccessLevels> { tcx.privacy_access_levels(LOCAL_CRATE) } fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) - -> Lrc { + -> Bx<'tcx, AccessLevels> { assert_eq!(krate, LOCAL_CRATE); let krate = tcx.hir.krate(); @@ -1785,7 +1784,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } - Lrc::new(visitor.access_levels) + tcx.bx(visitor.access_levels) } __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 15c8861eb3f1f..f3e79e62fcb10 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -66,14 +66,14 @@ macro_rules! access_from { ($save_ctxt:expr, $vis:expr, $id:expr) => { Access { public: $vis.node.is_pub(), - reachable: $save_ctxt.analysis.access_levels.is_reachable($id), + reachable: $save_ctxt.access_levels.is_reachable($id), } }; ($save_ctxt:expr, $item:expr) => { Access { public: $item.vis.node.is_pub(), - reachable: $save_ctxt.analysis.access_levels.is_reachable($item.id), + reachable: $save_ctxt.access_levels.is_reachable($item.id), } }; } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 82c4795a29d4b..91da25188251c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -46,6 +46,7 @@ use rustc::hir::def::Def as HirDef; use rustc::hir::Node; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::ExternCrate; +use rustc::middle::privacy::AccessLevels; use rustc::session::config::{CrateType, Input, OutputType}; use rustc::ty::{self, TyCtxt}; use rustc_typeck::hir_ty_to_ty; @@ -78,6 +79,7 @@ use rls_data::config::Config; pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, tables: &'l ty::TypeckTables<'tcx>, + access_levels: &'tcx AccessLevels, analysis: &'l ty::CrateAnalysis, span_utils: SpanUtils<'tcx>, config: Config, @@ -1139,6 +1141,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( let save_ctxt = SaveContext { tcx, tables: &ty::TypeckTables::empty(None), + access_levels: tcx.privacy_access_levels(LOCAL_CRATE).0, analysis, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 9ab86daf65449..a6cdda25cdb46 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -15,9 +15,8 @@ use rustc::traits::query::{CanonicalTyGoal, NoSolution}; use rustc::traits::{FulfillmentContext, Normalized, ObligationCause, TraitEngineExt}; use rustc::ty::query::Providers; use rustc::ty::subst::{Subst, Substs}; -use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use rustc::ty::{self, Bx, ParamEnvAnd, Ty, TyCtxt}; use rustc::util::nodemap::FxHashSet; -use rustc_data_structures::sync::Lrc; use syntax::source_map::{Span, DUMMY_SP}; crate fn provide(p: &mut Providers) { @@ -31,7 +30,8 @@ crate fn provide(p: &mut Providers) { fn dropck_outlives<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonical_goal: CanonicalTyGoal<'tcx>, -) -> Result>>>, NoSolution> { +) -> Result>>>, NoSolution> { debug!("dropck_outlives(goal={:#?})", canonical_goal); tcx.infer_ctxt().enter_with_canonical( diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 7514c2c18e7ca..a1285017a56be 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -16,7 +16,7 @@ use rustc::infer::canonical::{self, Canonical}; use rustc::traits::{TraitEngine, TraitEngineExt}; use rustc::traits::query::outlives_bounds::OutlivesBound; use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Bx, Ty, TyCtxt, TypeFoldable}; use rustc::ty::outlives::Component; use rustc::ty::query::Providers; use rustc::ty::wf; @@ -25,8 +25,6 @@ use syntax::ast::DUMMY_NODE_ID; use syntax::source_map::DUMMY_SP; use rustc::traits::FulfillmentContext; -use rustc_data_structures::sync::Lrc; - crate fn provide(p: &mut Providers) { *p = Providers { implied_outlives_bounds, @@ -38,7 +36,7 @@ fn implied_outlives_bounds<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, goal: CanonicalTyGoal<'tcx>, ) -> Result< - Lrc>>>>, + Bx<'tcx, Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>>, NoSolution, > { tcx.infer_ctxt() diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index 637a50728f39c..4124a4afff00d 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -12,8 +12,7 @@ use rustc::infer::canonical::{Canonical, QueryResponse}; use rustc::traits::query::{normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution}; use rustc::traits::{self, ObligationCause, SelectionContext, TraitEngineExt}; use rustc::ty::query::Providers; -use rustc::ty::{ParamEnvAnd, TyCtxt}; -use rustc_data_structures::sync::Lrc; +use rustc::ty::{Bx, ParamEnvAnd, TyCtxt}; use std::sync::atomic::Ordering; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::DUMMY_SP; @@ -28,7 +27,7 @@ crate fn provide(p: &mut Providers) { fn normalize_projection_ty<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, goal: CanonicalProjectionGoal<'tcx>, -) -> Result>>>, NoSolution> { +) -> Result>>>, NoSolution> { debug!("normalize_provider(goal={:#?})", goal); tcx.sess diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index e635bc9efc45c..83b8b8f6c4dab 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -27,8 +27,8 @@ use rustc::ty::query::Providers; use rustc::ty::subst::{Kind, Subst, UserSelfTy, UserSubsts}; use rustc::ty::{ FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance, + Bx, }; -use rustc_data_structures::sync::Lrc; use std::fmt; use syntax::ast; use syntax_pos::DUMMY_SP; @@ -50,7 +50,7 @@ crate fn provide(p: &mut Providers) { fn type_op_ascribe_user_type<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>, -) -> Result>>, NoSolution> { +) -> Result>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let ( @@ -228,7 +228,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { fn type_op_eq<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, -) -> Result>>, NoSolution> { +) -> Result>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let (param_env, Eq { a, b }) = key.into_parts(); @@ -258,7 +258,7 @@ where fn type_op_normalize_ty( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, -) -> Result>>>, NoSolution> { +) -> Result>>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, type_op_normalize) } @@ -266,7 +266,7 @@ fn type_op_normalize_ty( fn type_op_normalize_predicate( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, -) -> Result>>>, NoSolution> { +) -> Result>>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, type_op_normalize) } @@ -274,7 +274,7 @@ fn type_op_normalize_predicate( fn type_op_normalize_fn_sig( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, -) -> Result>>>, NoSolution> { +) -> Result>>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, type_op_normalize) } @@ -282,7 +282,7 @@ fn type_op_normalize_fn_sig( fn type_op_normalize_poly_fn_sig( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, -) -> Result>>>, NoSolution> { +) -> Result>>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, type_op_normalize) } @@ -290,7 +290,7 @@ fn type_op_normalize_poly_fn_sig( fn type_op_subtype<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, -) -> Result>>, NoSolution> { +) -> Result>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let (param_env, Subtype { sub, sup }) = key.into_parts(); @@ -304,7 +304,7 @@ fn type_op_subtype<'tcx>( fn type_op_prove_predicate<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, -) -> Result>>, NoSolution> { +) -> Result>>, NoSolution> { tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let (param_env, ProvePredicate { predicate }) = key.into_parts(); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4fbbe58445254..dcd8be8ab1d0b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -21,10 +21,9 @@ use middle::resolve_lifetime as rl; use namespace::Namespace; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; +use rustc::ty::{self, Bx, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::wf::object_region_bounds; -use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use std::collections::BTreeSet; use std::slice; @@ -47,7 +46,7 @@ pub trait AstConv<'gcx, 'tcx> { /// Returns the set of bounds in scope for the type parameter with /// the given id. fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> Lrc>; + -> Bx<'tcx, ty::GenericPredicates<'tcx>>; /// What lifetime should we use when a lifetime is omitted (and not elided)? fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>) diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index b4ad9cfbc6d51..3af3a7b5140cf 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -18,7 +18,6 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::{self, Pat, PatKind, Expr}; use rustc::middle::region; use rustc::ty::{self, Ty}; -use rustc_data_structures::sync::Lrc; use syntax_pos::Span; use super::FnCtxt; use util::nodemap::FxHashMap; @@ -26,7 +25,7 @@ use util::nodemap::FxHashMap; struct InteriorVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, types: FxHashMap, usize>, - region_scope_tree: Lrc, + region_scope_tree: &'gcx region::ScopeTree, expr_count: usize, } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index cd243d4144394..1578eca3ec1aa 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -14,7 +14,6 @@ use check::FnCtxt; use rustc::hir::map as hir_map; use hir::Node; -use rustc_data_structures::sync::Lrc; use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; use rustc::ty::item_path::with_crate_prefix; use hir::def::Def; @@ -785,7 +784,7 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec pub fn provide(providers: &mut ty::query::Providers) { providers.all_traits = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(compute_all_traits(tcx)) + tcx.bx_vec(compute_all_traits(tcx)) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e30a79b25de7f..a9d99a69c8fd6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -98,7 +98,7 @@ use rustc::mir::interpret::{ConstValue, GlobalId}; use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; -use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; +use rustc::ty::{self, Bx, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; @@ -115,7 +115,6 @@ use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap}; use std::cell::{Cell, RefCell, Ref, RefMut}; -use rustc_data_structures::sync::Lrc; use std::collections::hash_map::Entry; use std::cmp; use std::fmt::Display; @@ -831,8 +830,8 @@ fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn used_trait_imports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Lrc { - tcx.typeck_tables_of(def_id).used_trait_imports.clone() + -> Bx<'tcx, DefIdSet> { + Bx(&*tcx.typeck_tables_of(def_id).used_trait_imports) } fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1878,7 +1877,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) - -> Lrc> + -> Bx<'tcx, ty::GenericPredicates<'tcx>> { let tcx = self.tcx; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -1886,7 +1885,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - Lrc::new(ty::GenericPredicates { + tcx.bx(ty::GenericPredicates { parent: None, predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| { match predicate { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 212ee2698e012..82af26cfd8935 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -96,7 +96,6 @@ use rustc::ty::{self, Ty}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::{self, PatKind}; -use rustc_data_structures::sync::Lrc; use std::mem; use std::ops::Deref; use std::rc::Rc; @@ -206,7 +205,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - pub region_scope_tree: Lrc, + pub region_scope_tree: &'gcx region::ScopeTree, outlives_environment: OutlivesEnvironment<'tcx>, diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index d9dff1441296d..df6b2dc4c4888 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -23,14 +23,13 @@ use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::{self, CrateInherentImpls, TyCtxt}; -use rustc_data_structures::sync::Lrc; use syntax::ast; use syntax_pos::Span; /// On-demand query: yields a map containing all types mapped to their inherent impls. pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) - -> Lrc { + -> &'tcx CrateInherentImpls { assert_eq!(crate_num, LOCAL_CRATE); let krate = tcx.hir.krate(); @@ -39,13 +38,13 @@ pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impls_map: Default::default(), }; krate.visit_all_item_likes(&mut collect); - Lrc::new(collect.impls_map) + tcx.promote(collect.impls_map) } /// On-demand query: yields a vector of the inherent impls for a specific type. pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty_def_id: DefId) - -> Lrc> { + -> &'tcx [DefId] { assert!(ty_def_id.is_local()); // NB. Until we adopt the red-green dep-tracking algorithm (see @@ -63,15 +62,11 @@ pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4 - thread_local! { - static EMPTY_DEF_ID_VEC: Lrc> = Lrc::new(vec![]) - } - let result = tcx.dep_graph.with_ignore(|| { let crate_map = tcx.crate_inherent_impls(ty_def_id.krate); match crate_map.inherent_impls.get(&ty_def_id) { - Some(v) => v.clone(), - None => EMPTY_DEF_ID_VEC.with(|v| v.clone()) + Some(v) => &v[..], + None => &[], } }); @@ -299,13 +294,8 @@ impl<'a, 'tcx> InherentCollect<'a, 'tcx> { // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. let impl_def_id = self.tcx.hir.local_def_id(item.id); - let mut rc_vec = self.impls_map.inherent_impls - .entry(def_id) - .or_default(); - - // At this point, there should not be any clones of the - // `Lrc`, so we can still safely push into it in place: - Lrc::get_mut(&mut rc_vec).unwrap().push(impl_def_id); + let vec = self.impls_map.inherent_impls.entry(def_id).or_default(); + vec.push(impl_def_id); } else { struct_span_err!(self.tcx.sess, item.span, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a1bb0b53f1fce..ceaaf81e37f9d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -35,11 +35,10 @@ use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::ty::util::Discr; use rustc::ty::util::IntTypeExt; -use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; +use rustc::ty::{self, Bx, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{ReprOptions, ToPredicate}; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use syntax::ast; @@ -180,7 +179,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { } fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> Lrc> { + -> Bx<'tcx, ty::GenericPredicates<'tcx>> { self.tcx .at(span) .type_param_predicates((self.item_def_id, def_id)) @@ -245,7 +244,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { fn type_param_predicates<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, (item_def_id, def_id): (DefId, DefId), -) -> Lrc> { +) -> Bx<'tcx, ty::GenericPredicates<'tcx>> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -266,8 +265,8 @@ fn type_param_predicates<'a, 'tcx>( tcx.generics_of(item_def_id).parent }; - let mut result = parent.map_or_else( - || Lrc::new(ty::GenericPredicates { + let result = parent.map_or_else( + || tcx.bx(ty::GenericPredicates { parent: None, predicates: vec![], }), @@ -276,6 +275,7 @@ fn type_param_predicates<'a, 'tcx>( icx.get_type_parameter_bounds(DUMMY_SP, def_id) }, ); + let mut extend = None; let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap(); let ast_generics = match tcx.hir.get(item_node_id) { @@ -300,9 +300,7 @@ fn type_param_predicates<'a, 'tcx>( // Implied `Self: Trait` and supertrait bounds. if param_id == item_node_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - Lrc::make_mut(&mut result) - .predicates - .push((identity_trait_ref.to_predicate(), item.span)); + extend = Some((identity_trait_ref.to_predicate(), item.span)); } generics } @@ -319,11 +317,12 @@ fn type_param_predicates<'a, 'tcx>( }; let icx = ItemCtxt::new(tcx, item_def_id); - Lrc::make_mut(&mut result) - .predicates - .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, - OnlySelfBounds(true))); - result + let mut result = (*result).clone(); + result.predicates.extend(extend.into_iter()); + result.predicates + .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, + OnlySelfBounds(true))); + tcx.bx(result) } impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { @@ -687,7 +686,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad fn super_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, -) -> Lrc> { +) -> Bx<'tcx, ty::GenericPredicates<'tcx>> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap(); @@ -731,7 +730,7 @@ fn super_predicates_of<'a, 'tcx>( } } - Lrc::new(ty::GenericPredicates { + tcx.bx(ty::GenericPredicates { parent: None, predicates: superbounds, }) @@ -1607,9 +1606,9 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( fn predicates_defined_on<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc> { +) -> Bx<'tcx, ty::GenericPredicates<'tcx>> { debug!("predicates_defined_on({:?})", def_id); - let mut result = tcx.explicit_predicates_of(def_id); + let result = tcx.explicit_predicates_of(def_id); debug!( "predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, @@ -1623,18 +1622,19 @@ fn predicates_defined_on<'a, 'tcx>( def_id, inferred_outlives, ); - Lrc::make_mut(&mut result) - .predicates - .extend(inferred_outlives.iter().map(|&p| (p, span))); + let mut result = (*result).clone(); + result.predicates.extend(inferred_outlives.iter().map(|&p| (p, span))); + tcx.bx(result) + } else { + result } - result } fn predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc> { - let mut result = tcx.predicates_defined_on(def_id); +) -> Bx<'tcx, ty::GenericPredicates<'tcx>> { + let result = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { // For traits, add `Self: Trait` predicate. This is @@ -1650,17 +1650,18 @@ fn predicates_of<'a, 'tcx>( // used, and adding the predicate into this list ensures // that this is done. let span = tcx.def_span(def_id); - Lrc::make_mut(&mut result) - .predicates - .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + let mut result = (*result).clone(); + result.predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + tcx.bx(result) + } else { + result } - result } fn explicit_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Lrc> { +) -> Bx<'tcx, ty::GenericPredicates<'tcx>> { use rustc::hir::*; use rustc_data_structures::fx::FxHashSet; @@ -1771,7 +1772,7 @@ fn explicit_predicates_of<'a, 'tcx>( if impl_trait_fn.is_some() { // impl Trait - return Lrc::new(ty::GenericPredicates { + return tcx.bx(ty::GenericPredicates { parent: None, predicates: bounds.predicates(tcx, opaque_ty), }); @@ -1981,7 +1982,7 @@ fn explicit_predicates_of<'a, 'tcx>( ); } - Lrc::new(ty::GenericPredicates { + tcx.bx(ty::GenericPredicates { parent: generics.parent, predicates, }) diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index 1eb53ffc730f6..0705ee4e0912c 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -13,8 +13,7 @@ use rustc::hir; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::ty::query::Providers; use rustc::ty::subst::UnpackedKind; -use rustc::ty::{self, CratePredicatesMap, TyCtxt}; -use rustc_data_structures::sync::Lrc; +use rustc::ty::{self, Bx, CratePredicatesMap, TyCtxt}; mod explicit; mod implicit_infer; @@ -33,7 +32,7 @@ pub fn provide(providers: &mut Providers) { fn inferred_outlives_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId, -) -> Lrc>> { +) -> &'tcx [ty::Predicate<'tcx>] { let id = tcx .hir .as_local_node_id(item_def_id) @@ -47,8 +46,8 @@ fn inferred_outlives_of<'a, 'tcx>( let predicates = crate_map .predicates .get(&item_def_id) - .unwrap_or(&crate_map.empty_predicate) - .clone(); + .map(|p| *p) + .unwrap_or(&[]); if tcx.has_attr(item_def_id, "rustc_outlives") { let mut pred: Vec = predicates @@ -73,17 +72,17 @@ fn inferred_outlives_of<'a, 'tcx>( predicates } - _ => Lrc::new(Vec::new()), + _ => &[], }, - _ => Lrc::new(Vec::new()), + _ => &[], } } fn inferred_outlives_crate<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, crate_num: CrateNum, -) -> Lrc> { +) -> Bx<'tcx, CratePredicatesMap<'tcx>> { assert_eq!(crate_num, LOCAL_CRATE); // Compute a map from each struct/enum/union S to the **explicit** @@ -118,13 +117,10 @@ fn inferred_outlives_crate<'tcx>( ), }, ).collect(); - (def_id, Lrc::new(vec)) + (def_id, tcx.promote_vec(vec)) }).collect(); - let empty_predicate = Lrc::new(Vec::new()); - - Lrc::new(ty::CratePredicatesMap { + tcx.bx(ty::CratePredicatesMap { predicates, - empty_predicate, }) } diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index e3c82d50a8d9b..5f96f7ab6e156 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -17,9 +17,8 @@ use arena; use rustc::hir; use hir::Node; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::ty::{self, CrateVariancesMap, TyCtxt}; +use rustc::ty::{self, Bx, CrateVariancesMap, TyCtxt}; use rustc::ty::query::Providers; -use rustc_data_structures::sync::Lrc; /// Defines the `TermsContext` basically houses an arena where we can /// allocate terms. @@ -46,16 +45,16 @@ pub fn provide(providers: &mut Providers) { } fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) - -> Lrc { + -> Bx<'tcx, CrateVariancesMap<'tcx>> { assert_eq!(crate_num, LOCAL_CRATE); let mut arena = arena::TypedArena::default(); let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena); let constraints_cx = constraints::add_constraints_from_crate(terms_cx); - Lrc::new(solve::solve_constraints(constraints_cx)) + tcx.bx(solve::solve_constraints(constraints_cx)) } fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) - -> Lrc> { + -> &'tcx [ty::Variance] { let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id"); let unsupported = || { // Variance not relevant. @@ -98,7 +97,7 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) let crate_map = tcx.crate_variances(LOCAL_CRATE); crate_map.variances.get(&item_def_id) - .unwrap_or(&crate_map.empty_variance) - .clone() + .map(|p| *p) + .unwrap_or(&[]) } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 7116a42cead83..1f2e7968aa4f1 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -18,7 +18,6 @@ use rustc::hir::def_id::DefId; use rustc::ty; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; use super::constraints::*; use super::terms::*; @@ -33,7 +32,9 @@ struct SolveContext<'a, 'tcx: 'a> { solutions: Vec, } -pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap { +pub fn solve_constraints<'tcx>( + constraints_cx: ConstraintContext<'_, 'tcx> +) -> ty::CrateVariancesMap<'tcx> { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; @@ -51,9 +52,8 @@ pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariance }; solutions_cx.solve(); let variances = solutions_cx.create_map(); - let empty_variance = Lrc::new(Vec::new()); - ty::CrateVariancesMap { variances, empty_variance } + ty::CrateVariancesMap { variances } } impl<'a, 'tcx> SolveContext<'a, 'tcx> { @@ -88,7 +88,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } } - fn create_map(&self) -> FxHashMap>> { + fn create_map(&self) -> FxHashMap { let tcx = self.terms_cx.tcx; let solutions = &self.solutions; @@ -109,7 +109,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } } - (def_id, Lrc::new(variances)) + (def_id, tcx.promote_vec(variances)) }).collect() } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index fde8648c0c40a..304ca052b96a8 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -151,7 +151,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { // Instead, we generate `impl !Send for Foo`, which better // expresses the fact that `Foo` never implements `Send`, // regardless of the choice of `T`. - let real_generics = (&generics, &Default::default()); + let real_generics = (&generics, &self.cx.tcx.bx(Default::default())); // Clean the generics, but ignore the '?Sized' bounds generated // by the `Clean` impl diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fd8f70b19e7ec..2c84c222ef220 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -37,7 +37,7 @@ use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::ty::subst::Substs; -use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; +use rustc::ty::{self, Bx, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::layout::VariantIdx; use rustc::middle::stability; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -51,7 +51,6 @@ use std::hash::{Hash, Hasher}; use std::default::Default; use std::{mem, slice, vec}; use std::iter::{FromIterator, once}; -use rustc_data_structures::sync::Lrc; use std::rc::Rc; use std::str::FromStr; use std::cell::RefCell; @@ -1563,7 +1562,7 @@ impl Clean for hir::Generics { } impl<'a, 'tcx> Clean for (&'a ty::Generics, - &'a Lrc>) { + &'a Bx<'tcx, ty::GenericPredicates<'tcx>>) { fn clean(&self, cx: &DocContext) -> Generics { use self::WherePredicate as WP; @@ -3991,7 +3990,7 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { None => return None, }; - for item in mem::replace(&mut items, Lrc::new(vec![])).iter() { + for item in mem::replace(&mut items, Bx(&[])).iter() { if item.ident.name == *segment { if path_it.peek().is_none() { return match item.def { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index aac0f9f94e329..9355883210111 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -480,7 +480,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }).collect(), }; let analysis = ty::CrateAnalysis { - access_levels: Lrc::new(AccessLevels::default()), name: name.to_string(), glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None }, }; @@ -504,12 +503,12 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt &arenas, &name, &output_filenames, - |tcx, analysis, _, result| { + |tcx, _, _, result| { if result.is_err() { sess.fatal("Compilation failed, aborting rustdoc"); } - let ty::CrateAnalysis { access_levels, .. } = analysis; + let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); // Convert from a NodeId set to a DefId set since we don't always have easy access // to the map from defid -> nodeid diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 349aa029ba8cb..fdd539806ed71 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,11 +11,13 @@ use self::Entry::*; use self::VacantEntryState::*; +use alloc::Layout; use collections::CollectionAllocErr; use cell::Cell; use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; +use ptr::NonNull; #[allow(deprecated)] use hash::{Hash, Hasher, BuildHasher, SipHasher13}; use iter::{FromIterator, FusedIterator}; @@ -832,6 +834,14 @@ impl HashMap self.table.capacity() } + /// Gets the underlying allocation used to store data + /// if such allocation exists + #[inline] + #[unstable(feature = "extract_raw_alloc", issue = "0")] + pub fn raw_alloc(&self) -> Option<(NonNull, Layout)> { + self.table.raw_alloc() + } + /// Reserves capacity for at least `additional` more elements to be inserted /// in the `HashMap`. The collection may reserve more space to avoid /// frequent reallocations. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 5ac3e8f9cf7d3..63fe1ed209ac0 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -13,6 +13,8 @@ use fmt; use hash::{Hash, BuildHasher}; use iter::{Chain, FromIterator, FusedIterator}; use ops::{BitOr, BitAnd, BitXor, Sub}; +use ptr::NonNull; +use alloc::Layout; use super::Recover; use super::map::{self, HashMap, Keys, RandomState}; @@ -250,6 +252,14 @@ impl HashSet self.map.capacity() } + /// Gets the underlying allocation used to store data + /// if such allocation exists + #[inline] + #[unstable(feature = "extract_raw_alloc", issue = "0")] + pub fn raw_alloc(&self) -> Option<(NonNull, Layout)> { + self.map.raw_alloc() + } + /// Reserves capacity for at least `additional` more elements to be inserted /// in the `HashSet`. The collection may reserve more space to avoid /// frequent reallocations. diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 479e6dccb90dd..1b4663857cd21 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -769,6 +769,18 @@ impl RawTable { } } + #[inline] + pub fn raw_alloc(&self) -> Option<(NonNull, Layout)> { + if self.capacity() == 0 { + return None; + } + let (layout, _) = calculate_layout::(self.capacity()) + .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); + unsafe { + Some((NonNull::new_unchecked(self.hashes.ptr()).cast(), layout)) + } + } + /// The hashtable's capacity, similar to a vector's. pub fn capacity(&self) -> usize { self.capacity_mask.wrapping_add(1) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 227017a9073fe..5a4ec387fb1b2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -224,6 +224,8 @@ mod node_id_inner { } } +impl_defer_dellocs_for_no_drop_type!([] NodeId); + pub use self::node_id_inner::NodeId; impl NodeId { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d0c4d1c7dce0a..020b16f5386ea 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -25,6 +25,7 @@ use self::AttributeType::*; use self::AttributeGate::*; +use rustc_data_structures::defer_deallocs::{DeferDeallocs, DeferredDeallocs}; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; use ast::{self, NodeId, PatKind, RangeEnd}; @@ -106,6 +107,13 @@ macro_rules! declare_features { } } +unsafe impl DeferDeallocs for Features { + fn defer(&self, deferred: &mut DeferredDeallocs) { + self.declared_lang_features.defer(deferred); + self.declared_lib_features.defer(deferred); + } +} + // If you change this, please modify src/doc/unstable-book as well. // // Don't ever remove anything from this list; set them to 'Removed'. diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 34fb71e4ddf68..b7dd749768be0 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -39,6 +39,7 @@ use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{Lrc, Lock}; extern crate arena; +#[macro_use] extern crate rustc_data_structures; #[macro_use] diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs index 473aa1bd1b8a4..ae6be0d08e4f1 100644 --- a/src/libsyntax_pos/span_encoding.rs +++ b/src/libsyntax_pos/span_encoding.rs @@ -53,6 +53,8 @@ impl Hash for Span { } } +impl_defer_dellocs_for_no_drop_type!([] Span); + /// Dummy span, both position and length are zero, syntax context is zero as well. /// This span is kept inline and encoded with format 0. pub const DUMMY_SP: Span = Span(0); diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 741877bb4c88f..db4e8bc076fa1 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -141,6 +141,8 @@ impl Decodable for Ident { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Symbol(u32); +impl_defer_dellocs_for_no_drop_type!([] Symbol); + // The interner is pointed to by a thread local value which is only set on the main thread // with parallelization is disabled. So we don't allow Symbol to transfer between threads // to avoid panics and other errors, even though it would be memory safe to do so.