We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Orientation and the Gate step 2 of 6
How to read a rustc error message
Sum a slice of integers.
pub fn tally(items: &[i32]) -> i32
[1, 2, 3] is 6, [] is 0, [-5, 5] is 0.
The starter does not compile. It contains four independent mistakes, deliberately planted, and your job is to read your way out. This skill gates every other item in the course: a learner who reads the whole message stops needing hints.
The compiler will not show you everything at once
rustc runs in passes, and a pass only runs if the previous one succeeded.
So you will fix errors in rounds. Concretely, for this starter:
-
Round 1 reports
E0277andE0308. Those are type errors. -
Fix them, compile again, and round 2 reports
E0282— type inference had no chance to run until the type errors were gone. -
Fix that, and round 3 finally reports
E0384, which comes from the borrow checker, the last pass of all.
This is not the compiler being coy. It is a real ordering: you cannot check who owns what until you know what everything is. Expect it, and stop reading “1 error” as “1 mistake”.
Anatomy of a message
A rustc diagnostic has five parts, and beginners typically read one of them.
error[E0308]: mismatched types
--> unit.rs:11:16
|
11 | return "nothing to tally";
| ^^^^^^^^^^^^^^^^^^ expected `i32`, found `&str`
|
help: try removing the string literal and returning a number
-
The code —
E0308. Stable, searchable, and explainable:rustc --explain E0308prints a page about it. - The headline — “mismatched types”. Usually too short to act on alone.
- The location — file, line, column.
-
The underline and its label — this is the part that actually tells you
what happened.
expected i32, found &strnames both sides. Almost every beginner question is answered by this line. -
The
help:/note:footer — frequently a literal fix.
The four codes you will meet here
E0308 — mismatched types. The most common error in Rust by a wide
margin, and it has several distinct faces. Here it is a &str returned from a
function declared -> i32. Elsewhere it is “if and else have incompatible
types”, or the notorious semicolon swallows the return value: a function
body ending in x; evaluates to (), not to x, and () is not i32. If
you learn to recognise only one code, learn this one.
E0277 — the trait bound is not satisfied. In this starter it is
the type `[i32]` cannot be indexed by `i32`. Slices are indexed by
usize, the pointer-sized unsigned integer, and by nothing else. Item 1.3
explains why. E0277 in general means “you asked for an operation this type
does not implement” — indexing, adding, printing, comparing.
E0282 — type annotations needed. Vec::new() builds a Vec<_> and Rust
infers the _ from how you use it. If you never push anything in, there is
nothing to infer from, and the compiler refuses to guess. The fix is one
annotation: let scratch: Vec<i32> = Vec::new();.
E0384 — cannot assign twice to immutable variable. let bindings are
immutable by default in Rust — the opposite default from almost every other
language you have used. let mut opts in. Item 1.1 is about exactly this.
Then the gate
Once it compiles, clippy -D warnings still has to pass, and the accumulated
scaffolding in the starter will not survive it. The shortest correct answer to
this problem is one line long, and the standard library already contains the
loop you were about to write.
Predict the error code before you compile. Then compile. You will be right more often than you expect, and being right is what makes the compiler start feeling like a colleague instead of a gatekeeper.
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.