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:
commit
164e1297e1
@ -1162,7 +1162,7 @@ fn confirm_builtin_unsize_candidate(
|
||||
let InferOk { mut obligations, .. } = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(DefineOpaqueTypes::No, target, source_trait)
|
||||
.sup(DefineOpaqueTypes::Yes, target, source_trait)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
|
||||
// Register one obligation for 'a: 'b.
|
||||
@ -1229,7 +1229,7 @@ fn confirm_builtin_unsize_candidate(
|
||||
let InferOk { obligations, .. } = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::No, b, a)
|
||||
.eq(DefineOpaqueTypes::Yes, b, a)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
|
||||
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
|
||||
@ -1277,7 +1277,7 @@ fn confirm_builtin_unsize_candidate(
|
||||
let InferOk { obligations, .. } = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::No, target, new_struct)
|
||||
.eq(DefineOpaqueTypes::Yes, target, new_struct)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
nested.extend(obligations);
|
||||
|
||||
@ -1310,7 +1310,7 @@ fn confirm_builtin_unsize_candidate(
|
||||
let InferOk { mut obligations, .. } = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::No, target, new_tuple)
|
||||
.eq(DefineOpaqueTypes::Yes, target, new_tuple)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
|
||||
// Add a nested `T: Unsize<U>` predicate.
|
||||
|
26
tests/ui/impl-trait/trait_upcasting.rs
Normal file
26
tests/ui/impl-trait/trait_upcasting.rs
Normal 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() {}
|
18
tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs
Normal file
18
tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs
Normal 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() {}
|
@ -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`.
|
@ -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);
|
||||
|
||||
@ -6,7 +8,6 @@
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &Foo<[i32]> = &x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
@ -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`.
|
@ -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] {
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &[i32] = &x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
@ -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`.
|
@ -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)]
|
||||
|
||||
@ -6,7 +8,6 @@
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &([i32],) = &x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
@ -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`.
|
26
tests/ui/impl-trait/unsized_coercion.next.stderr
Normal file
26
tests/ui/impl-trait/unsized_coercion.next.stderr
Normal 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`.
|
21
tests/ui/impl-trait/unsized_coercion.rs
Normal file
21
tests/ui/impl-trait/unsized_coercion.rs
Normal 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() {}
|
12
tests/ui/impl-trait/unsized_coercion2.old.stderr
Normal file
12
tests/ui/impl-trait/unsized_coercion2.old.stderr
Normal 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`.
|
21
tests/ui/impl-trait/unsized_coercion2.rs
Normal file
21
tests/ui/impl-trait/unsized_coercion2.rs
Normal 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() {}
|
38
tests/ui/impl-trait/unsized_coercion3.next.stderr
Normal file
38
tests/ui/impl-trait/unsized_coercion3.next.stderr
Normal 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`.
|
26
tests/ui/impl-trait/unsized_coercion3.old.stderr
Normal file
26
tests/ui/impl-trait/unsized_coercion3.old.stderr
Normal 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`.
|
24
tests/ui/impl-trait/unsized_coercion3.rs
Normal file
24
tests/ui/impl-trait/unsized_coercion3.rs
Normal 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() {}
|
20
tests/ui/impl-trait/unsized_coercion4.rs
Normal file
20
tests/ui/impl-trait/unsized_coercion4.rs
Normal 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() {}
|
14
tests/ui/impl-trait/unsized_coercion5.next.stderr
Normal file
14
tests/ui/impl-trait/unsized_coercion5.next.stderr
Normal 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`.
|
38
tests/ui/impl-trait/unsized_coercion5.old.stderr
Normal file
38
tests/ui/impl-trait/unsized_coercion5.old.stderr
Normal 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`.
|
24
tests/ui/impl-trait/unsized_coercion5.rs
Normal file
24
tests/ui/impl-trait/unsized_coercion5.rs
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user