| ... | @@ -261,6 +261,23 @@ fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zi | ... | @@ -261,6 +261,23 @@ fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zi |
| 261 | return expr(gz, scope, .{ .ty = .type_type }, type_node); | 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 | fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { | 281 | fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 265 | const astgen = gz.astgen; | 282 | const astgen = gz.astgen; |
| 266 | const tree = astgen.tree; | 283 | const tree = astgen.tree; |
| ... | @@ -2331,8 +2348,7 @@ fn varDecl( | ... | @@ -2331,8 +2348,7 @@ fn varDecl( |
| 2331 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{ | 2348 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{ |
| 2332 | .ty = try typeExpr(gz, scope, var_decl.ast.type_node), | 2349 | .ty = try typeExpr(gz, scope, var_decl.ast.type_node), |
| 2333 | } else .none; | 2350 | } else .none; |
| 2334 | const init_inst = try expr(gz, scope, result_loc, var_decl.ast.init_node); | 2351 | const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node); |
| 2335 | try astgen.checkVarInitExpr(gz.*, node, var_decl.ast.init_node, init_inst, "local constant"); | | |
| 2336 | | 2352 | |
| 2337 | const sub_scope = try block_arena.create(Scope.LocalVal); | 2353 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 2338 | sub_scope.* = .{ | 2354 | sub_scope.* = .{ |
| ... | @@ -2383,8 +2399,7 @@ fn varDecl( | ... | @@ -2383,8 +2399,7 @@ fn varDecl( |
| 2383 | init_scope.rl_ptr = alloc; | 2399 | init_scope.rl_ptr = alloc; |
| 2384 | } | 2400 | } |
| 2385 | const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; | 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); | 2402 | const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node, node); |
| 2387 | try astgen.checkVarInitExpr(init_scope, node, var_decl.ast.init_node, init_inst, "local constant"); | | |
| 2388 | | 2403 | |
| 2389 | const zir_tags = astgen.instructions.items(.tag); | 2404 | const zir_tags = astgen.instructions.items(.tag); |
| 2390 | const zir_datas = astgen.instructions.items(.data); | 2405 | const zir_datas = astgen.instructions.items(.data); |
| ... | @@ -2486,8 +2501,7 @@ fn varDecl( | ... | @@ -2486,8 +2501,7 @@ fn varDecl( |
| 2486 | resolve_inferred_alloc = alloc; | 2501 | resolve_inferred_alloc = alloc; |
| 2487 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; | 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); | 2504 | _ = try reachableExpr(gz, scope, var_data.result_loc, var_decl.ast.init_node, node); |
| 2490 | try astgen.checkVarInitExpr(gz.*, node, var_decl.ast.init_node, init_inst, "local variable"); | | |
| 2491 | if (resolve_inferred_alloc != .none) { | 2505 | if (resolve_inferred_alloc != .none) { |
| 2492 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); | 2506 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 2493 | } | 2507 | } |
| ... | @@ -6618,14 +6632,14 @@ fn as( | ... | @@ -6618,14 +6632,14 @@ fn as( |
| 6618 | const dest_type = try typeExpr(gz, scope, lhs); | 6632 | const dest_type = try typeExpr(gz, scope, lhs); |
| 6619 | switch (rl) { | 6633 | switch (rl) { |
| 6620 | .none, .none_or_ref, .discard, .ref, .ty => { | 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 | return rvalue(gz, rl, result, node); | 6636 | return rvalue(gz, rl, result, node); |
| 6623 | }, | 6637 | }, |
| 6624 | .ptr, .inferred_ptr => |result_ptr| { | 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 | .block_ptr => |block_scope| { | 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,6 +6693,7 @@ fn asRlPtr( |
| 6679 | parent_gz: *GenZir, | 6693 | parent_gz: *GenZir, |
| 6680 | scope: *Scope, | 6694 | scope: *Scope, |
| 6681 | rl: ResultLoc, | 6695 | rl: ResultLoc, |
| | 6696 | src_node: ast.Node.Index, |
| 6682 | result_ptr: Zir.Inst.Ref, | 6697 | result_ptr: Zir.Inst.Ref, |
| 6683 | operand_node: ast.Node.Index, | 6698 | operand_node: ast.Node.Index, |
| 6684 | dest_type: Zir.Inst.Ref, | 6699 | dest_type: Zir.Inst.Ref, |
| ... | @@ -6692,7 +6707,7 @@ fn asRlPtr( | ... | @@ -6692,7 +6707,7 @@ fn asRlPtr( |
| 6692 | defer as_scope.instructions.deinit(astgen.gpa); | 6707 | defer as_scope.instructions.deinit(astgen.gpa); |
| 6693 | | 6708 | |
| 6694 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); | 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 | const parent_zir = &parent_gz.instructions; | 6711 | const parent_zir = &parent_gz.instructions; |
| 6697 | if (as_scope.rvalue_rl_count == 1) { | 6712 | if (as_scope.rvalue_rl_count == 1) { |
| 6698 | // Busted! This expression didn't actually need a pointer. | 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,27 +9622,3 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 9607 | astgen.source_line = line; | 9622 | astgen.source_line = line; |
| 9608 | astgen.source_column = column; | 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 | } | | |