diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index b50f6260ab301..8c5dc88184cda 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1162,7 +1162,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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` predicate. diff --git a/tests/ui/impl-trait/trait_upcasting.rs b/tests/ui/impl-trait/trait_upcasting.rs new file mode 100644 index 0000000000000..ce811004fae19 --- /dev/null +++ b/tests/ui/impl-trait/trait_upcasting.rs @@ -0,0 +1,26 @@ +//! Test that we allow unsizing `Trait` to `Trait` and vice versa + +//@ check-pass + +trait Trait {} + +impl Trait for U {} + +fn hello() -> &'static (dyn Trait + Send) { + if false { + let x = hello(); + let _: &'static dyn Trait<()> = x; + } + todo!() +} + +fn bye() -> &'static dyn Trait { + if false { + let mut x = bye(); + let y: &'static (dyn Trait<()> + Send) = &(); + x = y; + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs new file mode 100644 index 0000000000000..bed88db1accee --- /dev/null +++ b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs @@ -0,0 +1,18 @@ +//! Show an uninformative diagnostic that we could possibly improve in the future + +trait Trait {} + +impl Trait for U {} + +fn hello() -> &'static (dyn Trait + 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() {} diff --git a/tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr new file mode 100644 index 0000000000000..92da47b08e9f1 --- /dev/null +++ b/tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/trait_upcasting_reference_mismatch.rs:7:35 + | +LL | fn hello() -> &'static (dyn Trait + Send) { + | ^^^^^^^^^^ cannot infer type + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/unsize_adt.rs b/tests/ui/impl-trait/unsize_adt.rs index fce5094bd404c..825384b61e87a 100644 --- a/tests/ui/impl-trait/unsize_adt.rs +++ b/tests/ui/impl-trait/unsize_adt.rs @@ -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); @@ -6,7 +8,6 @@ fn hello() -> Foo<[impl Sized; 2]> { if false { let x = hello(); let _: &Foo<[i32]> = &x; - //~^ ERROR: mismatched types } todo!() } diff --git a/tests/ui/impl-trait/unsize_adt.stderr b/tests/ui/impl-trait/unsize_adt.stderr deleted file mode 100644 index 2b93b4a571b1b..0000000000000 --- a/tests/ui/impl-trait/unsize_adt.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/impl-trait/unsize_slice.rs b/tests/ui/impl-trait/unsize_slice.rs index ec0f162656400..b0cf1c7ca6d26 100644 --- a/tests/ui/impl-trait/unsize_slice.rs +++ b/tests/ui/impl-trait/unsize_slice.rs @@ -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!() } diff --git a/tests/ui/impl-trait/unsize_slice.stderr b/tests/ui/impl-trait/unsize_slice.stderr deleted file mode 100644 index 6a7fdb46163b9..0000000000000 --- a/tests/ui/impl-trait/unsize_slice.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/impl-trait/unsize_tuple.rs b/tests/ui/impl-trait/unsize_tuple.rs index 630b8fd430f1a..2678564f0e869 100644 --- a/tests/ui/impl-trait/unsize_tuple.rs +++ b/tests/ui/impl-trait/unsize_tuple.rs @@ -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 @@ fn hello() -> ([impl Sized; 2],) { if false { let x = hello(); let _: &([i32],) = &x; - //~^ ERROR: mismatched types } todo!() } diff --git a/tests/ui/impl-trait/unsize_tuple.stderr b/tests/ui/impl-trait/unsize_tuple.stderr deleted file mode 100644 index 8d3cf15887c08..0000000000000 --- a/tests/ui/impl-trait/unsize_tuple.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/impl-trait/unsized_coercion.next.stderr b/tests/ui/impl-trait/unsized_coercion.next.stderr new file mode 100644 index 0000000000000..49ac3f1845fb3 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion.next.stderr @@ -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 { + | ---------- 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`. diff --git a/tests/ui/impl-trait/unsized_coercion.rs b/tests/ui/impl-trait/unsized_coercion.rs new file mode 100644 index 0000000000000..46e040c1428a4 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion.rs @@ -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 { + if true { + let x = hello(); + //[next]~^ ERROR: type mismatch resolving `impl Trait <: dyn Trait` + let y: Box = x; + } + Box::new(1u32) //[next]~ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsized_coercion2.old.stderr b/tests/ui/impl-trait/unsized_coercion2.old.stderr new file mode 100644 index 0000000000000..a89d40f1130c1 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion2.old.stderr @@ -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 = 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` to `Box` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion2.rs b/tests/ui/impl-trait/unsized_coercion2.rs new file mode 100644 index 0000000000000..7368d47dbe2c0 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion2.rs @@ -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 { + if true { + let x = hello(); + let y: Box = x; + //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know + } + Box::new(1u32) +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr new file mode 100644 index 0000000000000..bab8d1cd83b30 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr @@ -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 { + | ------------------- 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::::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`. diff --git a/tests/ui/impl-trait/unsized_coercion3.old.stderr b/tests/ui/impl-trait/unsized_coercion3.old.stderr new file mode 100644 index 0000000000000..24a302d7007ab --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion3.old.stderr @@ -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 = 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 { + | ^^^^^^^^^^^^^^^^^^^ + = note: required for the cast from `Box` to `Box` + +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 = 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` to `Box` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion3.rs b/tests/ui/impl-trait/unsized_coercion3.rs new file mode 100644 index 0000000000000..85950ac583ebc --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion3.rs @@ -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 { + if true { + let x = hello(); + //[next]~^ ERROR: type mismatch resolving `impl Trait + ?Sized <: dyn Send` + let y: Box = 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() {} diff --git a/tests/ui/impl-trait/unsized_coercion4.rs b/tests/ui/impl-trait/unsized_coercion4.rs new file mode 100644 index 0000000000000..1c4d5462ceeb2 --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion4.rs @@ -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 { + if true { + let x = hello() as Box; + let y: Box = x; + } + Box::new(1u32) +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsized_coercion5.next.stderr b/tests/ui/impl-trait/unsized_coercion5.next.stderr new file mode 100644 index 0000000000000..5644ac7ab04bc --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion5.next.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/unsized_coercion5.rs:16:32 + | +LL | let y: Box = x as Box; + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send` + | | + | expected due to this + | + = note: expected struct `Box` + found struct `Box` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/unsized_coercion5.old.stderr b/tests/ui/impl-trait/unsized_coercion5.old.stderr new file mode 100644 index 0000000000000..b6437266f27dd --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion5.old.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/unsized_coercion5.rs:16:32 + | +LL | let y: Box = x as Box; + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `Send`, found trait `Trait + Send` + | | + | expected due to this + | + = note: expected struct `Box` + found struct `Box` + +error: cannot check whether the hidden type of opaque type satisfies auto traits + --> $DIR/unsized_coercion5.rs:16:32 + | +LL | let y: Box = x as Box; + | ^ + | + = 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 { + | ^^^^^^^^^^^^^^^^^^^ + = note: required for the cast from `Box` to `Box` + +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 = x as Box; + | ^ 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` to `Box` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/unsized_coercion5.rs b/tests/ui/impl-trait/unsized_coercion5.rs new file mode 100644 index 0000000000000..b007267a0066f --- /dev/null +++ b/tests/ui/impl-trait/unsized_coercion5.rs @@ -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 { + if true { + let x = hello(); + let y: Box = x as Box; + //[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() {}