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

Poor Trailing Semicolon Error in -> impl Trait Function #54771

Open
cramertj opened this Issue Oct 2, 2018 · 3 comments

Comments

Projects
None yet
3 participants
@cramertj
Copy link
Member

cramertj commented Oct 2, 2018

The diagnostics that check whether the concrete return type of an -> impl Trait function meets the : Trait bound should special-case the error when the concrete type is () to suggest removing the semicolon. Without this, the errors for a misplaced semicolon are misleading:

Without impl Trait:

trait Bar {}
impl Bar for u8 {}
fn foo() -> u8 {
    5;
}
error[E0308]: mismatched types
 --> src/main.rs:3:16
  |
3 |   fn foo() -> u8 {
  |  ________________^
4 | |     5;
  | |      - help: consider removing this semicolon
5 | | }
  | |_^ expected u8, found ()
  |
  = note: expected type `u8`
             found type `()`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: Could not compile `playground`.

With impl Trait:

trait Bar {}
impl Bar for u8 {}
fn foo() -> impl Bar {
    5;
}
error[E0277]: the trait bound `(): Bar` is not satisfied
 --> src/main.rs:3:13
  |
3 | fn foo() -> impl Bar {
  |             ^^^^^^^^ the trait `Bar` is not implemented for `()`
  |
  = note: the return type of a function must have a statically known size

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: Could not compile `playground`.
@cramertj

This comment has been minimized.

Copy link
Member Author

cramertj commented Oct 2, 2018

Note: there's a similar issue in closure return types:

trait Bar {}
impl Bar for u8 {}

fn bar<R: Bar>(_: impl Fn() -> R) {}
fn main() {
    bar(|| { 5u8; })
}

gives

error[E0277]: the trait bound `(): Bar` is not satisfied
 --> src/main.rs:6:5
  |
6 |     bar(|| { 5u8; })
  |     ^^^ the trait `Bar` is not implemented for `()`
  |
note: required by `bar`
 --> src/main.rs:4:1
  |
4 | fn bar<R: Bar>(_: impl Fn() -> R) {}
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error
@csmoe

This comment has been minimized.

Copy link
Member

csmoe commented Oct 3, 2018

the impl-Trait <: T subtyping seems fail here:

if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
return;
}


DEBUG LOG:

DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: >> typechecking: expr=expr(21: { 1u8; }) expected=ExpectHasType(_)
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: >> typechecking: expr=expr(16: 1u8) expected=NoExpectation
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: write_ty(HirId { owner: DefIndex(0:5), local_id: ItemLocalId(1) }, u8) in fcx 0x7ffef324d930
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: type of expr 1u8 (id=16) is...
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: ... u8, expected is NoExpectation
/// STOP!!!
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: write_ty(HirId { owner: DefIndex(0:5), local_id: ItemLocalId(3) }, ()) in fcx 0x7ffef324d930
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: write_ty(HirId { owner: DefIndex(0:5), local_id: ItemLocalId(4) }, ()) in fcx 0x7ffef324d930
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: type of expr { 1u8; } (id=21) is...
DEBUG 2018-10-03T09:41:07Z: rustc_typeck::check: ... (), expected is ExpectHasType(_)
D

as it shows the checking should move to lint_remove_semi before the 2nd time of calling write_ty , or then expr { 1u8; } will be "parsed" as (), that's why we get (): Bar is not satisfied.

@estebank

This comment has been minimized.

Copy link
Contributor

estebank commented Feb 5, 2019

there's a similar issue in closure return types

@cramertj closure output is already problematic for the simple case there too:

error[E0308]: mismatched types
 --> src/main.rs:6:12
  |
6 |     bar(|| { 5u8; })
  |            ^^^^^^^^ expected u32, found ()
  |
  = note: expected type `u32`
             found type `()`

Disregard this, we actually do the right thing for this case:

error[E0308]: mismatched types
 --> file.rs:3:12
  |
3 |     bar(|| { 5; })
  |            ^^^-^^
  |            |  |
  |            |  help: consider removing this semicolon
  |            expected u8, found ()
  |
  = note: expected type `u8`
             found type `()`

Centril added a commit to Centril/rust that referenced this issue Feb 13, 2019

Rollup merge of rust-lang#58204 - estebank:impl-trait-semi, r=zackmdavis
On return type `impl Trait` for block with no expr point at last semi

Partial solution, doesn't actually validate that the last statement in the function body can satisfy the trait bound, but it's a good incremental improvement over the status quo.

```
error[E0277]: the trait bound `(): Bar` is not satisfied
  --> $DIR/impl-trait-return-trailing-semicolon.rs:3:13
   |
LL | fn foo() -> impl Bar {
   |             ^^^^^^^^ the trait `Bar` is not implemented for `()`
LL |     5;
   |      - consider removing this semicolon
   |
   = note: the return type of a function must have a statically known size
```

Partially addresses rust-lang#54771.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment