Skip to content

Commit

Permalink
Auto merge of rust-lang#125610 - oli-obk:define_opaque_types14, r=com…
Browse files Browse the repository at this point in the history
…piler-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 rust-lang#116652
  • Loading branch information
bors committed Jun 25, 2024
2 parents fc555cd + 45da035 commit 164e129
Show file tree
Hide file tree
Showing 21 changed files with 330 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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<U>` predicate.
Expand Down
26 changes: 26 additions & 0 deletions tests/ui/impl-trait/trait_upcasting.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions tests/ui/impl-trait/trait_upcasting_reference_mismatch.rs
Original file line number Diff line number Diff line change
@@ -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() {}
9 changes: 9 additions & 0 deletions tests/ui/impl-trait/trait_upcasting_reference_mismatch.stderr
Original file line number Diff line number Diff line change
@@ -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`.
5 changes: 3 additions & 2 deletions tests/ui/impl-trait/unsize_adt.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! 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);

fn hello() -> Foo<[impl Sized; 2]> {
if false {
let x = hello();
let _: &Foo<[i32]> = &x;
//~^ ERROR: mismatched types
}
todo!()
}
Expand Down
17 changes: 0 additions & 17 deletions tests/ui/impl-trait/unsize_adt.stderr

This file was deleted.

5 changes: 3 additions & 2 deletions tests/ui/impl-trait/unsize_slice.rs
Original file line number Diff line number Diff line change
@@ -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!()
}
Expand Down
17 changes: 0 additions & 17 deletions tests/ui/impl-trait/unsize_slice.stderr

This file was deleted.

5 changes: 3 additions & 2 deletions tests/ui/impl-trait/unsize_tuple.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! 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)]

fn hello() -> ([impl Sized; 2],) {
if false {
let x = hello();
let _: &([i32],) = &x;
//~^ ERROR: mismatched types
}
todo!()
}
Expand Down
17 changes: 0 additions & 17 deletions tests/ui/impl-trait/unsize_tuple.stderr

This file was deleted.

26 changes: 26 additions & 0 deletions tests/ui/impl-trait/unsized_coercion.next.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions tests/ui/impl-trait/unsized_coercion.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions tests/ui/impl-trait/unsized_coercion2.old.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions tests/ui/impl-trait/unsized_coercion2.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 38 additions & 0 deletions tests/ui/impl-trait/unsized_coercion3.next.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 26 additions & 0 deletions tests/ui/impl-trait/unsized_coercion3.old.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 24 additions & 0 deletions tests/ui/impl-trait/unsized_coercion3.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions tests/ui/impl-trait/unsized_coercion4.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Loading

0 comments on commit 164e129

Please sign in to comment.