authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-10 23:26:56+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-10 23:26:56+02:00
log1f8ae10a388bc2836c954c54fa487233fe045dd6
tree3e2a5856269b1c985ad806a214b8550df31ff131
parentdacdc95ea24c12e2f1771f928ffa4bbd18cc3a19
parent4a6cc1c602a08ddff6c498d8c37919c5c0c842f0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13091 from Vexu/small-proposals

Implement some small proposals

22 files changed, 196 insertions(+), 47 deletions(-)

doc/langref.html.in+1-1
...@@ -4064,7 +4064,7 @@ test "labeled break from labeled block expression" {...@@ -4064,7 +4064,7 @@ test "labeled break from labeled block expression" {
40644064
4065 {#header_open|Shadowing#}4065 {#header_open|Shadowing#}
4066 <p>{#link|Identifiers#} are never allowed to "hide" other identifiers by using the same name:</p>4066 <p>{#link|Identifiers#} are never allowed to "hide" other identifiers by using the same name:</p>
4067 {#code_begin|test_err|local shadows declaration#}4067 {#code_begin|test_err|local variable shadows declaration#}
4068const pi = 3.14;4068const pi = 3.14;
40694069
4070test "inside test block" {4070test "inside test block" {
src/AstGen.zig+56-21
...@@ -2004,7 +2004,8 @@ fn blockExpr(...@@ -2004,7 +2004,8 @@ fn blockExpr(
2004 return labeledBlockExpr(gz, scope, rl, block_node, statements);2004 return labeledBlockExpr(gz, scope, rl, block_node, statements);
2005 }2005 }
20062006
2007 try blockExprStmts(gz, scope, statements);2007 var sub_gz = gz.makeSubBlock(scope);
2008 try blockExprStmts(&sub_gz, &sub_gz.base, statements);
2008 return rvalue(gz, rl, .void_value, block_node);2009 return rvalue(gz, rl, .void_value, block_node);
2009}2010}
20102011
...@@ -2772,7 +2773,13 @@ fn varDecl(...@@ -2772,7 +2773,13 @@ fn varDecl(
2772 }2773 }
2773 const ident_name = try astgen.identAsString(name_token);2774 const ident_name = try astgen.identAsString(name_token);
27742775
2775 try astgen.detectLocalShadowing(scope, ident_name, name_token, ident_name_raw);2776 try astgen.detectLocalShadowing(
2777 scope,
2778 ident_name,
2779 name_token,
2780 ident_name_raw,
2781 if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable",
2782 );
27762783
2777 if (var_decl.ast.init_node == 0) {2784 if (var_decl.ast.init_node == 0) {
2778 return astgen.failNode(node, "variables must be initialized", .{});2785 return astgen.failNode(node, "variables must be initialized", .{});
...@@ -3502,7 +3509,7 @@ fn fnDecl(...@@ -3502,7 +3509,7 @@ fn fnDecl(
35023509
3503 const param_name = try astgen.identAsString(name_token);3510 const param_name = try astgen.identAsString(name_token);
3504 if (!is_extern) {3511 if (!is_extern) {
3505 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes);3512 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes, .@"function parameter");
3506 }3513 }
3507 break :blk param_name;3514 break :blk param_name;
3508 } else if (!is_extern) {3515 } else if (!is_extern) {
...@@ -5181,7 +5188,7 @@ fn orelseCatchExpr(...@@ -5181,7 +5188,7 @@ fn orelseCatchExpr(
5181 }5188 }
5182 const err_name = try astgen.identAsString(payload);5189 const err_name = try astgen.identAsString(payload);
51835190
5184 try astgen.detectLocalShadowing(scope, err_name, payload, err_str);5191 try astgen.detectLocalShadowing(scope, err_name, payload, err_str, .@"capture");
51855192
5186 err_val_scope = .{5193 err_val_scope = .{
5187 .parent = &else_scope.base,5194 .parent = &else_scope.base,
...@@ -5480,7 +5487,7 @@ fn ifExpr(...@@ -5480,7 +5487,7 @@ fn ifExpr(
5480 const token_name_str = tree.tokenSlice(token_name_index);5487 const token_name_str = tree.tokenSlice(token_name_index);
5481 if (mem.eql(u8, "_", token_name_str))5488 if (mem.eql(u8, "_", token_name_str))
5482 break :s &then_scope.base;5489 break :s &then_scope.base;
5483 try astgen.detectLocalShadowing(&then_scope.base, ident_name, token_name_index, token_name_str);5490 try astgen.detectLocalShadowing(&then_scope.base, ident_name, token_name_index, token_name_str, .@"capture");
5484 payload_val_scope = .{5491 payload_val_scope = .{
5485 .parent = &then_scope.base,5492 .parent = &then_scope.base,
5486 .gen_zir = &then_scope,5493 .gen_zir = &then_scope,
...@@ -5505,7 +5512,7 @@ fn ifExpr(...@@ -5505,7 +5512,7 @@ fn ifExpr(
5505 break :s &then_scope.base;5512 break :s &then_scope.base;
5506 const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr);5513 const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr);
5507 const ident_name = try astgen.identAsString(ident_token);5514 const ident_name = try astgen.identAsString(ident_token);
5508 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes);5515 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes, .@"capture");
5509 payload_val_scope = .{5516 payload_val_scope = .{
5510 .parent = &then_scope.base,5517 .parent = &then_scope.base,
5511 .gen_zir = &then_scope,5518 .gen_zir = &then_scope,
...@@ -5551,7 +5558,7 @@ fn ifExpr(...@@ -5551,7 +5558,7 @@ fn ifExpr(
5551 const error_token_str = tree.tokenSlice(error_token);5558 const error_token_str = tree.tokenSlice(error_token);
5552 if (mem.eql(u8, "_", error_token_str))5559 if (mem.eql(u8, "_", error_token_str))
5553 break :s &else_scope.base;5560 break :s &else_scope.base;
5554 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, error_token_str);5561 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, error_token_str, .@"capture");
5555 payload_val_scope = .{5562 payload_val_scope = .{
5556 .parent = &else_scope.base,5563 .parent = &else_scope.base,
5557 .gen_zir = &else_scope,5564 .gen_zir = &else_scope,
...@@ -5816,7 +5823,7 @@ fn whileExpr(...@@ -5816,7 +5823,7 @@ fn whileExpr(
5816 break :s &then_scope.base;5823 break :s &then_scope.base;
5817 const payload_name_loc = payload_token + @boolToInt(payload_is_ref);5824 const payload_name_loc = payload_token + @boolToInt(payload_is_ref);
5818 const ident_name = try astgen.identAsString(payload_name_loc);5825 const ident_name = try astgen.identAsString(payload_name_loc);
5819 try astgen.detectLocalShadowing(&then_scope.base, ident_name, payload_name_loc, ident_bytes);5826 try astgen.detectLocalShadowing(&then_scope.base, ident_name, payload_name_loc, ident_bytes, .@"capture");
5820 payload_val_scope = .{5827 payload_val_scope = .{
5821 .parent = &then_scope.base,5828 .parent = &then_scope.base,
5822 .gen_zir = &then_scope,5829 .gen_zir = &then_scope,
...@@ -5843,7 +5850,7 @@ fn whileExpr(...@@ -5843,7 +5850,7 @@ fn whileExpr(
5843 const ident_bytes = tree.tokenSlice(ident_token);5850 const ident_bytes = tree.tokenSlice(ident_token);
5844 if (mem.eql(u8, "_", ident_bytes))5851 if (mem.eql(u8, "_", ident_bytes))
5845 break :s &then_scope.base;5852 break :s &then_scope.base;
5846 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes);5853 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes, .@"capture");
5847 payload_val_scope = .{5854 payload_val_scope = .{
5848 .parent = &then_scope.base,5855 .parent = &then_scope.base,
5849 .gen_zir = &then_scope,5856 .gen_zir = &then_scope,
...@@ -5919,7 +5926,7 @@ fn whileExpr(...@@ -5919,7 +5926,7 @@ fn whileExpr(
5919 const ident_bytes = tree.tokenSlice(error_token);5926 const ident_bytes = tree.tokenSlice(error_token);
5920 if (mem.eql(u8, ident_bytes, "_"))5927 if (mem.eql(u8, ident_bytes, "_"))
5921 break :s &else_scope.base;5928 break :s &else_scope.base;
5922 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, ident_bytes);5929 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, ident_bytes, .@"capture");
5923 payload_val_scope = .{5930 payload_val_scope = .{
5924 .parent = &else_scope.base,5931 .parent = &else_scope.base,
5925 .gen_zir = &else_scope,5932 .gen_zir = &else_scope,
...@@ -6092,7 +6099,7 @@ fn forExpr(...@@ -6092,7 +6099,7 @@ fn forExpr(
6092 .lhs = array_ptr,6099 .lhs = array_ptr,
6093 .rhs = index,6100 .rhs = index,
6094 });6101 });
6095 try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name);6102 try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name, .@"capture");
6096 payload_val_scope = .{6103 payload_val_scope = .{
6097 .parent = &then_scope.base,6104 .parent = &then_scope.base,
6098 .gen_zir = &then_scope,6105 .gen_zir = &then_scope,
...@@ -6118,7 +6125,7 @@ fn forExpr(...@@ -6118,7 +6125,7 @@ fn forExpr(
6118 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});6125 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});
6119 }6126 }
6120 const index_name = try astgen.identAsString(index_token);6127 const index_name = try astgen.identAsString(index_token);
6121 try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token, token_bytes);6128 try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token, token_bytes, .@"loop index capture");
6122 index_scope = .{6129 index_scope = .{
6123 .parent = payload_sub_scope,6130 .parent = payload_sub_scope,
6124 .gen_zir = &then_scope,6131 .gen_zir = &then_scope,
...@@ -6433,7 +6440,7 @@ fn switchExpr(...@@ -6433,7 +6440,7 @@ fn switchExpr(
6433 });6440 });
6434 }6441 }
6435 const capture_name = try astgen.identAsString(ident);6442 const capture_name = try astgen.identAsString(ident);
6436 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice);6443 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice, .@"capture");
6437 capture_val_scope = .{6444 capture_val_scope = .{
6438 .parent = &case_scope.base,6445 .parent = &case_scope.base,
6439 .gen_zir = &case_scope,6446 .gen_zir = &case_scope,
...@@ -6458,7 +6465,7 @@ fn switchExpr(...@@ -6458,7 +6465,7 @@ fn switchExpr(
6458 return astgen.failTok(tag_token, "tag capture on non-inline prong", .{});6465 return astgen.failTok(tag_token, "tag capture on non-inline prong", .{});
6459 }6466 }
6460 const tag_name = try astgen.identAsString(tag_token);6467 const tag_name = try astgen.identAsString(tag_token);
6461 try astgen.detectLocalShadowing(payload_sub_scope, tag_name, tag_token, tag_slice);6468 try astgen.detectLocalShadowing(payload_sub_scope, tag_name, tag_token, tag_slice, .@"switch tag capture");
6462 tag_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);6469 tag_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
6463 try astgen.instructions.append(gpa, .{6470 try astgen.instructions.append(gpa, .{
6464 .tag = .switch_capture_tag,6471 .tag = .switch_capture_tag,
...@@ -11669,6 +11676,7 @@ fn detectLocalShadowing(...@@ -11669,6 +11676,7 @@ fn detectLocalShadowing(
11669 ident_name: u32,11676 ident_name: u32,
11670 name_token: Ast.TokenIndex,11677 name_token: Ast.TokenIndex,
11671 token_bytes: []const u8,11678 token_bytes: []const u8,
11679 id_cat: Scope.IdCat,
11672) !void {11680) !void {
11673 const gpa = astgen.gpa;11681 const gpa = astgen.gpa;
11674 if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {11682 if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
...@@ -11682,6 +11690,7 @@ fn detectLocalShadowing(...@@ -11682,6 +11690,7 @@ fn detectLocalShadowing(
11682 }11690 }
1168311691
11684 var s = scope;11692 var s = scope;
11693 var outer_scope = false;
11685 while (true) switch (s.tag) {11694 while (true) switch (s.tag) {
11686 .local_val => {11695 .local_val => {
11687 const local_val = s.cast(Scope.LocalVal).?;11696 const local_val = s.cast(Scope.LocalVal).?;
...@@ -11689,6 +11698,17 @@ fn detectLocalShadowing(...@@ -11689,6 +11698,17 @@ fn detectLocalShadowing(
11689 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));11698 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
11690 const name = try gpa.dupe(u8, name_slice);11699 const name = try gpa.dupe(u8, name_slice);
11691 defer gpa.free(name);11700 defer gpa.free(name);
11701 if (outer_scope) {
11702 return astgen.failTokNotes(name_token, "{s} '{s}' shadows {s} from outer scope", .{
11703 @tagName(id_cat), name, @tagName(local_val.id_cat),
11704 }, &[_]u32{
11705 try astgen.errNoteTok(
11706 local_val.token_src,
11707 "previous declaration here",
11708 .{},
11709 ),
11710 });
11711 }
11692 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{11712 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
11693 @tagName(local_val.id_cat), name,11713 @tagName(local_val.id_cat), name,
11694 }, &[_]u32{11714 }, &[_]u32{
...@@ -11707,6 +11727,17 @@ fn detectLocalShadowing(...@@ -11707,6 +11727,17 @@ fn detectLocalShadowing(
11707 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));11727 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
11708 const name = try gpa.dupe(u8, name_slice);11728 const name = try gpa.dupe(u8, name_slice);
11709 defer gpa.free(name);11729 defer gpa.free(name);
11730 if (outer_scope) {
11731 return astgen.failTokNotes(name_token, "{s} '{s}' shadows {s} from outer scope", .{
11732 @tagName(id_cat), name, @tagName(local_ptr.id_cat),
11733 }, &[_]u32{
11734 try astgen.errNoteTok(
11735 local_ptr.token_src,
11736 "previous declaration here",
11737 .{},
11738 ),
11739 });
11740 }
11710 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{11741 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
11711 @tagName(local_ptr.id_cat), name,11742 @tagName(local_ptr.id_cat), name,
11712 }, &[_]u32{11743 }, &[_]u32{
...@@ -11720,6 +11751,7 @@ fn detectLocalShadowing(...@@ -11720,6 +11751,7 @@ fn detectLocalShadowing(
11720 s = local_ptr.parent;11751 s = local_ptr.parent;
11721 },11752 },
11722 .namespace => {11753 .namespace => {
11754 outer_scope = true;
11723 const ns = s.cast(Scope.Namespace).?;11755 const ns = s.cast(Scope.Namespace).?;
11724 const decl_node = ns.decls.get(ident_name) orelse {11756 const decl_node = ns.decls.get(ident_name) orelse {
11725 s = ns.parent;11757 s = ns.parent;
...@@ -11728,13 +11760,16 @@ fn detectLocalShadowing(...@@ -11728,13 +11760,16 @@ fn detectLocalShadowing(
11728 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));11760 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
11729 const name = try gpa.dupe(u8, name_slice);11761 const name = try gpa.dupe(u8, name_slice);
11730 defer gpa.free(name);11762 defer gpa.free(name);
11731 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{11763 return astgen.failTokNotes(name_token, "{s} shadows declaration of '{s}'", .{
11732 name,11764 @tagName(id_cat), name,
11733 }, &[_]u32{11765 }, &[_]u32{
11734 try astgen.errNoteNode(decl_node, "declared here", .{}),11766 try astgen.errNoteNode(decl_node, "declared here", .{}),
11735 });11767 });
11736 },11768 },
11737 .gen_zir => s = s.cast(GenZir).?.parent,11769 .gen_zir => {
11770 s = s.cast(GenZir).?.parent;
11771 outer_scope = true;
11772 },
11738 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,11773 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
11739 .top => break,11774 .top => break,
11740 };11775 };
...@@ -11844,8 +11879,8 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -11844,8 +11879,8 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
11844 .local_val => {11879 .local_val => {
11845 const local_val = s.cast(Scope.LocalVal).?;11880 const local_val = s.cast(Scope.LocalVal).?;
11846 if (local_val.name == name_str_index) {11881 if (local_val.name == name_str_index) {
11847 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{11882 return astgen.failTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{
11848 @tagName(local_val.id_cat), token_bytes,11883 token_bytes, @tagName(local_val.id_cat),
11849 }, &[_]u32{11884 }, &[_]u32{
11850 try astgen.errNoteTok(11885 try astgen.errNoteTok(
11851 local_val.token_src,11886 local_val.token_src,
...@@ -11859,8 +11894,8 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast....@@ -11859,8 +11894,8 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
11859 .local_ptr => {11894 .local_ptr => {
11860 const local_ptr = s.cast(Scope.LocalPtr).?;11895 const local_ptr = s.cast(Scope.LocalPtr).?;
11861 if (local_ptr.name == name_str_index) {11896 if (local_ptr.name == name_str_index) {
11862 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{11897 return astgen.failTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{
11863 @tagName(local_ptr.id_cat), token_bytes,11898 token_bytes, @tagName(local_ptr.id_cat),
11864 }, &[_]u32{11899 }, &[_]u32{
11865 try astgen.errNoteTok(11900 try astgen.errNoteTok(
11866 local_ptr.token_src,11901 local_ptr.token_src,
src/Sema.zig+27
...@@ -7622,6 +7622,10 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -7622,6 +7622,10 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
7622 const inst_data = sema.code.instructions.items(.data)[inst].un_node;7622 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
7623 const src = inst_data.src();7623 const src = inst_data.src();
7624 const operand = try sema.resolveInst(inst_data.operand);7624 const operand = try sema.resolveInst(inst_data.operand);
7625 return sema.analyzeErrUnionCode(block, src, operand);
7626}
7627
7628fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {
7625 const operand_ty = sema.typeOf(operand);7629 const operand_ty = sema.typeOf(operand);
7626 if (operand_ty.zigTypeTag() != .ErrorUnion) {7630 if (operand_ty.zigTypeTag() != .ErrorUnion) {
7627 return sema.fail(block, src, "expected error union type, found '{}'", .{7631 return sema.fail(block, src, "expected error union type, found '{}'", .{
...@@ -9998,6 +10002,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9998,6 +10002,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9998 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);10002 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
9999 }10003 }
1000010004
10005 const backend_supports_is_named_enum = sema.mod.comp.bin_file.options.use_llvm;
10006
10001 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {10007 if (scalar_cases_len + multi_cases_len == 0 and !special.is_inline) {
10002 if (empty_enum) {10008 if (empty_enum) {
10003 return Air.Inst.Ref.void_value;10009 return Air.Inst.Ref.void_value;
...@@ -10008,6 +10014,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10008,6 +10014,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10008 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {10014 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {
10009 return Air.Inst.Ref.unreachable_value;10015 return Air.Inst.Ref.unreachable_value;
10010 }10016 }
10017 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
10018 (!operand_ty.isNonexhaustiveEnum() or union_originally))
10019 {
10020 const ok = try block.addUnOp(.is_named_enum_value, operand);
10021 try sema.addSafetyCheck(block, ok, .corrupt_switch);
10022 }
10011 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);10023 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
10012 }10024 }
1001310025
...@@ -10465,6 +10477,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10465,6 +10477,13 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10465 case_block.wip_capture_scope = wip_captures.scope;10477 case_block.wip_capture_scope = wip_captures.scope;
10466 case_block.inline_case_capture = .none;10478 case_block.inline_case_capture = .none;
1046710479
10480 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and
10481 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
10482 {
10483 const ok = try case_block.addUnOp(.is_named_enum_value, operand);
10484 try sema.addSafetyCheck(&case_block, ok, .corrupt_switch);
10485 }
10486
10468 const analyze_body = if (union_originally and !special.is_inline)10487 const analyze_body = if (union_originally and !special.is_inline)
10469 for (seen_enum_fields) |seen_field, index| {10488 for (seen_enum_fields) |seen_field, index| {
10470 if (seen_field != null) continue;10489 if (seen_field != null) continue;
...@@ -14114,6 +14133,14 @@ fn analyzeCmp(...@@ -14114,6 +14133,14 @@ fn analyzeCmp(
14114 // numeric types.14133 // numeric types.
14115 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);14134 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
14116 }14135 }
14136 if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorUnion and rhs_ty.zigTypeTag() == .ErrorSet) {
14137 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);
14138 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);
14139 }
14140 if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorSet and rhs_ty.zigTypeTag() == .ErrorUnion) {
14141 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
14142 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
14143 }
14117 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };14144 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
14118 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });14145 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } });
14119 if (!resolved_type.isSelfComparable(is_equality_cmp)) {14146 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
test/behavior/error.zig+21
...@@ -809,3 +809,24 @@ test "alignment of wrapping an error union payload" {...@@ -809,3 +809,24 @@ test "alignment of wrapping an error union payload" {
809 };809 };
810 try expect((S.foo() catch unreachable).x == 1234);810 try expect((S.foo() catch unreachable).x == 1234);
811}811}
812
813test "compare error union and error set" {
814 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
816
817 var a: anyerror = error.Foo;
818 var b: anyerror!u32 = error.Bar;
819
820 try expect(a != b);
821 try expect(b != a);
822
823 b = error.Foo;
824
825 try expect(a == b);
826 try expect(b == a);
827
828 b = 2;
829
830 try expect(a != b);
831 try expect(b != a);
832}
test/cases/compile_errors/comparison_with_error_union_and_error_value.zig deleted-10
...@@ -1,10 +0,0 @@
1export fn entry() void {
2 var number_or_error: anyerror!i32 = error.SomethingAwful;
3 _ = number_or_error == error.SomethingAwful;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :3:25: error: operator == not allowed for type 'anyerror!i32'
test/cases/compile_errors/decl_shadows_local.zig+2-2
...@@ -16,7 +16,7 @@ fn bar(a: usize) void {...@@ -16,7 +16,7 @@ fn bar(a: usize) void {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :3:15: error: redeclaration of function parameter 'a'19// :3:15: error: declaration 'a' shadows function parameter from outer scope
20// :1:8: note: previous declaration here20// :1:8: note: previous declaration here
21// :9:19: error: redeclaration of function parameter 'a'21// :9:19: error: declaration 'a' shadows function parameter from outer scope
22// :6:8: note: previous declaration here22// :6:8: note: previous declaration here
test/cases/compile_errors/local_shadows_global_that_occurs_later.zig+1-1
...@@ -8,5 +8,5 @@ fn foo() void {}...@@ -8,5 +8,5 @@ fn foo() void {}
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :2:9: error: local shadows declaration of 'foo'11// :2:9: error: local variable shadows declaration of 'foo'
12// :5:1: note: declared here12// :5:1: note: declared here
test/cases/compile_errors/local_variable_redeclares_parameter.zig+1-1
...@@ -7,5 +7,5 @@ export fn entry() void { f(1); }...@@ -7,5 +7,5 @@ export fn entry() void { f(1); }
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:11: error: redeclaration of function parameter 'a'10// :2:11: error: local constant 'a' shadows function parameter from outer scope
11// :1:6: note: previous declaration here11// :1:6: note: previous declaration here
test/cases/compile_errors/local_variable_shadowing_global.zig+1-1
...@@ -10,5 +10,5 @@ export fn entry() void {...@@ -10,5 +10,5 @@ export fn entry() void {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :5:9: error: local shadows declaration of 'Bar'13// :5:9: error: local variable shadows declaration of 'Bar'
14// :2:1: note: declared here14// :2:1: note: declared here
test/cases/compile_errors/parameter_shadowing_global.zig+1-1
...@@ -8,5 +8,5 @@ export fn entry() void {...@@ -8,5 +8,5 @@ export fn entry() void {
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :2:6: error: local shadows declaration of 'Foo'11// :2:6: error: function parameter shadows declaration of 'Foo'
12// :1:1: note: declared here12// :1:1: note: declared here
test/cases/function_redeclaration.zig+1-1
...@@ -10,5 +10,5 @@ fn foo() void {...@@ -10,5 +10,5 @@ fn foo() void {
10//10//
11// :3:1: error: redeclaration of 'entry'11// :3:1: error: redeclaration of 'entry'
12// :2:1: note: other declaration here12// :2:1: note: other declaration here
13// :6:9: error: local shadows declaration of 'foo'13// :6:9: error: local variable shadows declaration of 'foo'
14// :5:1: note: declared here14// :5:1: note: declared here
test/cases/safety/switch else on corrupt enum value - one prong.zig created+24
...@@ -0,0 +1,24 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "switch on corrupt value")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10const E = enum(u32) {
11 one = 1,
12 two = 2,
13};
14pub fn main() !void {
15 var a: E = undefined;
16 @ptrCast(*u32, &a).* = 255;
17 switch (a) {
18 .one => @panic("one"),
19 else => @panic("else"),
20 }
21}
22// run
23// backend=llvm
24// target=native
test/cases/safety/switch else on corrupt enum value - union.zig created+29
...@@ -0,0 +1,29 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "switch on corrupt value")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10const E = enum(u16) {
11 one = 1,
12 two = 2,
13 _,
14};
15const U = union(E) {
16 one: u16,
17 two: u16,
18};
19pub fn main() !void {
20 var a: U = undefined;
21 @ptrCast(*align(@alignOf(U)) u32, &a).* = 0xFFFF_FFFF;
22 switch (a) {
23 .one => @panic("one"),
24 else => @panic("else"),
25 }
26}
27// run
28// backend=llvm
29// target=native
test/cases/safety/switch else on corrupt enum value.zig created+23
...@@ -0,0 +1,23 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "switch on corrupt value")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10const E = enum(u32) {
11 one = 1,
12 two = 2,
13};
14pub fn main() !void {
15 var a: E = undefined;
16 @ptrCast(*u32, &a).* = 255;
17 switch (a) {
18 else => @panic("else"),
19 }
20}
21// run
22// backend=llvm
23// target=native
test/cases/variable_shadowing.1.zig+1-1
...@@ -5,5 +5,5 @@ pub fn main() void {...@@ -5,5 +5,5 @@ pub fn main() void {
55
6// error6// error
7//7//
8// :3:9: error: local shadows declaration of 'testing'8// :3:9: error: local variable shadows declaration of 'testing'
9// :1:1: note: declared here9// :1:1: note: declared here
test/cases/variable_shadowing.3.zig+1-1
...@@ -6,5 +6,5 @@ pub fn main() void {...@@ -6,5 +6,5 @@ pub fn main() void {
66
7// error7// error
8//8//
9// :3:19: error: redeclaration of local variable 'i'9// :3:19: error: loop index capture 'i' shadows local variable from outer scope
10// :2:9: note: previous declaration here10// :2:9: note: previous declaration here
test/cases/variable_shadowing.4.zig+1-1
...@@ -6,5 +6,5 @@ pub fn main() void {...@@ -6,5 +6,5 @@ pub fn main() void {
66
7// error7// error
8//8//
9// :3:16: error: redeclaration of local variable 'i'9// :3:16: error: capture 'i' shadows local variable from outer scope
10// :2:9: note: previous declaration here10// :2:9: note: previous declaration here
test/cases/variable_shadowing.5.zig+1-1
...@@ -6,5 +6,5 @@ pub fn main() void {...@@ -6,5 +6,5 @@ pub fn main() void {
66
7// error7// error
8//8//
9// :3:18: error: redeclaration of local variable 'i'9// :3:18: error: capture 'i' shadows local variable from outer scope
10// :2:9: note: previous declaration here10// :2:9: note: previous declaration here
test/cases/variable_shadowing.6.zig+1-1
...@@ -9,5 +9,5 @@ pub fn main() void {...@@ -9,5 +9,5 @@ pub fn main() void {
99
10// error10// error
11//11//
12// :5:13: error: redeclaration of local variable 'i'12// :5:13: error: capture 'i' shadows local variable from outer scope
13// :2:9: note: previous declaration here13// :2:9: note: previous declaration here
test/cases/variable_shadowing.7.zig+1-1
...@@ -5,5 +5,5 @@ pub fn main() void {...@@ -5,5 +5,5 @@ pub fn main() void {
55
6// error6// error
7//7//
8// :3:16: error: redeclaration of local variable 'i'8// :3:16: error: capture 'i' shadows local variable from outer scope
9// :2:9: note: previous declaration here9// :2:9: note: previous declaration here
test/cases/variable_shadowing.8.zig+1-1
...@@ -5,5 +5,5 @@ pub fn main() void {...@@ -5,5 +5,5 @@ pub fn main() void {
55
6// error6// error
7//7//
8// :3:16: error: redeclaration of local variable 'i'8// :3:16: error: capture 'i' shadows local variable from outer scope
9// :2:9: note: previous declaration here9// :2:9: note: previous declaration here
test/cases/variable_shadowing.9.zig+1-1
...@@ -5,5 +5,5 @@ pub fn main() void {...@@ -5,5 +5,5 @@ pub fn main() void {
55
6// error6// error
7//7//
8// :3:28: error: redeclaration of local variable 'i'8// :3:28: error: capture 'i' shadows local variable from outer scope
9// :2:9: note: previous declaration here9// :2:9: note: previous declaration here