Skip to content

Commit 29a630e

Browse files
committed
When checking whether an impl applies, constrain hidden types of opaque types.
We already handle this case this way on the coherence side, and it matches the new solver's behaviour. While there is some breakage around type-alias-impl-trait (see new "type annotations needed" in tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs), no stable code breaks, and no new stable code is accepted.
1 parent dc8d1bc commit 29a630e

23 files changed

+127
-116
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
25392539
let InferOk { obligations, .. } = self
25402540
.infcx
25412541
.at(&cause, obligation.param_env)
2542-
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
2542+
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
25432543
.map_err(|e| {
25442544
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
25452545
})?;

tests/ui/impl-trait/equality.rs

+8-5
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 add `impl Foo` to `u32`
25+
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
2626
}
2727
}
2828

@@ -32,12 +32,15 @@ trait Leak: Sized {
3232
}
3333
impl<T> Leak for T {
3434
default type T = ();
35-
default fn leak(self) -> Self::T { panic!() }
35+
default fn leak(self) -> Self::T {
36+
panic!()
37+
}
3638
}
3739
impl Leak for i32 {
3840
type T = i32;
39-
fn leak(self) -> i32 { self }
41+
fn leak(self) -> i32 {
42+
self
43+
}
4044
}
4145

42-
fn main() {
43-
}
46+
fn main() {}

tests/ui/impl-trait/equality.stderr

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

25-
error[E0277]: cannot add `impl Foo` to `u32`
25+
error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
2626
--> $DIR/equality.rs:24:11
2727
|
2828
LL | n + sum_to(n - 1)
29-
| ^ no implementation for `u32 + impl Foo`
30-
|
31-
= help: the trait `Add<impl Foo>` is not implemented for `u32`
32-
= help: the following other types implement trait `Add<Rhs>`:
33-
<&'a u32 as Add<u32>>
34-
<&u32 as Add<&u32>>
35-
<u32 as Add<&u32>>
36-
<u32 as Add>
29+
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
3730

3831
error: aborting due to 2 previous errors; 1 warning emitted
3932

40-
Some errors have detailed explanations: E0277, E0308.
41-
For more information about an error, try `rustc --explain E0277`.
33+
Some errors have detailed explanations: E0284, E0308.
34+
For more information about an error, try `rustc --explain E0284`.

tests/ui/impl-trait/nested_impl_trait.stderr

+10-6
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,23 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
4646
--> $DIR/nested_impl_trait.rs:6:46
4747
|
4848
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
49-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
49+
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
5050
|
51-
= help: the trait `Into<U>` is implemented for `T`
52-
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
51+
help: consider further restricting this bound
52+
|
53+
LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
54+
| +++++++++++++++++
5355

5456
error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
5557
--> $DIR/nested_impl_trait.rs:19:34
5658
|
5759
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
58-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
60+
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
61+
|
62+
help: consider further restricting this bound
5963
|
60-
= help: the trait `Into<U>` is implemented for `T`
61-
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
64+
LL | fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
65+
| +++++++++++++++++
6266

6367
error: aborting due to 7 previous errors
6468

tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar {
1111
}
1212

