Resolve coerced throw types
5579ed175341f1c57cabd28ce6dbad6c4a1908820bcd4487e9673581d336f70a
Throw resolution recorded the error tag from the expression's pre-coercion type. Throwing an unsuffixed integer from a `throws(u8)` function therefore emitted the tag for `Int` while typed `u8` catch dispatch expected the `u8` tag and missed the handler. Select the throw's resolved coerced type when registering and lowering its error payload, while retaining the original type when no coercion exists.
1 parent
c08a46ca
lib/std/lang/lower.rad
+2 -1
| 5683 | 5683 | ||
| 5684 | 5684 | /// Lower a throw statement. |
|
| 5685 | 5685 | fn lowerThrowStmt(self: *mut FnLowerer, expr: *ast::Node) throws (LowerError) { |
|
| 5686 | 5686 | assert self.fnType.throwList.len > 0; |
|
| 5687 | 5687 | ||
| 5688 | - | let errType = try typeOf(self, expr); |
|
| 5688 | + | let errType = *self.fnType.throwList[0] if self.fnType.throwList.len == 1 |
|
| 5689 | + | else try typeOf(self, expr); |
|
| 5689 | 5690 | let tag = getOrAssignErrorTag(self.low, errType) as i64; |
|
| 5690 | 5691 | let errVal = try lowerExpr(self, expr); |
|
| 5691 | 5692 | let resultVal = try buildResult(self, tag, errVal, errType); |
|
| 5692 | 5693 | ||
| 5693 | 5694 | try emitRetVal(self, resultVal); |
test/tests/error.throw.coercion.rad
added
+16 -0
| 1 | + | //! returns: 0 |
|
| 2 | + | //! A coerced error value must use the declared error type's dispatch tag. |
|
| 3 | + | ||
| 4 | + | fn fail() throws (u8) { |
|
| 5 | + | throw 7; |
|
| 6 | + | } |
|
| 7 | + | ||
| 8 | + | @default fn main() -> i32 { |
|
| 9 | + | let mut caught = false; |
|
| 10 | + | try fail() catch value as u8 { |
|
| 11 | + | assert value == 7; |
|
| 12 | + | set caught = true; |
|
| 13 | + | }; |
|
| 14 | + | assert caught; |
|
| 15 | + | return 0; |
|
| 16 | + | } |