diff options
| author | Deadbeef <ent3rm4n@gmail.com> | 2021-07-24 19:12:24 +0800 |
|---|---|---|
| committer | Deadbeef <ent3rm4n@gmail.com> | 2021-08-13 09:28:49 +0000 |
| commit | 3bab45d2acc24bf21c3fc760de0942b437e1ad54 (patch) | |
| tree | a427fb0379b68acd5d1f67cacc1796618cebecfc /compiler/rustc_trait_selection/src | |
| parent | 36ace4c0ada61df5a409a756bb161177876cfde8 (diff) | |
Make selection and evaluation caches use constness
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 87 |
1 files changed, 57 insertions, 30 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index be5787cda03..5321993f0ce 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -41,6 +41,7 @@ use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; +use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::sym; @@ -141,7 +142,7 @@ struct TraitObligationStack<'prev, 'tcx> { /// The trait ref from `obligation` but "freshened" with the /// selection-context's freshener. Used to check for recursion. - fresh_trait_ref: ty::PolyTraitRef<'tcx>, + fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, /// Starts out equal to `depth` -- if, during evaluation, we /// encounter a cycle, then we will set this flag to the minimum @@ -804,7 +805,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // terms of `Fn` etc, but we could probably make this more // precise still. let unbound_input_types = - stack.fresh_trait_ref.skip_binder().substs.types().any(|ty| ty.is_fresh()); + stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh()); // This check was an imperfect workaround for a bug in the old // intercrate mode; it should be removed when that goes away. if unbound_input_types && self.intercrate { @@ -925,7 +926,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_evaluation_cache( &self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ) -> Option<EvaluationResult> { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { @@ -939,7 +940,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn insert_evaluation_cache( &mut self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, dep_node: DepNodeIndex, result: EvaluationResult, ) { @@ -1024,18 +1025,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); // Respect const trait obligations if let hir::Constness::Const = obligation.predicate.skip_binder().constness { - match candidate { - // const impl - ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} - // const param - ParamCandidate(ty::ConstnessAnd { constness: hir::Constness::Const, .. }) => {} - // auto trait impl - AutoImplCandidate(..) => {} - // FIXME check if this is right, but this would allow Sized impls - // BuiltinCandidate { .. } => {} - _ => { - // reject all other types of candidates - return Err(Unimplemented); + if Some(obligation.predicate.skip_binder().trait_ref.def_id) + != tcx.lang_items().sized_trait() + // const Sized bounds are skipped + { + match candidate { + // const impl + ImplCandidate(def_id) + if tcx.impl_constness(def_id) == hir::Constness::Const => {} + // const param + ParamCandidate(ty::ConstnessAnd { + constness: hir::Constness::Const, .. + }) => {} + // auto trait impl + AutoImplCandidate(..) => {} + // FIXME check if this is right, but this would allow Sized impls + // BuiltinCandidate { .. } => {} + _ => { + // reject all other types of candidates + return Err(Unimplemented); + } } } } @@ -1121,13 +1130,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> { let tcx = self.tcx(); - let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref; + let pred = &cache_fresh_trait_pred.skip_binder(); + let trait_ref = pred.trait_ref; if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.selection_cache.get(¶m_env.and(*trait_ref), tcx) { + if let Some(res) = tcx + .selection_cache + .get(¶m_env.and(trait_ref).with_constness(pred.constness), tcx) + { return Some(res); } } - self.infcx.selection_cache.get(¶m_env.and(*trait_ref), tcx) + self.infcx + .selection_cache + .get(¶m_env.and(trait_ref).with_constness(pred.constness), tcx) } /// Determines whether can we safely cache the result @@ -1164,7 +1179,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) { let tcx = self.tcx(); - let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; + let pred = cache_fresh_trait_pred.skip_binder(); + let trait_ref = pred.trait_ref; if !self.can_cache_candidate(&candidate) { debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable"); @@ -1178,14 +1194,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !candidate.needs_infer() { debug!(?trait_ref, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. - tcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate); + tcx.selection_cache.insert( + param_env.and(trait_ref).with_constness(pred.constness), + dep_node, + candidate, + ); return; } } } debug!(?trait_ref, ?candidate, "insert_candidate_cache local"); - self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate); + self.infcx.selection_cache.insert( + param_env.and(trait_ref).with_constness(pred.constness), + dep_node, + candidate, + ); } /// Matches a predicate against the bounds of its self type. @@ -2015,8 +2039,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_fresh_trait_refs( &self, - previous: ty::PolyTraitRef<'tcx>, - current: ty::PolyTraitRef<'tcx>, + previous: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, + current: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, param_env: ty::ParamEnv<'tcx>, ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx(), param_env); @@ -2028,8 +2052,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &'o TraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = - obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener); + let fresh_trait_ref = obligation + .predicate + .to_poly_trait_ref() + .fold_with(&mut self.freshener) + .with_constness(obligation.predicate.skip_binder().constness); let dfn = previous_stack.cache.next_dfn(); let depth = previous_stack.depth() + 1; @@ -2308,7 +2335,7 @@ struct ProvisionalEvaluationCache<'tcx> { /// - then we determine that `E` is in error -- we will then clear /// all cache values whose DFN is >= 4 -- in this case, that /// means the cached value for `F`. - map: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ProvisionalEvaluation>>, + map: RefCell<FxHashMap<ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ProvisionalEvaluation>>, } /// A cache value for the provisional cache: contains the depth-first @@ -2340,7 +2367,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// `reached_depth` (from the returned value). fn get_provisional( &self, - fresh_trait_ref: ty::PolyTraitRef<'tcx>, + fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ) -> Option<ProvisionalEvaluation> { debug!( ?fresh_trait_ref, @@ -2358,7 +2385,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { &self, from_dfn: usize, reached_depth: usize, - fresh_trait_ref: ty::PolyTraitRef<'tcx>, + fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, result: EvaluationResult, ) { debug!(?from_dfn, ?fresh_trait_ref, ?result, "insert_provisional"); @@ -2436,7 +2463,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { fn on_completion( &self, dfn: usize, - mut op: impl FnMut(ty::PolyTraitRef<'tcx>, EvaluationResult), + mut op: impl FnMut(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, EvaluationResult), ) { debug!(?dfn, "on_completion"); |
