Auto merge of #125610 - oli-obk:define_opaque_types14, r=compiler-errors

Allow constraining opaque types during various unsizing casts

allows unsizing of tuples, arrays and Adts to constraint opaque types in their generic parameters to concrete types on either side of the unsizing cast.

Also allows constraining opaque types during trait object casts that only differ in auto traits or lifetimes.

cc #116652
This commit is contained in:
bors 2024-06-25 05:09:30 +00:00
commit 164e1297e1
21 changed files with 330 additions and 61 deletions

View File

@ -1162,7 +1162,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { mut obligations, .. } = self let InferOk { mut obligations, .. } = self
.infcx .infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.sup(DefineOpaqueTypes::No, target, source_trait) .sup(DefineOpaqueTypes::Yes, target, source_trait)
.map_err(|_| Unimplemented)?; .map_err(|_| Unimplemented)?;
// Register one obligation for 'a: 'b. // Register one obligation for 'a: 'b.
@ -1229,7 +1229,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self let InferOk { obligations, .. } = self
.infcx .infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, b, a) .eq(DefineOpaqueTypes::Yes, b, a)
.map_err(|_| Unimplemented)?; .map_err(|_| Unimplemented)?;
ImplSource::Builtin(BuiltinImplSource::Misc, obligations) ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
@ -1277,7 +1277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self let InferOk { obligations, .. } = self
.infcx .infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, target, new_struct) .eq(DefineOpaqueTypes::Yes, target, new_struct)
.map_err(|_| Unimplemented)?; .map_err(|_| Unimplemented)?;
nested.extend(obligations); nested.extend(obligations);
@ -1310,7 +1310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { mut obligations, .. } = self let InferOk { mut obligations, .. } = self
.infcx .infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, target, new_tuple) .eq(DefineOpaqueTypes::Yes, target, new_tuple)
.map_err(|_| Unimplemented)?; .map_err(|_| Unimplemented)?;
// Add a nested `T: Unsize<U>` predicate. // Add a nested `T: Unsize<U>` predicate.

View File

@ -0,0 +1,26 @@
//! Test that we allow unsizing `Trait<Concrete>` to `Trait<Opaque>` and vice versa
//@ check-pass
trait Trait<T> {}
impl<T, U> Trait<T> for U {}
fn hello() -> &'static (dyn Trait<impl Sized> + Send) {
if false {
let x = hello();
let _: &'static dyn Trait<()> = x;
}
todo!()
}
fn bye() -> &'static dyn Trait<impl Sized> {
if false {
let mut x = bye();
let y: &'static (dyn Trait<()> + Send) = &();
x = y;
}
todo!()
}
fn main() {}

View File

@ -0,0 +1,18 @@
//! Show an uninformative diagnostic that we could possibly improve in the future
trait Trait<T> {}
impl<T, U> Trait<T> for U {}
fn hello() -> &'static (dyn Trait<impl Sized> + Send) {
//~^ ERROR: type annotations needed
if false {
let x = hello();
let _: &'static dyn Trait<()> = &x;
//^ Note the extra `&`, paired with the blanket impl causing
// `impl Sized` to never get a hidden type registered.
}
todo!()
}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/trait_upcasting_reference_mismatch.rs:7:35
|
LL | fn hello() -> &'static (dyn Trait<impl Sized> + Send) {
| ^^^^^^^^^^ cannot infer type
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.

View File

@ -1,4 +1,6 @@
//! Test that we do not allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`. //! Test that we allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`.
//@check-pass
struct Foo<T: ?Sized>(T); struct Foo<T: ?Sized>(T);
@ -6,7 +8,6 @@ fn hello() -> Foo<[impl Sized; 2]> {
if false { if false {
let x = hello(); let x = hello();
let _: &Foo<[i32]> = &x; let _: &Foo<[i32]> = &x;
//~^ ERROR: mismatched types
} }
todo!() todo!()
} }

View File

