Skip to content

Commit

Permalink
When checking whether an impl applies, constrain hidden types of opaq…
Browse files Browse the repository at this point in the history
…ue 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.
  • Loading branch information
oli-obk committed May 23, 2024
1 parent dc8d1bc commit 29a630e
Show file tree
Hide file tree
Showing 23 changed files with 127 additions and 116 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
.map_err(|e| {
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
})?;
Expand Down
13 changes: 8 additions & 5 deletions tests/ui/impl-trait/equality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo {
0
} else {
n + sum_to(n - 1)
//~^ ERROR cannot add `impl Foo` to `u32`
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
}
}

Expand All @@ -32,12 +32,15 @@ trait Leak: Sized {
}
impl<T> Leak for T {
default type T = ();
default fn leak(self) -> Self::T { panic!() }
default fn leak(self) -> Self::T {
panic!()
}
}
impl Leak for i32 {
type T = i32;
fn leak(self) -> i32 { self }
fn leak(self) -> i32 {
self
}
}

fn main() {
}
fn main() {}
15 changes: 4 additions & 11 deletions tests/ui/impl-trait/equality.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,13 @@ help: change the type of the numeric literal from `u32` to `i32`
LL | 0_i32
| ~~~

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

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

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0284, E0308.
For more information about an error, try `rustc --explain E0284`.
16 changes: 10 additions & 6 deletions tests/ui/impl-trait/nested_impl_trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,23 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
--> $DIR/nested_impl_trait.rs:6:46
|
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
|
= help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
help: consider further restricting this bound
|
LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
| +++++++++++++++++

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

error: aborting due to 7 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar {
}

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

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

error: aborting due to 1 previous error

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

This file was deleted.

3 changes: 1 addition & 2 deletions tests/ui/type-alias-impl-trait/constrain_in_projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@[next]check-pass
//@check-pass

#![feature(type_alias_impl_trait)]

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

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

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

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0283`.
3 changes: 1 addition & 2 deletions tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ impl Trait<u32> for Foo {

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

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
--> $DIR/issue-84660-unsoundness.rs:23:1
--> $DIR/issue-84660-unsoundness.rs:28:1
|
LL | impl<In, Out> Trait<Bar, In> for Out {
| ------------------------------------ first implementation here
Expand Down
23 changes: 23 additions & 0 deletions tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
--> $DIR/issue-84660-unsoundness.rs:22:37
|
LL | fn convert(_i: In) -> Self::Out {
| _____________________________________^
LL | |
LL | | unreachable!();
LL | | }
| |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`

error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
--> $DIR/issue-84660-unsoundness.rs:28:1
|
LL | impl<In, Out> Trait<Bar, In> for Out {
| ------------------------------------ first implementation here
...
LL | impl<In, Out> Trait<(), In> for Out {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0119, E0284.
For more information about an error, try `rustc --explain E0119`.
8 changes: 7 additions & 1 deletion tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an
// impl header being accepted was used to create unsoundness.

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

#![feature(type_alias_impl_trait)]

trait Foo {}
Expand All @@ -16,11 +20,13 @@ trait Trait<T, In> {
impl<In, Out> Trait<Bar, In> for Out {
type Out = Out;
fn convert(_i: In) -> Self::Out {
//[next]~^ ERROR: type annotations needed
unreachable!();
}
}

impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
impl<In, Out> Trait<(), In> for Out {
//~^ ERROR conflicting implementations of trait `Trait<Bar, _>`
type Out = In;
fn convert(i: In) -> Self::Out {
i
Expand Down
13 changes: 8 additions & 5 deletions tests/ui/type-alias-impl-trait/nested-tait-inference.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
#![feature(type_alias_impl_trait)]
#![allow(dead_code)]

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@check-pass

use std::fmt::Debug;

type FooX = impl Debug;

trait Foo<A> { }
trait Foo<A> {}

impl Foo<()> for () { }
impl Foo<()> for () {}

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

fn main() { }
fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0283]: type annotations needed: cannot satisfy `(): Foo<FooX>`
--> $DIR/nested-tait-inference2.rs:17:13
|
LL | fn foo() -> impl Foo<FooX> {
| ^^^^^^^^^^^^^^
|
note: multiple `impl`s satisfying `(): Foo<FooX>` found
--> $DIR/nested-tait-inference2.rs:14:1
|
LL | impl Foo<()> for () {}
| ^^^^^^^^^^^^^^^^^^^
LL | impl Foo<u32> for () {}
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0283`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
--> $DIR/nested-tait-inference2.rs:19:5
|
LL | ()
| ^^ cannot satisfy `impl Foo<FooX> == ()`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0284`.
7 changes: 6 additions & 1 deletion tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#![feature(type_alias_impl_trait)]
#![allow(dead_code)]

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

use std::fmt::Debug;

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

fn foo() -> impl Foo<FooX> {
//~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
//[current]~^ ERROR: cannot satisfy `(): Foo<FooX>`
()
//[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
}

fn main() {}
16 changes: 0 additions & 16 deletions tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,17 @@ note: previous use here
LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) }
| ^^^^^^^^^^^^^^^^^

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

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

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
14 changes: 0 additions & 14 deletions tests/ui/type-alias-impl-trait/self-referential-2.current.stderr

This file was deleted.

Loading

0 comments on commit 29a630e

Please sign in to comment.