| ... | @@ -1156,16 +1156,6 @@ fn fnProtoExpr( | ... | @@ -1156,16 +1156,6 @@ fn fnProtoExpr( |
| 1156 | return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{}); | 1156 | return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{}); |
| 1157 | } | 1157 | } |
| 1158 | | 1158 | |
| 1159 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | | |
| 1160 | const is_inferred_error = token_tags[maybe_bang] == .bang; | | |
| 1161 | if (is_inferred_error) { | | |
| 1162 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); | | |
| 1163 | } | | |
| 1164 | var ret_gz = gz.makeSubBlock(scope); | | |
| 1165 | defer ret_gz.instructions.deinit(gpa); | | |
| 1166 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); | | |
| 1167 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); | | |
| 1168 | | | |
| 1169 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) | 1159 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) |
| 1170 | try expr( | 1160 | try expr( |
| 1171 | gz, | 1161 | gz, |
| ... | @@ -1176,6 +1166,16 @@ fn fnProtoExpr( | ... | @@ -1176,6 +1166,16 @@ fn fnProtoExpr( |
| 1176 | else | 1166 | else |
| 1177 | Zir.Inst.Ref.none; | 1167 | Zir.Inst.Ref.none; |
| 1178 | | 1168 | |
| | 1169 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; |
| | 1170 | const is_inferred_error = token_tags[maybe_bang] == .bang; |
| | 1171 | if (is_inferred_error) { |
| | 1172 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| | 1173 | } |
| | 1174 | var ret_gz = gz.makeSubBlock(scope); |
| | 1175 | defer ret_gz.instructions.deinit(gpa); |
| | 1176 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); |
| | 1177 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| | 1178 | |
| 1179 | const result = try gz.addFunc(.{ | 1179 | const result = try gz.addFunc(.{ |
| 1180 | .src_node = fn_proto.ast.proto_node, | 1180 | .src_node = fn_proto.ast.proto_node, |
| 1181 | .param_block = 0, | 1181 | .param_block = 0, |
| ... | @@ -3182,11 +3182,6 @@ fn fnDecl( | ... | @@ -3182,11 +3182,6 @@ fn fnDecl( |
| 3182 | break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr); | 3182 | break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr); |
| 3183 | }; | 3183 | }; |
| 3184 | | 3184 | |
| 3185 | var ret_gz = decl_gz.makeSubBlock(params_scope); | | |
| 3186 | defer ret_gz.instructions.deinit(gpa); | | |
| 3187 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); | | |
| 3188 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); | | |
| 3189 | | | |
| 3190 | const cc: Zir.Inst.Ref = blk: { | 3185 | const cc: Zir.Inst.Ref = blk: { |
| 3191 | if (fn_proto.ast.callconv_expr != 0) { | 3186 | if (fn_proto.ast.callconv_expr != 0) { |
| 3192 | if (has_inline_keyword) { | 3187 | if (has_inline_keyword) { |
| ... | @@ -3212,6 +3207,11 @@ fn fnDecl( | ... | @@ -3212,6 +3207,11 @@ fn fnDecl( |
| 3212 | } | 3207 | } |
| 3213 | }; | 3208 | }; |
| 3214 | | 3209 | |
| | 3210 | var ret_gz = decl_gz.makeSubBlock(params_scope); |
| | 3211 | defer ret_gz.instructions.deinit(gpa); |
| | 3212 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); |
| | 3213 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| | 3214 | |
| 3215 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { | 3215 | const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { |
| 3216 | if (!is_extern) { | 3216 | if (!is_extern) { |
| 3217 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); | 3217 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); |
| ... | @@ -6500,7 +6500,8 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -6500,7 +6500,8 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6500 | }, | 6500 | }, |
| 6501 | .always => { | 6501 | .always => { |
| 6502 | // Value is always an error. Emit both error defers and regular defers. | 6502 | // Value is always an error. Emit both error defers and regular defers. |
| 6503 | const err_code = try gz.addUnNode(.err_union_code, operand, node); | 6503 | const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand; |
| | 6504 | const err_code = try gz.addUnNode(.err_union_code, result, node); |
| 6504 | try genDefers(gz, defer_outer, scope, .{ .both = err_code }); | 6505 | try genDefers(gz, defer_outer, scope, .{ .both = err_code }); |
| 6505 | try gz.addRet(rl, operand, node); | 6506 | try gz.addRet(rl, operand, node); |
| 6506 | return Zir.Inst.Ref.unreachable_value; | 6507 | return Zir.Inst.Ref.unreachable_value; |
| ... | @@ -6515,7 +6516,8 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -6515,7 +6516,8 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6515 | } | 6516 | } |
| 6516 | | 6517 | |
| 6517 | // Emit conditional branch for generating errdefers. | 6518 | // Emit conditional branch for generating errdefers. |
| 6518 | const is_non_err = try gz.addUnNode(.is_non_err, operand, node); | 6519 | const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand; |
| | 6520 | const is_non_err = try gz.addUnNode(.is_non_err, result, node); |
| 6519 | const condbr = try gz.addCondBr(.condbr, node); | 6521 | const condbr = try gz.addCondBr(.condbr, node); |
| 6520 | | 6522 | |
| 6521 | var then_scope = gz.makeSubBlock(scope); | 6523 | var then_scope = gz.makeSubBlock(scope); |
| ... | @@ -6528,7 +6530,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -6528,7 +6530,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6528 | defer else_scope.instructions.deinit(astgen.gpa); | 6530 | defer else_scope.instructions.deinit(astgen.gpa); |
| 6529 | | 6531 | |
| 6530 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ | 6532 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ |
| 6531 | .both = try else_scope.addUnNode(.err_union_code, operand, node), | 6533 | .both = try else_scope.addUnNode(.err_union_code, result, node), |
| 6532 | }; | 6534 | }; |
| 6533 | try genDefers(&else_scope, defer_outer, scope, which_ones); | 6535 | try genDefers(&else_scope, defer_outer, scope, which_ones); |
| 6534 | try else_scope.addRet(rl, operand, node); | 6536 | try else_scope.addRet(rl, operand, node); |
| ... | @@ -8514,10 +8516,10 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) enum { never | ... | @@ -8514,10 +8516,10 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) enum { never |
| 8514 | .unwrap_optional, | 8516 | .unwrap_optional, |
| 8515 | => node = node_datas[node].lhs, | 8517 | => node = node_datas[node].lhs, |
| 8516 | | 8518 | |
| 8517 | // Forward the question to the RHS sub-expression. | 8519 | // LHS sub-expression may still be an error under the outer optional or error union |
| 8518 | .@"catch", | 8520 | .@"catch", |
| 8519 | .@"orelse", | 8521 | .@"orelse", |
| 8520 | => node = node_datas[node].rhs, | 8522 | => return .maybe, |
| 8521 | | 8523 | |
| 8522 | .block_two, | 8524 | .block_two, |
| 8523 | .block_two_semicolon, | 8525 | .block_two_semicolon, |
| ... | @@ -8544,11 +8546,18 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) enum { never | ... | @@ -8544,11 +8546,18 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) enum { never |
| 8544 | // If the builtin is an invalid name, we don't cause an error here; instead | 8546 | // If the builtin is an invalid name, we don't cause an error here; instead |
| 8545 | // let it pass, and the error will be "invalid builtin function" later. | 8547 | // let it pass, and the error will be "invalid builtin function" later. |
| 8546 | const builtin_info = BuiltinFn.list.get(builtin_name) orelse return .maybe; | 8548 | const builtin_info = BuiltinFn.list.get(builtin_name) orelse return .maybe; |
| 8547 | if (builtin_info.tag == .err_set_cast) { | 8549 | return switch (builtin_info.tag) { |
| 8548 | return .always; | 8550 | .as, |
| 8549 | } else { | 8551 | .call, |
| 8550 | return .never; | 8552 | .field, |
| 8551 | } | 8553 | => .maybe, |
| | 8554 | |
| | 8555 | .err_set_cast, |
| | 8556 | .int_to_error, |
| | 8557 | => .always, |
| | 8558 | |
| | 8559 | else => .never, |
| | 8560 | }; |
| 8552 | }, | 8561 | }, |
| 8553 | } | 8562 | } |
| 8554 | } | 8563 | } |