Auto merge of #89125 - Aaron1011:remove-intercrate-cache, r=jackh726
Don't use projection cache or candidate cache in intercrate mode Fixes #88969 It appears that *just* disabling the evaluation cache (in #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.
This commit is contained in:
commit
7743c9fadd
@ -834,6 +834,10 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
|||||||
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
||||||
) -> Result<Option<Ty<'tcx>>, InProgress> {
|
) -> Result<Option<Ty<'tcx>>, InProgress> {
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
|
// Don't use the projection cache in intercrate mode -
|
||||||
|
// the `infcx` may be re-used between intercrate in non-intercrate
|
||||||
|
// mode, which could lead to using incorrect cache results.
|
||||||
|
let use_cache = !selcx.is_intercrate();
|
||||||
|
|
||||||
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
|
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
|
||||||
let cache_key = ProjectionCacheKey::new(projection_ty);
|
let cache_key = ProjectionCacheKey::new(projection_ty);
|
||||||
@ -846,7 +850,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
|||||||
// bounds. It might be the case that we want two distinct caches,
|
// bounds. It might be the case that we want two distinct caches,
|
||||||
// or else another kind of cache entry.
|
// or else another kind of cache entry.
|
||||||
|
|
||||||
let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
|
let cache_result = if use_cache {
|
||||||
|
infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
match cache_result {
|
match cache_result {
|
||||||
Ok(()) => debug!("no cache"),
|
Ok(()) => debug!("no cache"),
|
||||||
Err(ProjectionCacheEntry::Ambiguous) => {
|
Err(ProjectionCacheEntry::Ambiguous) => {
|
||||||
@ -871,7 +879,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
|||||||
// should ensure that, unless this happens within a snapshot that's
|
// should ensure that, unless this happens within a snapshot that's
|
||||||
// rolled back, fulfillment or evaluation will notice the cycle.
|
// rolled back, fulfillment or evaluation will notice the cycle.
|
||||||
|
|
||||||
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
|
if use_cache {
|
||||||
|
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
|
||||||
|
}
|
||||||
return Err(InProgress);
|
return Err(InProgress);
|
||||||
}
|
}
|
||||||
Err(ProjectionCacheEntry::Recur) => {
|
Err(ProjectionCacheEntry::Recur) => {
|
||||||
@ -953,20 +963,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
|||||||
.map_or(false, |res| res.must_apply_considering_regions())
|
.map_or(false, |res| res.must_apply_considering_regions())
|
||||||
});
|
});
|
||||||
|
|
||||||
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
|
if use_cache {
|
||||||
|
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
|
||||||
|
}
|
||||||
obligations.extend(result.obligations);
|
obligations.extend(result.obligations);
|
||||||
Ok(Some(result.value))
|
Ok(Some(result.value))
|
||||||
}
|
}
|
||||||
Ok(ProjectedTy::NoProgress(projected_ty)) => {
|
Ok(ProjectedTy::NoProgress(projected_ty)) => {
|
||||||
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
|
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
|
||||||
let result = Normalized { value: projected_ty, obligations: vec![] };
|
let result = Normalized { value: projected_ty, obligations: vec![] };
|
||||||
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
|
if use_cache {
|
||||||
|
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
|
||||||
|
}
|
||||||
// No need to extend `obligations`.
|
// No need to extend `obligations`.
|
||||||
Ok(Some(result.value))
|
Ok(Some(result.value))
|
||||||
}
|
}
|
||||||
Err(ProjectionTyError::TooManyCandidates) => {
|
Err(ProjectionTyError::TooManyCandidates) => {
|
||||||
debug!("opt_normalize_projection_type: too many candidates");
|
debug!("opt_normalize_projection_type: too many candidates");
|
||||||
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
|
if use_cache {
|
||||||
|
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
|
||||||
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Err(ProjectionTyError::TraitSelectionError(_)) => {
|
Err(ProjectionTyError::TraitSelectionError(_)) => {
|
||||||
@ -976,7 +992,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
|||||||
// Trait`, which when processed will cause the error to be
|
// Trait`, which when processed will cause the error to be
|
||||||
// reported later
|
// reported later
|
||||||
|
|
||||||
infcx.inner.borrow_mut().projection_cache().error(cache_key);
|
if use_cache {
|
||||||
|
infcx.inner.borrow_mut().projection_cache().error(cache_key);
|
||||||
|
}
|
||||||
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
|
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
|
||||||
obligations.extend(result.obligations);
|
obligations.extend(result.obligations);
|
||||||
Ok(Some(result.value))
|
Ok(Some(result.value))
|
||||||
|
@ -314,6 +314,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_intercrate(&self) -> bool {
|
||||||
|
self.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
|
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
|
||||||
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
|
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
|
||||||
match pred.constness {
|
match pred.constness {
|
||||||
@ -1197,6 +1201,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
|
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
|
||||||
|
// Neither the global nor local cache is aware of intercrate
|
||||||
|
// mode, so don't do any caching. In particular, we might
|
||||||
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
|
// and non-intercrate `SelectionContext`
|
||||||
|
if self.intercrate {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let pred = &cache_fresh_trait_pred.skip_binder();
|
let pred = &cache_fresh_trait_pred.skip_binder();
|
||||||
let trait_ref = pred.trait_ref;
|
let trait_ref = pred.trait_ref;
|
||||||
@ -1233,6 +1244,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
|
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
// Neither the global nor local cache is aware of intercrate
|
||||||
|
// mode, so don't do any caching. In particular, we might
|
||||||
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
|
// and non-intercrate `SelectionContext`
|
||||||
|
if self.intercrate {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
match result {
|
match result {
|
||||||
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
|
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
|
||||||
_ => true,
|
_ => true,
|
||||||
|
@ -8,6 +8,7 @@ LL | impl<A:Iterator> Foo<A::Item> for A { }
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
||||||
|
|
|
|
||||||
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
|
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
|
||||||
|
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user