-
Notifications
You must be signed in to change notification settings - Fork 13k
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
E0121 suggests the use of the unique type of a returned function/closure rather than a fn pointer or a Fn trait #80179
Comments
@rustbot modify labels: +A-diagnostics +D-incorrect |
This also seems to happen with closures: fn returns_closure() -> _ {
|| 5
}
|
@rustbot claim |
Function pointers are now working, but it looks like closures will be a bit harder of a task. fn f() -> i32 { 0 }
fn g() -> _ { f } error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> <anon>:2:11
|
2 | fn g() -> _ { f }
| ^
| |
| not allowed in type signatures
| help: replace with the correct return type: `fn() -> i32`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0121`. |
This brings up some questions though, unfortunately. For example, this code has the same type of issue: fn f() -> i32 { 0 }
fn g() -> () { f } This code brings up this diagnostic: error[E0308]: mismatched types
--> <anon>:2:16
|
2 | fn g() -> () { f }
| -- ^ expected `()`, found fn item
| |
| expected `()` because of return type
|
= note: expected unit type `()`
found fn item `fn() -> i32 {f}`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`. And to be honest, these diagnostics aren't entirely incorrect—that is the return type, it's just not valid syntax. Using a function pointer would be taking that unique type and coercing it into a function pointer or non-unique closure type. Arguably, it should have something like |
For errors like E0308, it would make sense to state the actual type since that is the root cause of the issue (functions cannot be coerced to This is probably problematic, since changing the I haven't looked into the underlying issue personally, but I can see a few options:
|
I think that I'll probably do this I guess:
|
Should I link to the Rust by Example on closure output types or maybe the |
Rust by Example or The Book would probably be preferable since they explain Fn, FnMut, and FnOnce in one place, but I'm not certain if there's any precedent or policy about linking to them in diagnostics. |
Alright. Does this look good? fn f() -> i32 { 0 }
fn g() -> _ { f } error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> <anon>:2:11
|
2 | fn g() -> _ { f }
| ^
| |
| not allowed in type signatures
| help: replace with the correct return type: `fn() -> i32`
|
= help: also consider using a `Fn`, `FnMut`, or `FnOnce` trait bound
= note: For more information on using `Fn` traits with function outputs, see https://doc.rust-lang.org/rust-by-example/fn/closures/output_parameters.html
error: aborting due to previous error
For more information about this error, try `rustc --explain E0121`. I'll get closures in a bit, cause my rustc dev build decided to die on me and I have to completely rebuild it 🙁 |
👍 Looks good to me, but I'd like to emphasize that I'm not ready a contributor, so take this with a grain of salt. |
Closures: fn f() -> _ { || 0 } error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> <anon>:1:11
|
1 | fn f() -> _ { || 0 }
| ^ not allowed in type signatures
|
= help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
= note: For more information on using `Fn` traits with function outputs, see https://doc.rust-lang.org/rust-by-example/fn/closures/output_parameters.html
error: aborting due to previous error
For more information about this error, try `rustc --explain E0121`. |
I think I'm going to remove the |
Thank you so much for all of your hard work! Just a nitpick: it seems like the note should start with a lowercase letter. |
Yeah, camelid noted that in a Zulip thread related to this so I fixed that. |
…arkor Suggest fn ptr rather than fn item and suggest to use `Fn` trait bounds rather than the unique closure type in E0121 Previously, using `_` as a return type in a function that returned a function/closure would provide a diagnostic that would cause a papercut. For example: ```rust fn f() -> i32 { 0 } fn fn_ptr() -> _ { f } fn closure() -> _ { || 0 } ``` would result in this diagnostic: ```rust error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> <anon>:2:16 | 2 | fn fn_ptr() -> _ { f } | ^ | | | not allowed in type signatures | help: replace with the correct return type: `fn() -> i32 {f}` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> <anon>:3:17 | 3 | fn closure() -> _ { || 0 } | ^ | | | not allowed in type signatures | help: replace with the correct return type: `[closure@<anon>:3:21: 3:25]` error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. ``` As can be seen, it was suggested to use the function definition return type `fn() -> i32 { f }` which is not valid syntax as a return type. Additionally, closures cause a papercut as unique closure types (notated in this case as `[closure@<anon>:3:21: 3:25]`) are not valid syntax either. Instead, this PR implements this version of the diagnostic (this example is for the same code featured above): ```rust error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> <anon>:2:16 | 2 | fn fn_ptr() -> _ { f } | ^ | | | not allowed in type signatures | help: replace with the correct return type: `fn() -> i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> <anon>:3:17 | 3 | fn closure() -> _ { || 0 } | ^ not allowed in type signatures | = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. ``` As can be seen in this diagnostic, the papercut for returning a function item is fixed by suggesting the usage of a function pointer as the return type. As for closures, it's suggested to use an `Fn`, `FnMut`, or `FnOnce` trait bound (with further reading on closures and `Fn` traits in *The Book* for beginners). I did not implement a suggestion to use `impl Fn() -> i32` syntax as that was out-of-scope for my abilities at the moment, therefore someone in the future may want to implement that. Also, it's possible to use either `impl Trait` syntax, generics, or generics with a `where` clause, and some users may not want to use `impl Trait` syntax for their own reasons. This PR fixes rust-lang#80179.
This still fails on generators (playground): #![feature(generators)]
fn foo() -> _ {
|| yield i32
}
I'm working on a PR to fix this as well as making this suggestion and E0308's @rustbot claim |
I tried this code:
The resulting diagnostic suggests replacing
_
withfn() -> i32 {f}
, the unique type off()
:This, of course, doesn't work:
I'd expect the diagnostic to suggest replacing
_
withfn() -> i32
orimpl Fn() -> i32
, both of which compile successfully.Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: