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.
This commit is contained in:
parent
dc8d1bc373
commit
29a630eb72
23 changed files with 126 additions and 115 deletions
|
@ -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()))
|
||||
})?;
|
||||
|
|
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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: 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(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
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`.
|
|
@ -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)]
|
||||
|
||||
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
|
@ -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`.
|
|
@ -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 {}
|
||||
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
|
@ -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`.
|
|
@ -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;
|
||||
|
@ -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() {}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
--> $DIR/nested-tait-inference2.rs:13:13
|
||||
|
|
||||
LL | fn foo() -> impl Foo<FooX> {
|
||||
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
|
||||
LL |
|
||||
LL | ()
|
||||
| -- return type was inferred to be `()` here
|
||||
|
|
||||
= 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 E0277`.
|
|
@ -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
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
|
||||
|
|
||||
= 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
|
||||
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
|
||||
|
@ -52,4 +48,3 @@ LL | None
|
|||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
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`.
|
|
@ -1,14 +1,14 @@
|
|||
//@ 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)]
|
||||
|
||||
type Foo = impl std::fmt::Debug;
|
||||
type Bar = impl PartialEq<Foo>;
|
||||
|
||||
fn bar() -> Bar {
|
||||
42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
|
||||
42_i32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -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 can't compare `&i32` with `Bar<'a, 'b>`
|
||||
//~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>`
|
||||
i
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
|
||||
error[E0275]: overflow normalizing the type alias `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
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: the trait `PartialEq<Bar<'a, 'b>>` is not implemented for `&i32`
|
||||
= help: the trait `PartialEq` is implemented for `i32`
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
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`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue