authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-26 12:03:15-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-26 12:03:15-07:00
log6df26a37d13d21be061a1cccd39dd17e46a81322
tree968733ee0b37a9335cf2a9c4d8fe26874618c671
parent25012ab3d12ac7bcd4e53a90367afc8e97d91c36

Sema: fix coercion from union to its own tag

I had reversed the tag type / union type arguments.

2 files changed, 22 insertions(+), 14 deletions(-)

src/Sema.zig+9-14
...@@ -8253,7 +8253,7 @@ fn analyzeCmpUnionTag(...@@ -8253,7 +8253,7 @@ fn analyzeCmpUnionTag(
8253 tag_src: LazySrcLoc,8253 tag_src: LazySrcLoc,
8254 op: std.math.CompareOperator,8254 op: std.math.CompareOperator,
8255) CompileError!Air.Inst.Ref {8255) CompileError!Air.Inst.Ref {
8256 const union_ty = sema.typeOf(un);8256 const union_ty = try sema.resolveTypeFields(block, un_src, sema.typeOf(un));
8257 const union_tag_ty = union_ty.unionTagType() orelse {8257 const union_tag_ty = union_ty.unionTagType() orelse {
8258 // TODO note at declaration site that says "union foo is not tagged"8258 // TODO note at declaration site that says "union foo is not tagged"
8259 return sema.fail(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});8259 return sema.fail(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
...@@ -9553,7 +9553,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9553,7 +9553,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9553fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9553fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
9554 const inst_data = sema.code.instructions.items(.data)[inst].un_node;9554 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
9555 const src = inst_data.src();9555 const src = inst_data.src();
9556 const type_info_ty = try sema.getBuiltinType(block, src, "TypeInfo");9556 const type_info_ty = try sema.resolveBuiltinTypeFields(block, src, "TypeInfo");
9557 const uncasted_operand = sema.resolveInst(inst_data.operand);9557 const uncasted_operand = sema.resolveInst(inst_data.operand);
9558 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };9558 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
9559 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);9559 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
...@@ -11984,8 +11984,7 @@ fn coerce(...@@ -11984,8 +11984,7 @@ fn coerce(
11984 }11984 }
11985 const dest_ty_src = inst_src; // TODO better source location11985 const dest_ty_src = inst_src; // TODO better source location
11986 const dest_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty_unresolved);11986 const dest_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty_unresolved);
1198711987 const inst_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst));
11988 const inst_ty = sema.typeOf(inst);
11989 // If the types are the same, we can return the operand.11988 // If the types are the same, we can return the operand.
11990 if (dest_ty.eql(inst_ty))11989 if (dest_ty.eql(inst_ty))
11991 return inst;11990 return inst;
...@@ -12167,18 +12166,17 @@ fn coerce(...@@ -12167,18 +12166,17 @@ fn coerce(
12167 // enum literal to enum12166 // enum literal to enum
12168 const val = try sema.resolveConstValue(block, inst_src, inst);12167 const val = try sema.resolveConstValue(block, inst_src, inst);
12169 const bytes = val.castTag(.enum_literal).?.data;12168 const bytes = val.castTag(.enum_literal).?.data;
12170 const resolved_dest_type = try sema.resolveTypeFields(block, inst_src, dest_ty);12169 const field_index = dest_ty.enumFieldIndex(bytes) orelse {
12171 const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse {
12172 const msg = msg: {12170 const msg = msg: {
12173 const msg = try sema.errMsg(12171 const msg = try sema.errMsg(
12174 block,12172 block,
12175 inst_src,12173 inst_src,
12176 "enum '{}' has no field named '{s}'",12174 "enum '{}' has no field named '{s}'",
12177 .{ resolved_dest_type, bytes },12175 .{ dest_ty, bytes },
12178 );12176 );
12179 errdefer msg.destroy(sema.gpa);12177 errdefer msg.destroy(sema.gpa);
12180 try sema.mod.errNoteNonLazy(12178 try sema.mod.errNoteNonLazy(
12181 resolved_dest_type.declSrcLoc(),12179 dest_ty.declSrcLoc(),
12182 msg,12180 msg,
12183 "enum declared here",12181 "enum declared here",
12184 .{},12182 .{},
...@@ -12188,7 +12186,7 @@ fn coerce(...@@ -12188,7 +12186,7 @@ fn coerce(
12188 return sema.failWithOwnedErrorMsg(msg);12186 return sema.failWithOwnedErrorMsg(msg);
12189 };12187 };
12190 return sema.addConstant(12188 return sema.addConstant(
12191 resolved_dest_type,12189 dest_ty,
12192 try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)),12190 try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)),
12193 );12191 );
12194 },12192 },
...@@ -12196,7 +12194,7 @@ fn coerce(...@@ -12196,7 +12194,7 @@ fn coerce(
12196 // union to its own tag type12194 // union to its own tag type
12197 const union_tag_ty = inst_ty.unionTagType() orelse break :blk;12195 const union_tag_ty = inst_ty.unionTagType() orelse break :blk;
12198 if (union_tag_ty.eql(dest_ty)) {12196 if (union_tag_ty.eql(dest_ty)) {
12199 return sema.unionToTag(block, dest_ty, inst, inst_src);12197 return sema.unionToTag(block, inst_ty, inst, inst_src);
12200 }12198 }
12201 },12199 },
12202 else => {},12200 else => {},
...@@ -14108,10 +14106,7 @@ fn semaStructFields(...@@ -14108,10 +14106,7 @@ fn semaStructFields(
14108 }14106 }
14109}14107}
1411014108
14111fn semaUnionFields(14109fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
14112 mod: *Module,
14113 union_obj: *Module.Union,
14114) CompileError!void {
14115 const tracy = trace(@src());14110 const tracy = trace(@src());
14116 defer tracy.end();14111 defer tracy.end();
1411714112
src/type.zig+13
...@@ -2573,6 +2573,19 @@ pub const Type = extern union {...@@ -2573,6 +2573,19 @@ pub const Type = extern union {
2573 pub fn unionTagType(ty: Type) ?Type {2573 pub fn unionTagType(ty: Type) ?Type {
2574 return switch (ty.tag()) {2574 return switch (ty.tag()) {
2575 .union_tagged => ty.castTag(.union_tagged).?.data.tag_ty,2575 .union_tagged => ty.castTag(.union_tagged).?.data.tag_ty,
2576
2577 .atomic_order,
2578 .atomic_rmw_op,
2579 .calling_convention,
2580 .address_space,
2581 .float_mode,
2582 .reduce_op,
2583 .call_options,
2584 .export_options,
2585 .extern_options,
2586 .type_info,
2587 => unreachable, // needed to call resolveTypeFields first
2588
2576 else => null,2589 else => null,
2577 };2590 };
2578 }2591 }