| ... | ... | @@ -261,6 +261,23 @@ fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zi |
| 261 | 261 | return expr(gz, scope, .{ .ty = .type_type }, type_node); |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | /// Same as `expr` but fails with a compile error if the result type is `noreturn`. |
| 265 | fn reachableExpr( |
| 266 | gz: *GenZir, |
| 267 | scope: *Scope, |
| 268 | rl: ResultLoc, |
| 269 | node: ast.Node.Index, |
| 270 | src_node: ast.Node.Index, |
| 271 | ) InnerError!Zir.Inst.Ref { |
| 272 | const result_inst = try expr(gz, scope, rl, node); |
| 273 | if (gz.refIsNoReturn(result_inst)) { |
| 274 | return gz.astgen.failNodeNotes(src_node, "unreachable code", .{}, &[_]u32{ |
| 275 | try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}), |
| 276 | }); |
| 277 | } |
| 278 | return result_inst; |
| 279 | } |
| 280 | |
| 264 | 281 | fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 265 | 282 | const astgen = gz.astgen; |
| 266 | 283 | const tree = astgen.tree; |
| ... | ... | @@ -2331,8 +2348,7 @@ fn varDecl( |
| 2331 | 2348 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{ |
| 2332 | 2349 | .ty = try typeExpr(gz, scope, var_decl.ast.type_node), |
| 2333 | 2350 | } else .none; |
| 2334 | | const init_inst = try expr(gz, scope, result_loc, var_decl.ast.init_node); |
| 2335 | | try astgen.checkVarInitExpr(gz.*, node, var_decl.ast.init_node, init_inst, "local constant"); |
| 2351 | const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node); |
| 2336 | 2352 | |
| 2337 | 2353 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 2338 | 2354 | sub_scope.* = .{ |
| ... | ... | @@ -2383,8 +2399,7 @@ fn varDecl( |
| 2383 | 2399 | init_scope.rl_ptr = alloc; |
| 2384 | 2400 | } |
| 2385 | 2401 | const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; |
| 2386 | | const init_inst = try expr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node); |
| 2387 | | try astgen.checkVarInitExpr(init_scope, node, var_decl.ast.init_node, init_inst, "local constant"); |
| 2402 | const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node, node); |
| 2388 | 2403 | |
| 2389 | 2404 | const zir_tags = astgen.instructions.items(.tag); |
| 2390 | 2405 | const zir_datas = astgen.instructions.items(.data); |
| ... | ... | @@ -2486,8 +2501,7 @@ fn varDecl( |
| 2486 | 2501 | resolve_inferred_alloc = alloc; |
| 2487 | 2502 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; |
| 2488 | 2503 | }; |
| 2489 | | const init_inst = try expr(gz, scope, var_data.result_loc, var_decl.ast.init_node); |
| 2490 | | try astgen.checkVarInitExpr(gz.*, node, var_decl.ast.init_node, init_inst, "local variable"); |
| 2504 | _ = try reachableExpr(gz, scope, var_data.result_loc, var_decl.ast.init_node, node); |
| 2491 | 2505 | if (resolve_inferred_alloc != .none) { |
| 2492 | 2506 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 2493 | 2507 | } |
| ... | ... | @@ -6618,14 +6632,14 @@ fn as( |
| 6618 | 6632 | const dest_type = try typeExpr(gz, scope, lhs); |
| 6619 | 6633 | switch (rl) { |
| 6620 | 6634 | .none, .none_or_ref, .discard, .ref, .ty => { |
| 6621 | | const result = try expr(gz, scope, .{ .ty = dest_type }, rhs); |
| 6635 | const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node); |
| 6622 | 6636 | return rvalue(gz, rl, result, node); |
| 6623 | 6637 | }, |
| 6624 | 6638 | .ptr, .inferred_ptr => |result_ptr| { |
| 6625 | | return asRlPtr(gz, scope, rl, result_ptr, rhs, dest_type); |
| 6639 | return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type); |
| 6626 | 6640 | }, |
| 6627 | 6641 | .block_ptr => |block_scope| { |
| 6628 | | return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type); |
| 6642 | return asRlPtr(gz, scope, rl, node, block_scope.rl_ptr, rhs, dest_type); |
| 6629 | 6643 | }, |
| 6630 | 6644 | } |
| 6631 | 6645 | } |
| ... | ... | @@ -6679,6 +6693,7 @@ fn asRlPtr( |
| 6679 | 6693 | parent_gz: *GenZir, |
| 6680 | 6694 | scope: *Scope, |
| 6681 | 6695 | rl: ResultLoc, |
| 6696 | src_node: ast.Node.Index, |
| 6682 | 6697 | result_ptr: Zir.Inst.Ref, |
| 6683 | 6698 | operand_node: ast.Node.Index, |
| 6684 | 6699 | dest_type: Zir.Inst.Ref, |
| ... | ... | @@ -6692,7 +6707,7 @@ fn asRlPtr( |
| 6692 | 6707 | defer as_scope.instructions.deinit(astgen.gpa); |
| 6693 | 6708 | |
| 6694 | 6709 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); |
| 6695 | | const result = try expr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node); |
| 6710 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); |
| 6696 | 6711 | const parent_zir = &parent_gz.instructions; |
| 6697 | 6712 | if (as_scope.rvalue_rl_count == 1) { |
| 6698 | 6713 | // Busted! This expression didn't actually need a pointer. |
| ... | ... | @@ -9607,27 +9622,3 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 9607 | 9622 | astgen.source_line = line; |
| 9608 | 9623 | astgen.source_column = column; |
| 9609 | 9624 | } |
| 9610 | | |
| 9611 | | fn checkVarInitExpr( |
| 9612 | | astgen: *AstGen, |
| 9613 | | gz: GenZir, |
| 9614 | | var_node: ast.Node.Index, |
| 9615 | | init_node: ast.Node.Index, |
| 9616 | | init_inst: Zir.Inst.Ref, |
| 9617 | | var_name_text: []const u8, |
| 9618 | | ) !void { |
| 9619 | | if (gz.refIsNoReturn(init_inst)) { |
| 9620 | | return astgen.failNodeNotes( |
| 9621 | | var_node, |
| 9622 | | "useless {s}", |
| 9623 | | .{var_name_text}, |
| 9624 | | &[_]u32{ |
| 9625 | | try astgen.errNoteNode( |
| 9626 | | init_node, |
| 9627 | | "control flow is diverted here", |
| 9628 | | .{}, |
| 9629 | | ), |
| 9630 | | }, |
| 9631 | | ); |
| 9632 | | } |
| 9633 | | } |