E0872 and E0746 should suggest "impl Trait" more prominently · Issue #121037 · rust-lang/rust (original) (raw)
Code
This code triggers E0872 "trait objects must include the dyn
keyword" with stable, and also E0746 "return type cannot have an unboxed trait object" with nightly. The optimal fix is to insert "impl" before "FnOnce". The stable compiler, however, only suggests use of "dyn FnOnce". The nightly compiler does suggest "impl FnOnce" but it's not nearly as prominent as the "dyn FnOnce" suggestion.
use std::io::{Error, ErrorKind, Result}; pub fn fallback_for_unsupported_op( fallback: T, ) -> FnOnce(Error) -> Result { move |err| { if err.kind() == ErrorKind::Unsupported { Ok(fallback) } else { Err(err) } } }
Current output
1.78.0-nightly (2024-02-12 b381d3a)
Compiling playground v0.0.1 (/playground)
error[E0746]: return type cannot have an unboxed trait object
--> src/lib.rs:4:6
|
4 | ) -> FnOnce(Error) -> Result<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
help: box the return type, and wrap all of the returned values in `Box::new`
|
4 ~ ) -> Box<FnOnce(Error) -> Result<T>> {
5 ~ Box::new(move |err| {
6 | if err.kind() == ErrorKind::Unsupported {
...
10| }
11~ })
|
error[E0782]: trait objects must include the `dyn` keyword
--> src/lib.rs:4:6
|
4 | ) -> FnOnce(Error) -> Result<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: use `impl FnOnce(Error) -> Result<T>` to return an opaque type, as long as you return a single underlying type
|
4 | ) -> impl FnOnce(Error) -> Result<T> {
| ++++
help: alternatively, you can return an owned trait object
|
4 | ) -> Box<dyn FnOnce(Error) -> Result<T>> {
| +++++++ +
Some errors have detailed explanations: E0746, E0782.
For more information about an error, try `rustc --explain E0746`.
error: could not compile `playground` (lib) due to 2 previous errors
Desired output
Make the suggestion to use "impl Trait" the most prominent piece of help. Also, do not issue two diagnostics for the same problem. E0746 is clearer about why this doesn't work, so that one should be preferred. Also also, since the error itself says "an unboxed trait object", the alternative "Box<dyn T>
" suggestion should call that "a boxed trait object".
error[E0746]: return type cannot have an unboxed trait object
--> src/lib.rs:4:6
|
4 | ) -> FnOnce(Error) -> Result<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
help: use `impl FnOnce(Error) -> Result<T>` to return an opaque type
|
4 | ) -> impl FnOnce(Error) -> Result<T> {
| ++++
help: alternatively, you can return a boxed trait object
|
4 | ) -> Box<dyn FnOnce(Error) -> Result<T>> {
| +++++++ +
Rationale and extra context
When "impl Trait
" can be used as the return value of a function, it is almost always preferable to use that instead of "Box<dyn Trait>
". The only reason I can think of to use "Box<dyn Trait>
" when "impl Trait
" would have worked, is if there is some sort of external API constraint requiring a boxed trait object. Therefore, the compiler should suggest changing a bare trait to impl Trait
first, and only to Box<dyn Trait>
as an alternative.
Note that the cautionary phrase "as long as you return a single underlying type" should not be necessary, because the compiler ought to be able to tell whether "impl Trait" is usable in context. When it isn't, only the suggestion to switch to "Box<dyn Trait>
" should be printed.
Rust Version
I used play.rust-lang.org for the nightly compiler so all I can give you is "1.78.0-nightly (2024-02-12 b381d3a)".