Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not define opaque types when selecting impls #126258

Merged
merged 3 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -2563,7 +2563,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
.eq(DefineOpaqueTypes::No, 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: 5 additions & 8 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 satisfy `<u32 as Add<impl Foo>>::Output == i32`
//~^ ERROR cannot add `impl Foo` to `u32`
}
}

Expand All @@ -32,15 +32,12 @@ 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: 11 additions & 4 deletions tests/ui/impl-trait/equality.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,20 @@ help: change the type of the numeric literal from `u32` to `i32`
LL | 0_i32
| ~~~

error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
error[E0277]: cannot add `impl Foo` to `u32`
--> $DIR/equality.rs:24:11
|
LL | n + sum_to(n - 1)
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
| ^ 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>

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

Some errors have detailed explanations: E0284, E0308.
For more information about an error, try `rustc --explain E0284`.
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
16 changes: 6 additions & 10 deletions tests/ui/impl-trait/nested_impl_trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,19 @@ 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 `Debug` is not implemented for `impl Into<u32>`
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: 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 }
| +++++++++++++++++
= help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`

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 `Debug` is not implemented for `impl Into<u32>`
|
help: consider further restricting this bound
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
LL | fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
| +++++++++++++++++
= help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`

error: aborting due to 7 previous errors

Expand Down
9 changes: 9 additions & 0 deletions tests/ui/impl-trait/recursive-bound-eval.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/recursive-bound-eval.rs:20:13
|
LL | move || recursive_fn().parse()
| ^^^^^^^^^^^^^^ cannot infer type

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0282`.
24 changes: 24 additions & 0 deletions tests/ui/impl-trait/recursive-bound-eval.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Test that we can evaluate nested obligations when invoking methods on recursive calls on
//! an RPIT.

//@revisions: next current
//@[next] compile-flags: -Znext-solver

//@[current] check-pass

pub trait Parser<E> {
fn parse(&self) -> E;
}

impl<E, T: Fn() -> E> Parser<E> for T {
fn parse(&self) -> E {
self()
}
}

pub fn recursive_fn<E>() -> impl Parser<E> {
move || recursive_fn().parse()
//[next]~^ ERROR: type annotations needed
}

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
error[E0277]: can't compare `Bar` with `(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 E0275`.
For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
--> $DIR/constrain_in_projection.rs:24:14
|
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
| ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
|
= help: the trait `Trait<()>` is implemented for `Foo`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
3 changes: 2 additions & 1 deletion 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
//@check-pass
//@[next]check-pass

#![feature(type_alias_impl_trait)]

Expand All @@ -22,6 +22,7 @@ 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,19 +1,13 @@
error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
--> $DIR/constrain_in_projection2.rs:27:14
|
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
| ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
| ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
|
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`
= help: the following other types implement trait `Trait<T>`:
<Foo as Trait<()>>
<Foo as Trait<u32>>

error: aborting due to 1 previous error

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

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

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ 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
//[next]~^ ERROR: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
unreachable!();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
--> $DIR/nested-tait-inference.rs:12:13
--> $DIR/nested-tait-inference.rs:17:13
|
LL | fn foo() -> impl Foo<FooX> {
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
Expand Down
4 changes: 3 additions & 1 deletion tests/ui/type-alias-impl-trait/nested-tait-inference.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
//@check-pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

//@[next] check-pass

use std::fmt::Debug;

Expand All @@ -15,6 +15,8 @@ trait Foo<A> {}
impl Foo<()> for () {}

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
error[E0283]: type annotations needed: cannot satisfy `(): Foo<FooX>`
error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
--> $DIR/nested-tait-inference2.rs:17:13
|
LL | fn foo() -> impl Foo<FooX> {
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
LL |
LL | ()
| -- return type was inferred to be `()` here
|
note: multiple `impl`s satisfying `(): Foo<FooX>` found
--> $DIR/nested-tait-inference2.rs:14:1
|
LL | impl Foo<()> for () {}
| ^^^^^^^^^^^^^^^^^^^
LL | impl Foo<u32> for () {}
| ^^^^^^^^^^^^^^^^^^^^
= help: the following other types implement trait `Foo<A>`:
<() as Foo<()>>
<() as Foo<u32>>

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0283`.
For more information about this error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Foo<()> for () {}
impl Foo<u32> for () {}

fn foo() -> impl Foo<FooX> {
//[current]~^ ERROR: cannot satisfy `(): Foo<FooX>`
//[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
()
//[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,21 @@ note: previous use here
LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) }
| ^^^^^^^^^^^^^^^^^

error: concrete type differs from previous defining opaque type use
error[E0308]: mismatched types
--> $DIR/normalize-hidden-types.rs:43:25
|
LL | type Opaque = impl Sized;
| ---------- the expected opaque type
...
LL | let _: Opaque = dyn_hoops::<u8>(0);
| ^^^^^^^^^^^^^^^^^^ 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
| ^^^^
| ------ ^^^^^^^^^^^^^^^^^^ 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

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

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
14 changes: 14 additions & 0 deletions tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0277]: can't compare `i32` with `Foo`
--> $DIR/self-referential-2.rs:10:13
|
LL | fn bar() -> Bar {
| ^^^ no implementation for `i32 == Foo`
LL | 42_i32
| ------ return type was inferred to be `i32` here
|
= help: the trait `PartialEq<Foo>` is not implemented for `i32`
= help: the trait `PartialEq` is implemented for `i32`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
4 changes: 2 additions & 2 deletions tests/ui/type-alias-impl-trait/self-referential-2.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass
//@[next] check-pass
#![feature(type_alias_impl_trait)]

type Foo = impl std::fmt::Debug;
type Bar = impl PartialEq<Foo>;

fn bar() -> Bar {
42_i32
42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
}

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/self-referential-3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;

fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
//~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>`
//~^ ERROR can't compare `&i32` with `Bar<'a, 'b>`
i
}

Expand Down
12 changes: 8 additions & 4 deletions tests/ui/type-alias-impl-trait/self-referential-3.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
error[E0275]: overflow normalizing the type alias `Bar<'a, 'b>`
error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
--> $DIR/self-referential-3.rs:7:31
|
LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
| ^^^^^^^^^^^
| ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>`
LL |
LL | i
| - return type was inferred to be `&i32` here
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
= help: the trait `PartialEq<Bar<'a, 'b>>` is not implemented for `&i32`
= help: the trait `PartialEq` is implemented for `i32`

error: aborting due to 1 previous error

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