4 ms·
This managed to capture a common occurrence when I've tried to learn rust. The compiler spits out a short but seemingly helpful error like this: warning: tr
by justinsaccount 6y ago
This managed to capture a common occurrence when I've tried to learn rust. The compiler spits out a short but seemingly helpful error like this:
warning: trait objects without an explicit `dyn` are deprecated
help: use `dyn`: `dyn Error`
You make the code change it suggests and then you get a longer error message that says what it just told you to do is invalid.
- estebank 6y agoThe longer error message would have been emitted regardless of the warning: warning: trait objects without an explicit `dyn` are deprecated --> file.rs:3:13 | 3 | fn foo() -> Trait { | ^^^^^ help: use `dyn`: `dyn Trait` | = note: `#[warn(bare_trait_objects)]` on by default error[E0746]: return type cannot have an unboxed trait object --> file.rs:3:13 | 3 | fn foo() -> Trait { | ^^^^^ 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 | 3 | fn foo() -> T { | ^ help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature | 3 | fn foo() -> impl Trait { | ^^^^^^^^^^ help: use a boxed trait object if all return paths implement trait `Trait` | 3 | fn foo() -> Box<dyn Trait> { | ^^^^^^^^^^^^^^ https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=304a1a1495275024b63676e605c197de https://play.rust-lang.org/?version=nightly&mode=debug&editi... Edit: and for some more realistic cases where the compiler can actually look at what you wrote, instead of just giving up because you used `todo!()`: warning: trait objects without an explicit `dyn` are deprecated --> file.rs:7:20 | 7 | fn foo(x: bool) -> Trait { | ^^^^^ help: use `dyn`: `dyn Trait` | = note: `#[warn(bare_trait_objects)]` on by default error[E0308]: `if` and `else` have incompatible types --> file.rs:11:9 | 8 | / if x { 9 | | S | | - expected because of this 10 | | } else { 11 | | D | | ^ expected struct `S`, found struct `D` 12 | | } | |_____- `if` and `else` have incompatible types error[E0746]: return type cannot have an unboxed trait object --> file.rs:7:20 | 7 | fn foo(x: bool) -> Trait { | ^^^^^ 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 Trait` 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 | 7 | fn foo(x: bool) -> Box<dyn Trait> { 8 | if x { 9 | Box::new(S) 10| } else { 11| Box::new(D) | and warning: trait objects without an explicit `dyn` are deprecated --> file.rs:7:20 | 7 | fn foo(x: bool) -> Trait { | ^^^^^ help: use `dyn`: `dyn Trait` | = note: `#[warn(bare_trait_objects)]` on by default error[E0746]: return type cannot have an unboxed trait object --> file.rs:7:20 | 7 | fn foo(x: bool) -> Trait { | ^^^^^ doesn't have a size known at compile-time | = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits> help: use `impl Trait` as the return type, as all return paths are of type `S`, which implements `Trait` | 7 | fn foo(x: bool) -> impl Trait { | ^^^^^^^^^^
- justinsaccount 6y agoah yeah I've gotten that error[E0308]: `if` and `else` have incompatible types before. I was trying to write a simple little program that would output data and optionally reversed (like sort -r). Nothing I could do with iterators would work because it kept trying to tell me that a reverse iterator was not compatible with an iterator. It would work if I hardcoded it, but any code like output = if (reverse) { result.rev() } else { result }; would fail to compile with a completely nonsense error message. I think I eventually got it to work by collecting it into a vector first and reversing that. Haven't really touched rust since. Honestly the compiler might as well just tell me to go fuck myself.
- estebank 6y ago> would fail to compile with a completely nonsense error message. How long ago was this? We spend a lot of time trying to make the error messages easy to follow and informative. If it wasn't that long ago, I would love to see the exact cases you had trouble with in order to improve them. > I think I eventually got it to work by collecting it into a vector first and reversing that. Collecting and reversing is indeed what I would do if I couldn't procure a reversible iterator (DoubleEndedIterator), but if you have one, you can write the code you wanted by spending some cost on a fat pointer by boxing the alternatives[1]. > Haven't really touched rust since. Honestly the compiler might as well just tell me to go fuck myself. I'm sad to hear that, both because you bounced off (which is understandable) and because that experience goes counter to what we aim for. We dedicate a lot of effort on making errors not only readable, pedagogic and actionable (with varying levels of success). We really don't want the compiler to come across as antagonistic or patronizing. [1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0965d3a326d977d7df1293470396e9ea https://play.rust-lang.org/?version=stable&mode=debug&editio... Edit: For what is worth, type mismatch errors do try to give you appropriate suggestions, but in the case of two types that both implement the same trait (like the one you mention), the compiler does not look for traits that are implemented for both: error[E0308]: `if` and `else` have incompatible types --> file.rs:10:9 | 7 | let x = if true { | _____________- 8 | | A | | - expected because of this 9 | | } else { 10 | | B | | ^ expected struct `A`, found struct `B` 11 | | }; | |_____- `if` and `else` have incompatible types This could be done, but that has the potential to give you a lot of output for all possible traits that could satisfy this code, and in general we would be sending you in the wrong direction. When we can't be 90% sure that the suggestion is not harmful, we just "say nothing", like in this case. On a real case of the example above, you'd be more likely to want to create a new enum.