Skip to content

Commit 761df25

Browse files
authored
Allow bare try blocks for exceptions (#289)
The exception handling spec now allows bare `try` blocks that have no corresponding `catch` (or other) clauses following it. These blocks are semantically equivalent to `block`. Related spec PR: WebAssembly/exception-handling#157
1 parent b185388 commit 761df25

File tree

5 files changed

+17
-15
lines changed

5 files changed

+17
-15
lines changed

crates/wasmparser/src/operators_validator.rs

-3
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,6 @@ impl OperatorValidator {
677677
self.push_ctrl(FrameKind::Else, frame.block_type, resources)?;
678678
frame = self.pop_ctrl(resources)?;
679679
}
680-
FrameKind::Try => {
681-
bail_op_err!("expected catch block");
682-
}
683680
_ => (),
684681
}
685682

crates/wast/src/ast/expr.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -193,17 +193,12 @@ impl<'a> ExpressionParser<'a> {
193193
self.instrs.push(Instruction::End(None));
194194
}
195195

196-
// Both `do` and `catch` are required in a `try` statement, so
197-
// we will signal those errors here. Otherwise, terminate with
196+
// The `do` clause is required in a `try` statement, so
197+
// we will signal that error here. Otherwise, terminate with
198198
// an `end` or `delegate` instruction.
199199
Level::Try(Try::Do(_)) => {
200200
return Err(parser.error("previous `try` had no `do`"));
201201
}
202-
Level::Try(Try::CatchOrDelegate) => {
203-
return Err(parser.error(
204-
"previous `try` had no `catch`, `catch_all`, or `delegate`",
205-
));
206-
}
207202
Level::Try(Try::Delegate) => {}
208203
Level::Try(_) => {
209204
self.instrs.push(Instruction::End(None));
@@ -372,7 +367,7 @@ impl<'a> ExpressionParser<'a> {
372367
Paren::Right => return Ok(true),
373368
}
374369
}
375-
return Ok(false);
370+
return Err(parser.error("expected a `catch`, `catch_all`, or `delegate`"));
376371
}
377372

378373
if let Try::Catch = i {

tests/local/try.wast

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
;; --enable-exceptions
22

3+
(assert_malformed
4+
(module quote
5+
"(func (try))"
6+
)
7+
"previous `try` had no `do`")
8+
39
(assert_malformed
410
(module quote
511
"(func (try (catch $exn)))"
@@ -14,15 +20,15 @@
1420

1521
(assert_malformed
1622
(module quote
17-
"(func (try (do)))"
23+
"(func (try (do) (unreachable)))"
1824
)
19-
"previous `try` had no `catch`")
25+
"expected a `catch`, `catch_all`, or `delegate`")
2026

2127
(assert_malformed
2228
(module quote
23-
"(func (try (do) (unreachable)))"
29+
"(func (try (do) (catch_all) (unreachable)))"
2430
)
25-
"previous `try` had no `catch`")
31+
"too many payloads inside of `(try)`")
2632

2733
(assert_malformed
2834
(module quote

tests/local/try.wat

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
(module $m
44
(type (func))
55
(event $exn (type 0))
6+
(func (try (do)))
67
(func (try (do) (catch $exn)))
78
(func (try (do) (catch $exn rethrow 0)))
89
(func (try (do) (catch_all rethrow 0)))

tests/roundtrip.rs

+3
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,9 @@ impl TestState {
280280
// FIXME wabt doesn't print conflict or empty names in the same way
281281
// that we do.
282282
&& !test.ends_with("local/names.wast")
283+
284+
// FIXME this can be removed once wabt support for catch-less try is merged
285+
&& !test.ends_with("local/try.wat")
283286
{
284287
if let Some(expected) = self.wasm2wat(contents)? {
285288
self.string_compare(&string, &expected)

0 commit comments

Comments
 (0)