Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix late-bound ICE #92289

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ pub(super) fn check_fn<'a, 'tcx>(
// case that a newcomer might make, returning a bare trait, and in that case we populate
// the tail expression's type so that the suggestion will be correct, but ignore all other
// possible cases.
fcx.check_expr(&body.value);
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
fcx.check_expr(&body.value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@estebank I see you added this branch in e536257 including the FIXME. Did you add the FIXME because it would be great to unify the ty::Dynamic case with all the others and remove the check or for another reason? Just trying to figure out what we'd like to have fixed. 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wesleywiser correct, before my change this was branchless code. I want it to return to being branchless code while also supporting the improved diagnostics.

} else {
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
fcx.check_return_expr(&body.value, false);
Expand Down
24 changes: 12 additions & 12 deletions src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,6 @@ LL | }
LL ~ Box::new(42)
|

error[E0308]: `if` and `else` have incompatible types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9
|
LL | / if true {
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | 42
| | ^^ expected struct `Struct`, found integer
LL | | }
| |_____- `if` and `else` have incompatible types

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13
|
Expand All @@ -133,6 +121,18 @@ LL | } else {
LL ~ Box::new(42)
|

error[E0308]: `if` and `else` have incompatible types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9
|
LL | / if true {
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | 42
| | ^^ expected struct `Struct`, found integer
LL | | }
| |_____- `if` and `else` have incompatible types

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,19 +236,37 @@ error[E0746]: return type cannot have an unboxed trait object
LL | fn hat() -> dyn std::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= note: you can create a new `enum` with a variant for each returned type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @estebank This PR resolves an ICE but causes some changes to diagnostics. Most of the notes appear to be more or less present as help messages instead but this note about creating a new enum is missing. Do you have concerns with merging this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this fixes an ICE, lets merge, but I at least I would open a ticket pointing at this PR about getting these back :-/

help: return a boxed trait object instead
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
LL ~ fn hat() -> Box<dyn std::fmt::Display> {
LL | match 13 {
LL | 0 => {
LL ~ return Box::new(0i32);
LL | }
LL | _ => {
...
LL | fn hat() -> T {
| ~
help: use `impl std::fmt::Display` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | fn hat() -> impl std::fmt::Display {
| ~~~~~~~~~~~~~~~~~~~~~~
help: use a boxed trait object if all return paths implement trait `std::fmt::Display`
|
LL | fn hat() -> Box<dyn std::fmt::Display> {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
|
LL | fn pug() -> dyn std::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
LL | fn pug() -> T {
| ~
help: use `impl std::fmt::Display` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | fn pug() -> impl std::fmt::Display {
| ~~~~~~~~~~~~~~~~~~~~~~
help: use a boxed trait object if all return paths implement trait `std::fmt::Display`
|
LL | fn pug() -> Box<dyn std::fmt::Display> {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~

error[E0308]: `match` arms have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14
Expand All @@ -262,25 +280,6 @@ LL | | _ => 2u32,
LL | | }
| |_____- `match` arms have incompatible types

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
|
LL | fn pug() -> dyn std::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= note: you can create a new `enum` with a variant for each returned type
help: return a boxed trait object instead
|
LL ~ fn pug() -> Box<dyn std::fmt::Display> {
LL | match 13 {
LL ~ 0 => Box::new(0i32),
LL ~ 1 => Box::new(1u32),
LL ~ _ => Box::new(2u32),
|

Comment on lines -277 to -283
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is the only output we'd lose, right? Can we check whether this suggestion in particular still triggers anywhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least the help "return a boxed trait object instead" triggers in dyn-trait-return-should-be-impl-trait

error[E0308]: `if` and `else` have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9
|
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/unsized/expect_unsized_return_sized.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// compile-flags: --crate-type lib
trait Foo<'x> {}

fn or<'a>(first: dyn Foo<'a>) -> dyn Foo<'a> {
//~^ ERROR: the size for values of type `(dyn Foo<'a> + 'static)` cannot be known at compilation time [E0277]
//~| ERROR: return type cannot have an unboxed trait object [E0746]
return Box::new(0);
}
36 changes: 36 additions & 0 deletions src/test/ui/unsized/expect_unsized_return_sized.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
error[E0277]: the size for values of type `(dyn Foo<'a> + 'static)` cannot be known at compilation time
--> $DIR/expect_unsized_return_sized.rs:4:11
|
LL | fn or<'a>(first: dyn Foo<'a>) -> dyn Foo<'a> {
| ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Foo<'a> + 'static)`
= help: unsized fn params are gated as an unstable feature
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | fn or<'a>(first: &dyn Foo<'a>) -> dyn Foo<'a> {
| +

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/expect_unsized_return_sized.rs:4:34
|
LL | fn or<'a>(first: dyn Foo<'a>) -> dyn Foo<'a> {
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
|
LL | fn or<'a>(first: dyn Foo<'a>) -> T {
| ~
help: use `impl Foo<'a>` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | fn or<'a>(first: dyn Foo<'a>) -> impl Foo<'a> {
| ~~~~~~~~~~~~
help: use a boxed trait object if all return paths implement trait `Foo<'a>`
|
LL | fn or<'a>(first: dyn Foo<'a>) -> Box<dyn Foo<'a>> {
| ~~~~~~~~~~~~~~~~

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0746.
For more information about an error, try `rustc --explain E0277`.