diff --git a/src/ir.cpp b/src/ir.cpp index 531c1b2432..590b81d3be 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16286,6 +16286,15 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i IrInstGen *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2; IrInstGen *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1; + if (!is_tagged_union(union_val->value->type)) { + ErrorMsg *msg = ir_add_error_node(ira, source_node, + buf_sprintf("comparison of union and enum literal is only valid for tagged union types")); + add_error_note(ira->codegen, msg, union_val->value->type->data.unionation.decl_node, + buf_sprintf("type %s is not a tagged union", + buf_ptr(&union_val->value->type->name))); + return ira->codegen->invalid_inst_gen; + } + ZigType *tag_type = union_val->value->type->data.unionation.tag_type; assert(tag_type != nullptr); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index d2e298032f..f19ff11471 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -14,6 +14,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:15: error: unused variable: 'a'", }); + cases.addTest("comparison of non-tagged union and enum literal", + \\export fn entry() void { + \\ const U = union { A: u32, B: u64 }; + \\ var u = U{ .A = 42 }; + \\ var ok = u == .A; + \\} + , &[_][]const u8{ + "tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types", + "tmp.zig:2:15: note: type U is not a tagged union", + }); + cases.addTest("shift on type with non-power-of-two size", \\export fn entry() void { \\ const S = struct {