Skip to content

Commit 7199946

Browse files
committed
Make selection and evaluation caches use constness
1 parent 4bdfb46 commit 7199946

File tree

2 files changed

+59
-32
lines changed
  • compiler
    • rustc_middle/src/traits
    • rustc_trait_selection/src/traits/select

2 files changed

+59
-32
lines changed

compiler/rustc_middle/src/traits/select.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use rustc_hir::def_id::DefId;
1212
use rustc_query_system::cache::Cache;
1313

1414
pub type SelectionCache<'tcx> = Cache<
15-
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
15+
ty::ConstnessAnd<ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>>,
1616
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
1717
>;
1818

1919
pub type EvaluationCache<'tcx> =
20-
Cache<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, EvaluationResult>;
20+
Cache<ty::ParamEnvAnd<'tcx, ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>>, EvaluationResult>;
2121

2222
/// The selection process begins by considering all impls, where
2323
/// clauses, and so forth that might resolve an obligation. Sometimes

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use rustc_middle::ty::fast_reject;
4141
use rustc_middle::ty::print::with_no_trimmed_paths;
4242
use rustc_middle::ty::relate::TypeRelation;
4343
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
44+
use rustc_middle::ty::WithConstness;
4445
use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
4546
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable};
4647
use rustc_span::symbol::sym;
@@ -141,7 +142,7 @@ struct TraitObligationStack<'prev, 'tcx> {
141142

142143
/// The trait ref from `obligation` but "freshened" with the
143144
/// selection-context's freshener. Used to check for recursion.
144-
fresh_trait_ref: ty::PolyTraitRef<'tcx>,
145+
fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
145146

146147
/// Starts out equal to `depth` -- if, during evaluation, we
147148
/// encounter a cycle, then we will set this flag to the minimum
@@ -804,7 +805,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
804805
// terms of `Fn` etc, but we could probably make this more
805806
// precise still.
806807
let unbound_input_types =
807-
stack.fresh_trait_ref.skip_binder().substs.types().any(|ty| ty.is_fresh());
808+
stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh());
808809
// This check was an imperfect workaround for a bug in the old
809810
// intercrate mode; it should be removed when that goes away.
810811
if unbound_input_types && self.intercrate {
@@ -925,7 +926,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
925926
fn check_evaluation_cache(
926927
&self,
927928
param_env: ty::ParamEnv<'tcx>,
928-
trait_ref: ty::PolyTraitRef<'tcx>,
929+
trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
929930
) -> Option<EvaluationResult> {
930931
let tcx = self.tcx();
931932
if self.can_use_global_caches(param_env) {
@@ -939,7 +940,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
939940
fn insert_evaluation_cache(
940941
&mut self,
941942
param_env: ty::ParamEnv<'tcx>,
942-
trait_ref: ty::PolyTraitRef<'tcx>,
943+
trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
943944
dep_node: DepNodeIndex,
944945
result: EvaluationResult,
945946
) {
@@ -1024,18 +1025,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10241025
let tcx = self.tcx();
10251026
// Respect const trait obligations
10261027
if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
1027-
match candidate {
1028-
// const impl
1029-
ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {}
1030-
// const param
1031-
ParamCandidate(ty::ConstnessAnd { constness: hir::Constness::Const, .. }) => {}
1032-
// auto trait impl
1033-
AutoImplCandidate(..) => {}
1034-
// FIXME check if this is right, but this would allow Sized impls
1035-
// BuiltinCandidate { .. } => {}
1036-
_ => {
1037-
// reject all other types of candidates
1038-
return Err(Unimplemented);
1028+
if Some(obligation.predicate.skip_binder().trait_ref.def_id)
1029+
!= tcx.lang_items().sized_trait()
1030+
// const Sized bounds are skipped
1031+
{
1032+
match candidate {
1033+
// const impl
1034+
ImplCandidate(def_id)
1035+
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
1036+
// const param
1037+
ParamCandidate(ty::ConstnessAnd {
1038+
constness: hir::Constness::Const, ..
1039+
}) => {}
1040+
// auto trait impl
1041+
AutoImplCandidate(..) => {}
1042+
// FIXME check if this is right, but this would allow Sized impls
1043+
// BuiltinCandidate { .. } => {}
1044+
_ => {
1045+
// reject all other types of candidates
1046+
return Err(Unimplemented);
1047+
}
10391048
}
10401049
}
10411050
}
@@ -1121,13 +1130,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11211130
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
11221131
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
11231132
let tcx = self.tcx();
1124-
let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
1133+
let pred = &cache_fresh_trait_pred.skip_binder();
1134+
let trait_ref = pred.trait_ref;
11251135
if self.can_use_global_caches(param_env) {
1126-
if let Some(res) = tcx.selection_cache.get(&param_env.and(*trait_ref), tcx) {
1136+
if let Some(res) = tcx
1137+
.selection_cache
1138+
.get(&param_env.and(trait_ref).with_constness(pred.constness), tcx)
1139+
{
11271140
return Some(res);
11281141
}
11291142
}
1130-
self.infcx.selection_cache.get(&param_env.and(*trait_ref), tcx)
1143+
self.infcx
1144+
.selection_cache
1145+
.get(&param_env.and(trait_ref).with_constness(pred.constness), tcx)
11311146
}
11321147

11331148
/// Determines whether can we safely cache the result
@@ -1164,7 +1179,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11641179
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
11651180
) {
11661181
let tcx = self.tcx();
1167-
let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
1182+
let pred = cache_fresh_trait_pred.skip_binder();
1183+
let trait_ref = pred.trait_ref;
11681184

11691185
if !self.can_cache_candidate(&candidate) {
11701186
debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable");
@@ -1178,14 +1194,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11781194
if !candidate.needs_infer() {
11791195
debug!(?trait_ref, ?candidate, "insert_candidate_cache global");
11801196
// This may overwrite the cache with the same value.
1181-
tcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
1197+
tcx.selection_cache.insert(
1198+
param_env.and(trait_ref).with_constness(pred.constness),
1199+
dep_node,
1200+
candidate,
1201+
);
11821202
return;
11831203
}
11841204
}
11851205
}
11861206

11871207
debug!(?trait_ref, ?candidate, "insert_candidate_cache local");
1188-
self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
1208+
self.infcx.selection_cache.insert(
1209+
param_env.and(trait_ref).with_constness(pred.constness),
1210+
dep_node,
1211+
candidate,
1212+
);
11891213
}
11901214

11911215
/// Matches a predicate against the bounds of its self type.
@@ -2015,8 +2039,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20152039

20162040
fn match_fresh_trait_refs(
20172041
&self,
2018-
previous: ty::PolyTraitRef<'tcx>,
2019-
current: ty::PolyTraitRef<'tcx>,
2042+
previous: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
2043+
current: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
20202044
param_env: ty::ParamEnv<'tcx>,
20212045
) -> bool {
20222046
let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
@@ -2028,8 +2052,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20282052
previous_stack: TraitObligationStackList<'o, 'tcx>,
20292053
obligation: &'o TraitObligation<'tcx>,
20302054
) -> TraitObligationStack<'o, 'tcx> {
2031-
let fresh_trait_ref =
2032-
obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener);
2055+
let fresh_trait_ref = obligation
2056+
.predicate
2057+
.to_poly_trait_ref()
2058+
.fold_with(&mut self.freshener)
2059+
.with_constness(obligation.predicate.skip_binder().constness);
20332060

20342061
let dfn = previous_stack.cache.next_dfn();
20352062
let depth = previous_stack.depth() + 1;
@@ -2308,7 +2335,7 @@ struct ProvisionalEvaluationCache<'tcx> {
23082335
/// - then we determine that `E` is in error -- we will then clear
23092336
/// all cache values whose DFN is >= 4 -- in this case, that
23102337
/// means the cached value for `F`.
2311-
map: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ProvisionalEvaluation>>,
2338+
map: RefCell<FxHashMap<ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ProvisionalEvaluation>>,
23122339
}
23132340

23142341
/// A cache value for the provisional cache: contains the depth-first
@@ -2340,7 +2367,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
23402367
/// `reached_depth` (from the returned value).
23412368
fn get_provisional(
23422369
&self,
2343-
fresh_trait_ref: ty::PolyTraitRef<'tcx>,
2370+
fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
23442371
) -> Option<ProvisionalEvaluation> {
23452372
debug!(
23462373
?fresh_trait_ref,
@@ -2358,7 +2385,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
23582385
&self,
23592386
from_dfn: usize,
23602387
reached_depth: usize,
2361-
fresh_trait_ref: ty::PolyTraitRef<'tcx>,
2388+
fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
23622389
result: EvaluationResult,
23632390
) {
23642391
debug!(?from_dfn, ?fresh_trait_ref, ?result, "insert_provisional");
@@ -2436,7 +2463,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
24362463
fn on_completion(
24372464
&self,
24382465
dfn: usize,
2439-
mut op: impl FnMut(ty::PolyTraitRef<'tcx>, EvaluationResult),
2466+
mut op: impl FnMut(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, EvaluationResult),
24402467
) {
24412468
debug!(?dfn, "on_completion");
24422469

0 commit comments

Comments
 (0)