Rust's Error Messages are Great
Something Broke
Rust's error messages are one of my favorite features of the language. That's no accident. The compiler folks spend a ton of effort on them. Going so far as saying that any error that doesn't give you enough information to fix it is considered a bug1.
It's an amazing philosophy.
I collected a few examples below. I'm not going to do a full write up explaining the ins and outs of the rust code behind them. That's not necessary to appreciate them. You can see some of the best parts without understanding the language at all.
Line Numbers
Showing line numbers in error messages is table stakes. Different language have their own styles. Rust's approach of showing code lines with the line numbers on the left side (similar to your editor) works great.

Expand to view original image and error text

Compiling neopolitan v0.2.0 (/Users/alan/workshop/neopolitan) error[E0425]: cannot find function `span_attr_key_token` in this scope --> src/span_attr/mod.rs:102:22 | 70 | / pub fn solo_span_attr_key_token<'a>( 71 | | source: &'a str, 72 | | character: &'a str, 73 | | ) -> IResult<&'a str, String> { ... | 84 | | Ok((source, key_snippets.join("").to_string())) 85 | | } | |_- similarly named function `solo_span_attr_key_token` defined here ... 102 | let result = span_attr_key_token(source, character).unwrap(); | ^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `solo_span_attr_key_token` For more information about this error, try `rustc --explain E0425`. error: could not compile `neopolitan` (lib test) due to 1 previous error [Command exited with 101]
Pointers
Rust uses the ^
character to point to the specific location on a line that has the problem. Sometimes, it's a full function name. Sometimes, it's a single character:

Expand to view original image and error text

Compiling mjoin v0.1.0 (/Users/alan/workshop/mjoin) error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` --> src/main.rs:37:47 | 32 | pub fn get_output_list(root_dir: &PathBuf) -> Result<BTreeMap<PathBuf, Vec<PathBuf>>> { | ------------------------------------------------------------------------------------- this function returns a `Result` ... 37 | let file_name = e.file_name().to_str()?; | ^ use `.ok_or(...)?` to provide an error compatible with `Result<BTreeMap<PathBuf, Vec<...>>, ...>` | = note: the full name for the type has been written to '/Users/alan/workshop/mjoin/target/debug/deps/mjoin-89e7bbeab42b3660.long-type-5502576226326651282.txt' = note: consider using `--verbose` to print the full type name to the console For more information about this error, try `rustc --explain E0277`. error: could not compile `mjoin` (bin "mjoin") due to 1 previous error
Extra Details
Error messages tend to show more than just the error itself. Take this, for example:

The error is:
expected `(&str, String)`, found `(String, &str)`
which happens on line 99.
The extra piece of info is why it's a problem. Specifically, the solo_span_attr_key_token_valid_tests
function on line 96 where:
arguments to this function are incorrect
Expand to view original image and error text

Compiling neopolitan v0.2.0 (/Users/alan/workshop/neopolitan) error[E0308]: mismatched types --> src/span_attr/mod.rs:99:17 | 96 | fn solo_span_attr_key_token_valid_tests( | ------------------------------------ arguments to this function are incorrect ... 99 | #[case] left: (&str, String), | ^^^^ expected `(&str, String)`, found `(String, &str)` | = note: expected tuple `(&str, std::string::String)` found tuple `(std::string::String, &str)` note: function defined here --> src/span_attr/mod.rs:96:8 | 96 | fn solo_span_attr_key_token_valid_tests( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... 99 | #[case] left: (&str, String), | -------------------- For more information about this error, try `rustc --explain E0308`. error: could not compile `neopolitan` (lib test) due to 1 previous error [Command exited with 101]
Helpful Suggestions
Error messages tend to have explicit recommendations for possible fixes. For example, here's an error that occurs on line 107:

The text of the error defines the problem:
cannot infer type of the type parameter `T` declared on the function `channel`
The next thing in the message is a help
line with:
help: consider specifying the generic argument
Even better, the message shows you an updated version of line 107 with the recommendation in place and underlined with +
characters to point out the change.
Expand to view original image and error text

Compiling mjoin v0.1.0 (/Users/alan/workshop/mjoin) error[E0282]: type annotations needed --> src/main.rs:107:20 | 107 | let (tx, rx) = std::sync::mpsc::channel(); | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` | help: consider specifying the generic argument | 107 | let (tx, rx) = std::sync::mpsc::channel::<T>(); | +++++ For more information about this error, try `rustc --explain E0282`. error: could not compile `mjoin` (bin "mjoin") due to 1 previous error
Error Number Details
Each error starts with a line like:
error[E0308]: mismatched types
And has a corresponding line like this at the end:
For more information about this error, try `rustc --explain E0308`.
For example:

The error code has more details about why the error might have happened and possible corrective measures. As it says, you can see these details by running the specific command like:
rustc --explain E0308
Which, in the case of error E0308, outputs this:
[NOTE: Don't worry about trying to understand the output. This is about showing the amount of information Rust gives you to find a solution for an error more than anything else.]
Expected type did not match the received type. Erroneous code examples: ``` fn plus_one(x: i32) -> i32 { x + 1 } plus_one("Not a number"); // ^^^^^^^^^^^^^^ expected `i32`, found `&str` if "Not a bool" { // ^^^^^^^^^^^^ expected `bool`, found `&str` } let x: f32 = "Not a float"; // --- ^^^^^^^^^^^^^ expected `f32`, found `&str` // | // expected due to this ``` This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration.
Expand to view original image and error text

NOTE: I goofed copying the text for this image. It's like the others on this page. Just a different error.
Use Sharp Tools
Rust's initial learning curve took significant effort to get over. A big part was learning how to read the error messages. They were overwhelming at first. After putting in some reps, they're amazing. They help make the language a pleasure to use.
-a
Footnotes
I got a response to a post on Mastodon from one of the compiler folks asking for bug reports on errors I didn't understand. This was some time last year. But, fucked if I can find it because Mastodon doesn't have search.