1313
fn foo() -> Foo {
14-
//~^ ERROR can't compare `Bar` with `(Foo, i32)`
14+
//~^ ERROR overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
1515
Bar
1616
}
1717

Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
1-
error[E0277]: can't compare `Bar` with `(Foo, i32)`
1+
error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
22
--> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13
33
|
44
LL | fn foo() -> Foo {
5-
| ^^^ no implementation for `Bar == (Foo, i32)`
6-
LL |
7-
LL | Bar
8-
| --- return type was inferred to be `Bar` here
9-
|
10-
= help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar`
11-
= help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar`
5+
| ^^^
126

137
error: aborting due to 1 previous error
148

15-
For more information about this error, try `rustc --explain E0277`.
9+
For more information about this error, try `rustc --explain E0275`.

tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr

-11
This file was deleted.

tests/ui/type-alias-impl-trait/constrain_in_projection.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//@ revisions: current next
55
//@ ignore-compare-mode-next-solver (explicit revisions)
66
//@[next] compile-flags: -Znext-solver
7-
//@[next]check-pass
7+
//@check-pass
88

99
#![feature(type_alias_impl_trait)]
1010

@@ -22,7 +22,6 @@ impl Trait<()> for Foo {
2222

2323
fn bop(_: Bar) {
2424
let x = <Foo as Trait<Bar>>::Assoc::default();
25-
//[current]~^ `Foo: Trait<Bar>` is not satisfied
2625
}
2726

2827
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
1+
error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
22
--> $DIR/constrain_in_projection2.rs:27:14
33
|
44
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
5-
| ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
5+
| ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
66
|
7-
= help: the following other types implement trait `Trait<T>`:
8-
<Foo as Trait<()>>
9-
<Foo as Trait<u32>>
7+
note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
8+
--> $DIR/constrain_in_projection2.rs:18:1
9+
|
10+
LL | impl Trait<()> for Foo {
11+
| ^^^^^^^^^^^^^^^^^^^^^^
12+
...
13+
LL | impl Trait<u32> for Foo {
14+
| ^^^^^^^^^^^^^^^^^^^^^^^
15+
= note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
1016

1117
error: aborting due to 1 previous error
1218

13-
For more information about this error, try `rustc --explain E0277`.
19+
For more information about this error, try `rustc --explain E0283`.

tests/ui/type-alias-impl-trait/constrain_in_projection2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ impl Trait<u32> for Foo {
2525

2626
fn bop(_: Bar) {
2727
let x = <Foo as Trait<Bar>>::Assoc::default();
28-
//[next]~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
29-
//[current]~^^ ERROR: `Foo: Trait<Bar>` is not satisfied
28+
//~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
3029
}
3130

3231
fn main() {}

tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr renamed to tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
2-
--> $DIR/issue-84660-unsoundness.rs:23:1
2+
--> $DIR/issue-84660-unsoundness.rs:28:1
33
|
44
LL | impl<In, Out> Trait<Bar, In> for Out {
55
| ------------------------------------ first implementation here
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
2+
--> $DIR/issue-84660-unsoundness.rs:22:37
3+
|
4+
LL | fn convert(_i: In) -> Self::Out {
5+
| _____________________________________^
6+
LL | |
7+
LL | | unreachable!();
8+
LL | | }
9+
| |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
10+
11+
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
12+
--> $DIR/issue-84660-unsoundness.rs:28:1
13+
|
14+
LL | impl<In, Out> Trait<Bar, In> for Out {
15+
| ------------------------------------ first implementation here
16+
...
17+
LL | impl<In, Out> Trait<(), In> for Out {
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
19+
20+
error: aborting due to 2 previous errors
21+
22+
Some errors have detailed explanations: E0119, E0284.
23+
For more information about an error, try `rustc --explain E0119`.

tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
// Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an
22
// impl header being accepted was used to create unsoundness.
33

4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
48
#![feature(type_alias_impl_trait)]
59

610
trait Foo {}
@@ -16,11 +20,13 @@ trait Trait<T, In> {
1620
impl<In, Out> Trait<Bar, In> for Out {
1721
type Out = Out;
1822
fn convert(_i: In) -> Self::Out {
23+
//[next]~^ ERROR: type annotations needed
1924
unreachable!();
2025
}
2126
}
2227

23-
impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
28+
impl<In, Out> Trait<(), In> for Out {
29+
//~^ ERROR conflicting implementations of trait `Trait<Bar, _>`
2430
type Out = In;
2531
fn convert(i: In) -> Self::Out {
2632
i
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
#![feature(type_alias_impl_trait)]
22
#![allow(dead_code)]
33

4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
//@check-pass
8+
49
use std::fmt::Debug;
510

611
type FooX = impl Debug;
712

8-
trait Foo<A> { }
13+
trait Foo<A> {}
914

10-
impl Foo<()> for () { }
15+
impl Foo<()> for () {}
1116

1217
fn foo() -> impl Foo<FooX> {
13-
//~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
14-
// FIXME(type-alias-impl-trait): We could probably make this work.
1518
()
1619
}
1720

18-
fn main() { }
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0283]: type annotations needed: cannot satisfy `(): Foo<FooX>`
2+
--> $DIR/nested-tait-inference2.rs:17:13
3+
|
4+
LL | fn foo() -> impl Foo<FooX> {
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: multiple `impl`s satisfying `(): Foo<FooX>` found
8+
--> $DIR/nested-tait-inference2.rs:14:1
9+
|
10+
LL | impl Foo<()> for () {}
11+
| ^^^^^^^^^^^^^^^^^^^
12+
LL | impl Foo<u32> for () {}
13+
| ^^^^^^^^^^^^^^^^^^^^
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0283`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
2+
--> $DIR/nested-tait-inference2.rs:19:5
3+
|
4+
LL | ()
5+
| ^^ cannot satisfy `impl Foo<FooX> == ()`
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0284`.

tests/ui/type-alias-impl-trait/nested-tait-inference2.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#![feature(type_alias_impl_trait)]
22
#![allow(dead_code)]
33

4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
48
use std::fmt::Debug;
59

610
type FooX = impl Debug;
@@ -11,8 +15,9 @@ impl Foo<()> for () {}
1115
impl Foo<u32> for () {}
1216

1317
fn foo() -> impl Foo<FooX> {
14-
//~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
18+
//[current]~^ ERROR: cannot satisfy `(): Foo<FooX>`
1519
()
20+
//[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
1621
}
1722

1823
fn main() {}

tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr

-16
This file was deleted.

tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr

+8-13
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,17 @@ note: previous use here
2222
LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) }
2323
| ^^^^^^^^^^^^^^^^^
2424

25-
error[E0308]: mismatched types
25+
error: concrete type differs from previous defining opaque type use
2626
--> $DIR/normalize-hidden-types.rs:43:25
2727
|
28-
LL | type Opaque = impl Sized;
29-
| ---------- the expected opaque type
30-
...
3128
LL | let _: Opaque = dyn_hoops::<u8>(0);
32-
| ------ ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())`
33-
| |
34-
| expected due to this
35-
|
36-
= note: expected opaque type `typeck::Opaque`
37-
found raw pointer `*const (dyn FnOnce(()) + 'static)`
38-
= help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>`
39-
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
29+
| ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
30+
|
31+
note: previous use here
32+
--> $DIR/normalize-hidden-types.rs:44:9
33+
|
34+
LL | None
35+
| ^^^^
4036

4137
error: concrete type differs from previous defining opaque type use
4238
--> $DIR/normalize-hidden-types.rs:52:25
@@ -52,4 +48,3 @@ LL | None
5248

5349
error: aborting due to 4 previous errors
5450

55-
For more information about this error, try `rustc --explain E0308`.

tests/ui/type-alias-impl-trait/self-referential-2.current.stderr

-14
This file was deleted.

0 commit comments

Comments
 (0)