authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-09-12 19:20:52+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-09-12 23:46:00+01:00
log55250a9370ae247d52d9d78033880451cb1e9add
treedcab4d53790c01b43aac9e94cbe4d3a84b8e2dca
parent03c363300fd829f3a656c6a9854a9c9720c9b3f1

Sema: perform requested coercion when decl literal demoted to enum literal

Resolves: #21392

2 files changed, 31 insertions(+), 17 deletions(-)

src/Sema.zig+22-17
......@@ -8980,36 +8980,41 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b
89808980 sema.code.nullTerminatedString(extra.field_name_start),
89818981 .no_embedded_nulls,
89828982 );
8983
89838984 const orig_ty = sema.resolveType(block, src, extra.lhs) catch |err| switch (err) {
8984 error.GenericPoison => {
8985 // Treat this as a normal enum literal.
8986 return Air.internedToRef(try pt.intern(.{ .enum_literal = name }));
8987 },
8985 error.GenericPoison => Type.generic_poison,
89888986 else => |e| return e,
89898987 };
89908988
8991 var ty = orig_ty;
8992 while (true) switch (ty.zigTypeTag(zcu)) {
8993 .error_union => ty = ty.errorUnionPayload(zcu),
8994 .optional => ty = ty.optionalChild(zcu),
8995 .enum_literal, .error_set => {
8989 const uncoerced_result = res: {
8990 if (orig_ty.toIntern() == .generic_poison_type) {
89968991 // Treat this as a normal enum literal.
8997 return Air.internedToRef(try pt.intern(.{ .enum_literal = name }));
8998 },
8999 else => break,
9000 };
8992 break :res Air.internedToRef(try pt.intern(.{ .enum_literal = name }));
8993 }
8994
8995 var ty = orig_ty;
8996 while (true) switch (ty.zigTypeTag(zcu)) {
8997 .error_union => ty = ty.errorUnionPayload(zcu),
8998 .optional => ty = ty.optionalChild(zcu),
8999 .enum_literal, .error_set => {
9000 // Treat this as a normal enum literal.
9001 break :res Air.internedToRef(try pt.intern(.{ .enum_literal = name }));
9002 },
9003 else => break,
9004 };
90019005
9002 const result = try sema.fieldVal(block, src, Air.internedToRef(ty.toIntern()), name, src);
9006 break :res try sema.fieldVal(block, src, Air.internedToRef(ty.toIntern()), name, src);
9007 };
90039008
90049009 // Decl literals cannot lookup runtime `var`s.
9005 if (!try sema.isComptimeKnown(result)) {
9010 if (!try sema.isComptimeKnown(uncoerced_result)) {
90069011 return sema.fail(block, src, "decl literal must be comptime-known", .{});
90079012 }
90089013
90099014 if (do_coerce) {
9010 return sema.coerce(block, orig_ty, result, src);
9015 return sema.coerce(block, orig_ty, uncoerced_result, src);
90119016 } else {
9012 return result;
9017 return uncoerced_result;
90139018 }
90149019}
90159020
test/cases/compile_errors/error_set_decl_literal.zig created+9
......@@ -0,0 +1,9 @@
1export fn entry() void {
2 const E = error{Foo};
3 const e: E = .Foo;
4 _ = e;
5}
6
7// error
8//
9// :3:19: error: expected type 'error{Foo}', found '@TypeOf(.enum_literal)'