I tried to run the following code snippet:
let a = &[Some(1), Some(2), Some(3), None, Some(4)];
let mut sum = 0;
for &Some(x) in a.iter() {
sum += x;
}
assert_eq!(sum, 1+2+3+4);
The compiler replied with:
about_loops.rs:39:9: 43:18 error: non-exhaustive patterns: None not covered
about_loops.rs:39 for &Some(x) in a.iter() {
about_loops.rs:40 sum += x;
about_loops.rs:41 }
about_loops.rs:42
about_loops.rs:43 assert_eq!(sum, 1+2+3+4);
error: aborting due to previous error
make: *** [all] Error 101
Can I make such a construct compile for a for loop without using a match expression as suggested by luke and hobbs? Or is this error message misleading? It does not seem so given the grammar definition of for.
for_expr : "for" pat "in" expr '{' block '}' ;
I'm on:
rustc 0.11.0-pre-nightly (6291955 2014-05-19 23:41:20 -0700)
host: x86_64-apple-darwin
To clarify: How expressive is the 'pat' portion of for_expr? This is not specified under http://doc.rust-lang.org/rust.html#for-expressions in contrast to the definition under http://doc.rust-lang.org/rust.html#match-expressions.
The pattern of a for
loop essentially has the same restrictions as a let
: it has to be irrefutable, that is, it can't ever fail to match.
Examples of irrefutable patterns are &
, tuples, structs and single-variant enums. Other patterns (like multivariant enums or literals) aren't guaranteed to always match, since the type allows for values that aren't covered by the pattern.
The for
construct is essentially a macro that desugars as follows (it desugars in the same pass as macros are expanded, you can see it manually running rustc with --pretty expanded
):
for <pattern> in <iter_expression> {
<code>
}
// becomes
match &mut <iter_expression> { // match to guarantee data lives long enough
it => {
loop {
match it.next() {
None => break,
Some(<pattern>) => { <code> }
}
}
}
}
That is a normal match
, i.e. the arms have to be exhaustive (cover every possibility), and so if <pattern>
is just &Some(_)
, then the Some(&None)
possibility isn't covered.
(The Some
arm is essentially equivalent to Some(value) => { let <pattern> = value; ...
. Thinking about it now, this might actually be a desugaring that gives better error messages: I filed #14390.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With