LYR-SEM0163
a loop's head takes 'try?', 'try!' or a catching form
The source of a for loop is marked try?, try! or with the catching form of try instead of the plain try.
Explanation
A loop's head takes the plain try mark only: it covers the source and every next() the loop makes. try? or try! would take the value of the head, and the pulls at every pass would stand outside it, uncaught.
Write for (x in try source) and let the error propagate, or put the loop in a try { … } catch block to handle what it throws.
Wrong
class Fail :: [Error] {
at: int,
fn message(): string {
return f"failed at {this.at}";
}
}
struct Lines :: [Iterator] {
type Item = int;
type Error = Fail;
var i: int,
stop: int,
mut fn next(): ?int throws Fail {
if (this.i == this.stop) { throw Fail { at = this.i }; }
this.i = this.i + 1;
return this.i;
}
}
fn main(): void {
var s = 0;
for (x in try? Lines { i = 0, stop = 3 }) { s = s + x; }
assert(s >= 0);
}
Right
class Fail :: [Error] {
at: int,
fn message(): string {
return f"failed at {this.at}";
}
}
struct Lines :: [Iterator] {
type Item = int;
type Error = Fail;
var i: int,
stop: int,
mut fn next(): ?int throws Fail {
if (this.i == this.stop) { throw Fail { at = this.i }; }
this.i = this.i + 1;
return this.i;
}
}
fn main(): void {
var s = 0;
try {
for (x in Lines { i = 0, stop = 3 }) { s = s + x; }
} catch (e: Fail) {
s = 0 - e.at;
}
assert(s >= 0);
}