Skip to content

Commit 22162a8

Browse files
committed
Auto merge of #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 #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, ..) cc #122192 (comment)
2 parents a330e49 + 0714168 commit 22162a8

File tree

8 files changed

+50
-9
lines changed

8 files changed

+50
-9
lines changed

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

+13
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;
@@ -1557,6 +1558,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15571558
if self.is_intercrate() {
15581559
return None;
15591560
}
1561+
1562+
// Opaque types are not part of the global cache key, so we'd be caching and loading
1563+
// values, even though we don't have all the information that went into them.
1564+
if !self.infcx.defining_opaque_types().is_empty() {
1565+
return None;
1566+
}
1567+
15601568
let tcx = self.tcx();
15611569
let pred = cache_fresh_trait_pred.skip_binder();
15621570

@@ -1595,6 +1603,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15951603
if self.is_intercrate() {
15961604
return false;
15971605
}
1606+
// Opaque types are not part of the global cache key, so we'd be caching and loading
1607+
// values, even though we don't have all the information that went into them.
1608+
if !self.infcx.defining_opaque_types().is_empty() {
1609+
return false;
1610+
}
15981611
match result {
15991612
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
16001613
_ => true,

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
}

tests/ui/impl-trait/equality.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo {
2222
0
2323
} else {
2424
n + sum_to(n - 1)
25-
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
25+
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == u32`
2626
}
2727
}
2828

tests/ui/impl-trait/equality.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ help: change the type of the numeric literal from `u32` to `i32`
2222
LL | 0_i32
2323
| ~~~
2424

25-
error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
25+
error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == u32`
2626
--> $DIR/equality.rs:24:11
2727
|
2828
LL | n + sum_to(n - 1)
29-
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
29+
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == u32`
3030

3131
error: aborting due to 2 previous errors; 1 warning emitted
3232

tests/ui/type-alias-impl-trait/escaping-bound-var.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ trait Test<'a> {}
88

99
pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
1010
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
11+
//~| ERROR unconstrained opaque type
1112

1213
impl Trait<'_> for () {
1314
type Assoc = ();

tests/ui/type-alias-impl-trait/escaping-bound-var.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ note: lifetime declared here
1010
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
1111
| ^^
1212

13-
error: aborting due to 1 previous error
13+
error: unconstrained opaque type
14+
--> $DIR/escaping-bound-var.rs:9:47
15+
|
16+
LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
17+
| ^^^^^^^^^^^^^
18+
|
19+
= note: `Foo` must be used in combination with a concrete type within the same module
20+
21+
error: aborting due to 2 previous errors
1422

1523
For more information about this error, try `rustc --explain E0657`.

0 commit comments

Comments
 (0)