Skip to content

Commit 7743c9f

Browse files
committed
Auto merge of rust-lang#89125 - Aaron1011:remove-intercrate-cache, r=jackh726
Don't use projection cache or candidate cache in intercrate mode Fixes rust-lang#88969 It appears that *just* disabling the evaluation cache (in rust-lang#88994) leads to other issues involving intercrate mode caching. I suspect that since we now always end up performing the full evaluation in intercrate mode, we end up 'polluting' the candidate and projection caches with results that depend on being in intercrate mode in some way. Previously, we might have hit a cached evaluation (stored during non-intercrate mode), and skipped doing this extra work in intercrate mode. The whole situation with intercrate mode caching is turning into a mess. Ideally, we would remove intercrate mode entirely - however, this might require waiting on Chalk.
2 parents dda2a0e + 6dbb9d4 commit 7743c9f

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

compiler/rustc_trait_selection/src/traits/project.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,10 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
834834
obligations: &mut Vec<PredicateObligation<'tcx>>,
835835
) -> Result<Option<Ty<'tcx>>, InProgress> {
836836
let infcx = selcx.infcx();
837+
// Don't use the projection cache in intercrate mode -
838+
// the `infcx` may be re-used between intercrate in non-intercrate
839+
// mode, which could lead to using incorrect cache results.
840+
let use_cache = !selcx.is_intercrate();
837841

838842
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
839843
let cache_key = ProjectionCacheKey::new(projection_ty);
@@ -846,7 +850,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
846850
// bounds. It might be the case that we want two distinct caches,
847851
// or else another kind of cache entry.
848852

849-
let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
853+
let cache_result = if use_cache {
854+
infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
855+
} else {
856+
Ok(())
857+
};
850858
match cache_result {
851859
Ok(()) => debug!("no cache"),
852860
Err(ProjectionCacheEntry::Ambiguous) => {
@@ -871,7 +879,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
871879
// should ensure that, unless this happens within a snapshot that's
872880
// rolled back, fulfillment or evaluation will notice the cycle.
873881

874-
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
882+
if use_cache {
883+
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
884+
}
875885
return Err(InProgress);
876886
}
877887
Err(ProjectionCacheEntry::Recur) => {
@@ -953,20 +963,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
953963
.map_or(false, |res| res.must_apply_considering_regions())
954964
});
955965

956-
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
966+
if use_cache {
967+
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
968+
}
957969
obligations.extend(result.obligations);
958970
Ok(Some(result.value))
959971
}
960972
Ok(ProjectedTy::NoProgress(projected_ty)) => {
961973
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
962974
let result = Normalized { value: projected_ty, obligations: vec![] };
963-
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
975+
if use_cache {
976+
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
977+
}
964978
// No need to extend `obligations`.
965979
Ok(Some(result.value))
966980
}
967981
Err(ProjectionTyError::TooManyCandidates) => {
968982
debug!("opt_normalize_projection_type: too many candidates");
969-
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
983+
if use_cache {
984+
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
985+
}
970986
Ok(None)
971987
}
972988
Err(ProjectionTyError::TraitSelectionError(_)) => {
@@ -976,7 +992,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
976992
// Trait`, which when processed will cause the error to be
977993
// reported later
978994

979-
infcx.inner.borrow_mut().projection_cache().error(cache_key);
995+
if use_cache {
996+
infcx.inner.borrow_mut().projection_cache().error(cache_key);
997+
}
980998
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
981999
obligations.extend(result.obligations);
9821000
Ok(Some(result.value))

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

+18
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
314314
self.infcx.tcx
315315
}
316316

317+
pub fn is_intercrate(&self) -> bool {
318+
self.intercrate
319+
}
320+
317321
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
318322
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
319323
match pred.constness {
@@ -1197,6 +1201,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11971201
param_env: ty::ParamEnv<'tcx>,
11981202
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
11991203
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
1204+
// Neither the global nor local cache is aware of intercrate
1205+
// mode, so don't do any caching. In particular, we might
1206+
// re-use the same `InferCtxt` with both an intercrate
1207+
// and non-intercrate `SelectionContext`
1208+
if self.intercrate {
1209+
return None;
1210+
}
12001211
let tcx = self.tcx();
12011212
let pred = &cache_fresh_trait_pred.skip_binder();
12021213
let trait_ref = pred.trait_ref;
@@ -1233,6 +1244,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12331244
&self,
12341245
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
12351246
) -> bool {
1247+
// Neither the global nor local cache is aware of intercrate
1248+
// mode, so don't do any caching. In particular, we might
1249+
// re-use the same `InferCtxt` with both an intercrate
1250+
// and non-intercrate `SelectionContext`
1251+
if self.intercrate {
1252+
return false;
1253+
}
12361254
match result {
12371255
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
12381256
_ => true,

src/test/ui/coherence/coherence-projection-conflict-orphan.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | impl<A:Iterator> Foo<A::Item> for A { }
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
99
|
1010
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
11+
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
1112

1213
error: aborting due to previous error
1314

0 commit comments

Comments
 (0)