X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_middle%2Fsrc%2Fty%2Fcontext.rs;h=a9a7a2c8b01cced710a674156f94c20ce246a95f;hb=c97b539e408ea353f4fde2f9251d598291fec421;hp=e802c71c64b8cb2521a5bc1fb8d441ad4fb9edb3;hpb=1ad234c3fc67099739ad92ff0020d0179ddc2491;p=rust.git diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e802c71c64b..a9a7a2c8b01 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -17,8 +17,8 @@ use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, - ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, FloatTy, FloatVar, FloatVid, - GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, + ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, + GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, Visibility, @@ -53,6 +53,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_middle::mir::FakeReadCause; +use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{CrateType, OutputFilenames}; @@ -142,7 +143,7 @@ pub struct CtxtInterners<'tcx> { canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List>>, - predicate: InternedSet<'tcx, PredicateS<'tcx>>, + predicate: InternedSet<'tcx, WithStableHash>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -190,20 +191,8 @@ fn intern_ty( self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); - - // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. - // Without incremental, we rarely stable-hash types, so let's not do it proactively. - let stable_hash = if flags.flags.intersects(TypeFlags::NEEDS_INFER) - || sess.opts.incremental.is_none() - { - Fingerprint::ZERO - } else { - let mut hasher = StableHasher::new(); - let mut hcx = - StableHashingContext::new(sess, definitions, cstore, source_span); - kind.hash_stable(&mut hcx, &mut hasher); - hasher.finish() - }; + let stable_hash = + self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); let ty_struct = TyS { kind, @@ -219,20 +208,54 @@ fn intern_ty( )) } + fn stable_hash<'a, T: HashStable>>( + &self, + flags: &ty::flags::FlagComputation, + sess: &'a Session, + definitions: &'a rustc_hir::definitions::Definitions, + cstore: &'a CrateStoreDyn, + source_span: &'a IndexVec, + val: &T, + ) -> Fingerprint { + // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. + // Without incremental, we rarely stable-hash types, so let's not do it proactively. + if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() { + Fingerprint::ZERO + } else { + let mut hasher = StableHasher::new(); + let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span); + val.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + } + } + #[inline(never)] - fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { + fn intern_predicate( + &self, + kind: Binder<'tcx, PredicateKind<'tcx>>, + sess: &Session, + definitions: &rustc_hir::definitions::Definitions, + cstore: &CrateStoreDyn, + source_span: &IndexVec, + ) -> Predicate<'tcx> { Predicate(Interned::new_unchecked( self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); + let stable_hash = + self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); + let predicate_struct = PredicateS { kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, }; - InternedInSet(self.arena.alloc(predicate_struct)) + InternedInSet( + self.arena + .alloc(WithStableHash { internee: predicate_struct, stable_hash }), + ) }) .0, )) @@ -1009,6 +1032,21 @@ pub struct FreeRegionInfo { pub is_impl_item: bool, } +/// This struct should only be created by `create_def`. +#[derive(Copy, Clone)] +pub struct TyCtxtFeed<'tcx> { + pub tcx: TyCtxt<'tcx>, + // Do not allow direct access, as downstream code must not mutate this field. + def_id: LocalDefId, +} + +impl<'tcx> TyCtxtFeed<'tcx> { + #[inline(always)] + pub fn def_id(&self) -> LocalDefId { + self.def_id + } +} + /// The central data structure of the compiler. It stores references /// to the various **arenas** and also houses the results of the /// various **compiler queries** that have been performed. See the @@ -1471,12 +1509,15 @@ pub fn def_path_debug_str(self, def_id: DefId) -> String { } /// Create a new definition within the incr. comp. engine. - pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) -> LocalDefId { + pub fn create_def( + self, + parent: LocalDefId, + data: hir::definitions::DefPathData, + ) -> TyCtxtFeed<'tcx> { // This function modifies `self.definitions` using a side-effect. // We need to ensure that these side effects are re-run by the incr. comp. engine. // Depending on the forever-red node will tell the graph that the calling query // needs to be re-evaluated. - use rustc_query_system::dep_graph::DepNodeIndex; self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); // The following call has the side effect of modifying the tables inside `definitions`. @@ -1493,23 +1534,38 @@ pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) // This is fine because: // - those queries are `eval_always` so we won't miss their result changing; // - this write will have happened before these queries are called. - self.definitions.write().create_def(parent, data) + let def_id = self.definitions.write().create_def(parent, data); + + TyCtxtFeed { tcx: self, def_id } } pub fn iter_local_def_id(self) -> impl Iterator + 'tcx { - // Create a dependency to the crate to be sure we re-execute this when the amount of + // Create a dependency to the red node to be sure we re-execute this when the amount of // definitions change. - self.ensure().hir_crate(()); - // Leak a read lock once we start iterating on definitions, to prevent adding new ones - // while iterating. If some query needs to add definitions, it should be `ensure`d above. - let definitions = self.definitions.leak(); - definitions.iter_local_def_id() + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + + let definitions = &self.definitions; + std::iter::from_generator(|| { + let mut i = 0; + + // Recompute the number of definitions each time, because our caller may be creating + // new ones. + while i < { definitions.read().num_definitions() } { + let local_def_index = rustc_span::def_id::DefIndex::from_usize(i); + yield LocalDefId { local_def_index }; + i += 1; + } + + // Leak a read lock once we finish iterating on definitions, to prevent adding new ones. + definitions.leak(); + }) } pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { // Create a dependency to the crate to be sure we re-execute this when the amount of // definitions change. - self.ensure().hir_crate(()); + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + // Leak a read lock once we start iterating on definitions, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. let definitions = self.definitions.leak(); @@ -2168,23 +2224,25 @@ fn hash(&self, s: &mut H) { } } -impl<'tcx> Borrow>> for InternedInSet<'tcx, PredicateS<'tcx>> { +impl<'tcx> Borrow>> + for InternedInSet<'tcx, WithStableHash>> +{ fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> { - fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash>> { + fn eq(&self, other: &InternedInSet<'tcx, WithStableHash>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. self.0.kind == other.0.kind } } -impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash>> {} -impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.kind.hash(s) @@ -2386,7 +2444,14 @@ pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> { #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { - self.interners.intern_predicate(binder) + self.interners.intern_predicate( + binder, + self.sess, + &self.definitions.read(), + &*self.untracked_resolutions.cstore, + // This is only used to create a stable hashing context. + &self.untracked_resolutions.source_span, + ) } #[inline] @@ -2604,13 +2669,8 @@ pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> { } #[inline] - pub fn mk_const(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const_internal(ty::ConstS { kind, ty }) - } - - #[inline] - pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const(ty::ConstKind::Infer(InferConst::Var(v)), ty) + pub fn mk_const(self, kind: impl Into>, ty: Ty<'tcx>) -> Const<'tcx> { + self.mk_const_internal(ty::ConstS { kind: kind.into(), ty }) } #[inline] @@ -2628,30 +2688,23 @@ pub fn mk_ty_infer(self, it: InferTy) -> Ty<'tcx> { self.mk_ty(Infer(it)) } - #[inline] - pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> { - self.mk_const(ty::ConstKind::Infer(ic), ty) - } - #[inline] pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { self.mk_ty(Param(ParamTy { index, name })) } - #[inline] - pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const(ty::ConstKind::Param(ParamConst { index, name }), ty) - } - pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() } GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const { .. } => { - self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into() - } + GenericParamDefKind::Const { .. } => self + .mk_const( + ParamConst { index: param.index, name: param.name }, + self.type_of(param.def_id), + ) + .into(), } }