Skip to content

Commit 56d23c2

Browse files
committed
Auto merge of rust-lang#126024 - oli-obk:candidate_key_caching_is_unsound_yay, r=<try>
Do not use global cache for selection candidates if opaque types can be constrained fixes rust-lang#105787 r? `@ghost` This is certainly the crudest way to make the cache sound wrt opaque types, but if perf lets us get away with this, let's do it in the old solver and let the new solver fix this correctly once and for all. If perf is prohibitively bad, I'll look into alternatives (using canonical queries, checking whether any opaque types got constrained or whether decisions based on the availability of opaque types were made, still using the cache for things that can't possibly constrain opaque types (probably sound, famous last words), ..) cc rust-lang#122192 (comment) * [ ] check if this actually fixes rust-lang#105787 or if it just fixes the opaque type reproducer
2 parents db8aca4 + 319843a commit 56d23c2

File tree

7 files changed

+56
-12
lines changed

7 files changed

+56
-12
lines changed

compiler/rustc_middle/src/traits/select.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ use rustc_errors::ErrorGuaranteed;
99

1010
use crate::ty;
1111

12-
use rustc_hir::def_id::DefId;
12+
use rustc_hir::def_id::{DefId, LocalDefId};
1313
use rustc_macros::{HashStable, TypeVisitable};
1414
use rustc_query_system::cache::Cache;
1515

1616
pub type SelectionCache<'tcx> = Cache<
1717
// This cache does not use `ParamEnvAnd` in its keys because `ParamEnv::and` can replace
1818
// caller bounds with an empty list if the `TraitPredicate` looks global, which may happen
1919
// after erasing lifetimes from the predicate.
20-
(ty::ParamEnv<'tcx>, ty::TraitPredicate<'tcx>),
20+
(&'tcx ty::List<LocalDefId>, ty::ParamEnv<'tcx>, ty::TraitPredicate<'tcx>),
2121
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
2222
>;
2323

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast};
4949
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
5050
use rustc_span::symbol::sym;
5151
use rustc_span::Symbol;
52+
use rustc_type_ir::InferCtxtLike as _;
5253

5354
use std::cell::{Cell, RefCell};
5455
use std::cmp;
@@ -1559,13 +1560,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15591560
}
15601561
let tcx = self.tcx();
15611562
let pred = cache_fresh_trait_pred.skip_binder();
1563+
let opaques = self.infcx.defining_opaque_types();
15621564

15631565
if self.can_use_global_caches(param_env) {
1564-
if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) {
1566+
if let Some(res) = tcx.selection_cache.get(&(opaques, param_env, pred), tcx) {
15651567
return Some(res);
15661568
}
15671569
}
1568-
self.infcx.selection_cache.get(&(param_env, pred), tcx)
1570+
self.infcx.selection_cache.get(&(opaques, param_env, pred), tcx)
15691571
}
15701572

15711573
/// Determines whether can we safely cache the result
@@ -1611,6 +1613,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16111613
) {
16121614
let tcx = self.tcx();
16131615
let pred = cache_fresh_trait_pred.skip_binder();
1616+
let opaques = self.infcx.defining_opaque_types();
16141617

16151618
if !self.can_cache_candidate(&candidate) {
16161619
debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");
@@ -1624,14 +1627,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16241627
if !candidate.has_infer() {
16251628
debug!(?pred, ?candidate, "insert_candidate_cache global");
16261629
// This may overwrite the cache with the same value.
1627-
tcx.selection_cache.insert((param_env, pred), dep_node, candidate);
1630+
tcx.selection_cache.insert((opaques, param_env, pred), dep_node, candidate);
16281631
return;
16291632
}
16301633
}
16311634
}
16321635

16331636
debug!(?pred, ?candidate, "insert_candidate_cache local");
1634-
self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate);
1637+
self.infcx.selection_cache.insert((opaques, param_env, pred), dep_node, candidate);
16351638
}
16361639

16371640
/// Looks at the item bounds of the projection or opaque type.

tests/crashes/119272.rs tests/ui/auto-traits/opaque_type_candidate_selection.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
//@ known-bug: #119272
1+
//! used to ICE: #119272
22
#![feature(type_alias_impl_trait)]
33
mod defining_scope {
44
use super::*;
55
pub type Alias<T> = impl Sized;
66

77
pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
8+
//~^ ERROR: type annotations needed
89
x
910
}
1011
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0284]: type annotations needed
2+
--> $DIR/opaque_type_candidate_selection.rs:7:20
3+
|
4+
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
5+
| ^ cannot infer type
6+
|
7+
= note: cannot satisfy `<Alias<T> as Trait<T>>::Assoc == _`
8+
note: required because it appears within the type `Container<Alias<T>, T>`
9+
--> $DIR/opaque_type_candidate_selection.rs:13:8
10+
|
11+
LL | struct Container<T: Trait<U>, U> {
12+
| ^^^^^^^^^
13+
= help: unsized fn params are gated as an unstable feature
14+
help: function arguments must have a statically known size, borrowed types always have a known size
15+
|
16+
LL | pub fn cast<T>(x: &Container<Alias<T>, T>) -> Container<T, T> {
17+
| +
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0284`.

tests/ui/coherence/occurs-check/opaques.next.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0119]: conflicting implementations of trait `Trait<_>`
2-
--> $DIR/opaques.rs:30:1
2+
--> $DIR/opaques.rs:28:1
33
|
44
LL | impl<T> Trait<T> for T {
55
| ---------------------- first implementation here
@@ -8,7 +8,7 @@ LL | impl<T> Trait<T> for defining_scope::Alias<T> {
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
99

1010
error[E0282]: type annotations needed
11-
--> $DIR/opaques.rs:13:20
11+
--> $DIR/opaques.rs:11:20
1212
|
1313
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
1414
| ^ cannot infer type
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0284]: type annotations needed
2+
--> $DIR/opaques.rs:11:20
3+
|
4+
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
5+
| ^ cannot infer type
6+
|
7+
= note: cannot satisfy `<Alias<T> as Trait<T>>::Assoc == _`
8+
note: required because it appears within the type `Container<Alias<T>, T>`
9+
--> $DIR/opaques.rs:17:8
10+
|
11+
LL | struct Container<T: Trait<U>, U> {
12+
| ^^^^^^^^^
13+
= help: unsized fn params are gated as an unstable feature
14+
help: function arguments must have a statically known size, borrowed types always have a known size
15+
|
16+
LL | pub fn cast<T>(x: &Container<Alias<T>, T>) -> Container<T, T> {
17+
| +
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0284`.

tests/ui/coherence/occurs-check/opaques.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33

44
// A regression test for #105787
55

6-
//@[old] known-bug: #105787
7-
//@[old] check-pass
86
#![feature(type_alias_impl_trait)]
97
mod defining_scope {
108
use super::*;
119
pub type Alias<T> = impl Sized;
1210

1311
pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
14-
//[next]~^ ERROR type annotations needed
12+
//~^ ERROR type annotations needed
1513
x
1614
}
1715
}

0 commit comments

Comments
 (0)