@ -1,17 +0,0 @@
error[E0308]: mismatched types
--> $DIR/unsize_adt.rs:8:30
|
LL | fn hello() -> Foo<[impl Sized; 2]> {
| ---------- the found opaque type
...
LL | let _: &Foo<[i32]> = &x;
| ----------- ^^ expected `&Foo<[i32]>`, found `&Foo<[impl Sized; 2]>`
| |
| expected due to this
|
= note: expected reference `&Foo<[i32]>`
found reference `&Foo<[impl Sized; 2]>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,10 +1,11 @@
//! Test that we do not allow unsizing `[Opaque; N]` to `[Concrete]`. //! Test that we allow unsizing `[Opaque; N]` to `[Concrete]`.
//@check-pass
fn hello() -> [impl Sized; 2] { fn hello() -> [impl Sized; 2] {
if false { if false {
let x = hello(); let x = hello();
let _: &[i32] = &x; let _: &[i32] = &x;
//~^ ERROR: mismatched types
} }
todo!() todo!()
} }

View File

@ -1,17 +0,0 @@
error[E0308]: mismatched types
--> $DIR/unsize_slice.rs:6:25
|
LL | fn hello() -> [impl Sized; 2] {
| ---------- the found opaque type
...
LL | let _: &[i32] = &x;
| ------ ^^ expected `&[i32]`, found `&[impl Sized; 2]`
| |
| expected due to this
|
= note: expected reference `&[i32]`
found reference `&[impl Sized; 2]`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,4 +1,6 @@
//! Test that we do not allow unsizing `([Opaque; N],)` to `([Concrete],)`. //! Test that we allow unsizing `([Opaque; N],)` to `([Concrete],)`.
//@check-pass
#![feature(unsized_tuple_coercion)] #![feature(unsized_tuple_coercion)]
@ -6,7 +8,6 @@ fn hello() -> ([impl Sized; 2],) {
if false { if false {
let x = hello(); let x = hello();
let _: &([i32],) = &x; let _: &([i32],) = &x;
//~^ ERROR: mismatched types
} }
todo!() todo!()
} }

View File

@ -1,17 +0,0 @@
error[E0308]: mismatched types
--> $DIR/unsize_tuple.rs:8:28
|
LL | fn hello() -> ([impl Sized; 2],) {
| ---------- the found opaque type
...
LL | let _: &([i32],) = &x;
| --------- ^^ expected `&([i32],)`, found `&([impl Sized; 2],)`
| |
| expected due to this
|
= note: expected reference `&([i32],)`
found reference `&([impl Sized; 2],)`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,26 @@
error[E0271]: type mismatch resolving `impl Trait <: dyn Trait`
--> $DIR/unsized_coercion.rs:14:17
|
LL | let x = hello();
| ^^^^^^^ types differ
error[E0308]: mismatched types
--> $DIR/unsized_coercion.rs:18:14
|
LL | fn hello() -> Box<impl Trait> {
| ---------- the expected opaque type
...
LL | Box::new(1u32)
| -------- ^^^^ types differ
| |
| arguments to this function are incorrect
|
= note: expected opaque type `impl Trait`
found type `u32`
note: associated function defined here
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0271, E0308.
For more information about an error, try `rustc --explain E0271`.

View File

@ -0,0 +1,21 @@
//! This test checks that opaque types get unsized instead of
//! constraining their hidden type to a trait object.
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
//@[old] check-pass
trait Trait {}
impl Trait for u32 {}
fn hello() -> Box<impl Trait> {
if true {
let x = hello();
//[next]~^ ERROR: type mismatch resolving `impl Trait <: dyn Trait`
let y: Box<dyn Trait> = x;
}
Box::new(1u32) //[next]~ ERROR: mismatched types
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion2.rs:15:33
|
LL | let y: Box<dyn Trait> = x;
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
//! This test checks that opaque types get unsized instead of
//! constraining their hidden type to a trait object.
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
//@[next] check-pass
trait Trait {}
impl Trait for u32 {}
fn hello() -> Box<impl Trait + ?Sized> {
if true {
let x = hello();
let y: Box<dyn Trait> = x;
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
}
Box::new(1u32)
}
fn main() {}

View File

@ -0,0 +1,38 @@
error[E0271]: type mismatch resolving `impl Trait + ?Sized <: dyn Send`
--> $DIR/unsized_coercion3.rs:13:17
|
LL | let x = hello();
| ^^^^^^^ types differ
error[E0308]: mismatched types
--> $DIR/unsized_coercion3.rs:19:14
|
LL | fn hello() -> Box<impl Trait + ?Sized> {
| ------------------- the expected opaque type
...
LL | Box::new(1u32)
| -------- ^^^^ types differ
| |
| arguments to this function are incorrect
|
= note: expected opaque type `impl Trait + ?Sized`
found type `u32`
note: associated function defined here
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion3.rs:19:14
|
LL | Box::new(1u32)
| -------- ^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
note: required by a bound in `Box::<T>::new`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0271, E0277, E0308.
For more information about an error, try `rustc --explain E0271`.

View File

@ -0,0 +1,26 @@
error: cannot check whether the hidden type of opaque type satisfies auto traits
--> $DIR/unsized_coercion3.rs:15:32
|
LL | let y: Box<dyn Send> = x;
| ^
|
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
note: opaque type is declared here
--> $DIR/unsized_coercion3.rs:11:19
|
LL | fn hello() -> Box<impl Trait + ?Sized> {
| ^^^^^^^^^^^^^^^^^^^
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`
error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion3.rs:15:32
|
LL | let y: Box<dyn Send> = x;
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Send>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,24 @@
//! This test checks that opaque types get unsized instead of
//! constraining their hidden type to a trait object.
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
trait Trait {}
impl Trait for u32 {}
fn hello() -> Box<impl Trait + ?Sized> {
if true {
let x = hello();
//[next]~^ ERROR: type mismatch resolving `impl Trait + ?Sized <: dyn Send`
let y: Box<dyn Send> = x;
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
//[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
}
Box::new(1u32)
//[next]~^ ERROR: mismatched types
//[next]~| ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
}
fn main() {}

View File

@ -0,0 +1,20 @@
//! This test checks that opaque types get unsized instead of
//! constraining their hidden type to a trait object.
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
//@check-pass
trait Trait {}
impl Trait for u32 {}
fn hello() -> Box<impl Trait + ?Sized> {
if true {
let x = hello() as Box<u32>;
let y: Box<dyn Send> = x;
}
Box::new(1u32)
}
fn main() {}

View File

@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/unsized_coercion5.rs:16:32
|
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
| |
| expected due to this
|
= note: expected struct `Box<dyn Send>`
found struct `Box<dyn Trait + Send>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,38 @@
error[E0308]: mismatched types
--> $DIR/unsized_coercion5.rs:16:32
|
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send`
| |
| expected due to this
|
= note: expected struct `Box<dyn Send>`
found struct `Box<dyn Trait + Send>`
error: cannot check whether the hidden type of opaque type satisfies auto traits
--> $DIR/unsized_coercion5.rs:16:32
|
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
| ^
|
= note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
note: opaque type is declared here
--> $DIR/unsized_coercion5.rs:13:19
|
LL | fn hello() -> Box<impl Trait + ?Sized> {
| ^^^^^^^^^^^^^^^^^^^
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
--> $DIR/unsized_coercion5.rs:16:32
|
LL | let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl Trait + ?Sized`
= note: required for the cast from `Box<impl Trait + ?Sized>` to `Box<dyn Trait + Send>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

View File

@ -0,0 +1,24 @@
//! This test checks that opaque types get unsized instead of
//! constraining their hidden type to a trait object.
//@ revisions: next old
//@[next] compile-flags: -Znext-solver
#![feature(trait_upcasting)]
trait Trait {}
impl Trait for u32 {}
fn hello() -> Box<impl Trait + ?Sized> {
if true {
let x = hello();
let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
//[old]~| ERROR: cannot check whether the hidden type of opaque type satisfies auto traits
//~^^^ ERROR: mismatched types
}
Box::new(1u32)
}
fn main() {}