We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ground Rules: Values, Types, Control Flow step 13 of 24
Find the first negative value with an early return
Find the zero-based index of the first negative value in a slice. Return
-1 if the slice has no negative values, including when it is empty.
pub fn first_negative_index(values: &[i32]) -> i32
A value is negative when it is less than zero. Zero is not negative. Search from left to right and stop at the first match; do not return the last match or the most negative value. Leave the borrowed input unchanged.
| Input | Result |
|---|---|
[1, 2, -3] |
2 |
[] |
-1 |
[-1] |
0 |
[0, 0, 0] |
-1 |
[5, -1, -2] |
1 |
Values may span the full i32 range. The input length is at most i32::MAX,
so every valid index fits in the return type.
Repair the two lint failures
The starter already computes the required result for these inputs, but it fails the warnings-as-errors check:
- The final
return -1;triggers Clippy'sneedless_return. Use a tail expression for the not-found result. - The private helper
is_negativeis never used, which triggersdead_code. Remove it or use it in the search. Do not suppress the warnings for this task.
Keep the useful early return inside the loop. It ends the search as soon as a negative value is found.
Early return versus a tail expression
return value; leaves the current function immediately. A tail expression
supplies the value when execution reaches the end of the body. Both are valid
Rust; the distinction here is which form makes the control flow clearer and
satisfies the lint.
This complete example uses an early return for a match and a tail expression for the fallback:
fn has_zero(values: &[i32]) -> bool {
for &value in values {
if value == 0 {
return true;
}
}
false
}
fn main() {
assert!(has_zero(&[4, 0, 8]));
assert!(!has_zero(&[4, 8]));
assert!(!has_zero(&[]));
}
Do not add a semicolon after the tail expression. false; is a statement,
so that function body would instead finish with (), which does not match
its declared bool result. The same distinction applies to the final -1
in this exercise.
Read the signature and loop pattern
&[i32] is a borrowed slice, and -> i32 declares the result type. The compiler
can infer many local types from their uses. Ordinary function parameters need
type annotations, while an omitted return type means (); explicit signatures
do not guarantee that every compiler error will be reported at the source of
the original mistake.
values.iter().enumerate() yields (usize, &i32) pairs. In (i, &v), i
is the index and the reference pattern copies the i32 into v. The input
slice remains borrowed.
Converting the index with as i32 is valid under the stated input-size bound.
It is not a general checked conversion: a larger usize can lose its numeric
value when cast to i32.
Your solution must compile, produce the required result and pass Clippy with warnings treated as errors.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.