stage2: coerce enum_literal -> enum

This commit is contained in:
jacob gw 2021-04-06 22:38:25 -04:00
parent 19cf987198
commit 01a39fa1d4
2 changed files with 94 additions and 1 deletions

View File

@ -4702,6 +4702,60 @@ fn coerce(
}
}
},
.Enum => {
if (inst.ty.zigTypeTag() == .EnumLiteral) {
const val = (try sema.resolveDefinedValue(block, inst_src, inst)).?;
const bytes = val.castTag(.enum_literal).?.data;
switch (dest_type.tag()) {
.enum_full => {
const enumeration = dest_type.castTag(.enum_full).?.data;
const enum_fields = enumeration.fields;
const i = enum_fields.getIndex(bytes) orelse return sema.mod.fail(
&block.base,
inst_src,
"enum '{s}' has no field named '{s}'",
.{ enumeration.owner_decl.name, bytes },
);
const val_pl = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
return sema.mod.constInst(sema.arena, inst_src, .{
.ty = dest_type,
.val = val_pl,
});
},
.enum_simple => {
const enumeration = dest_type.castTag(.enum_simple).?.data;
const enum_fields = enumeration.fields;
const i = enum_fields.getIndex(bytes) orelse return sema.mod.fail(
&block.base,
inst_src,
"enum '{s}' has no field named '{s}'",
.{ enumeration.owner_decl.name, bytes },
);
const val_pl = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
return sema.mod.constInst(sema.arena, inst_src, .{
.ty = dest_type,
.val = val_pl,
});
},
.enum_nonexhaustive => {
const enumeration = dest_type.castTag(.enum_nonexhaustive).?.data;
const enum_fields = enumeration.fields;
const i = enum_fields.getIndex(bytes) orelse return sema.mod.fail(
&block.base,
inst_src,
"enum '{s}' has no field named '{s}'",
.{ enumeration.owner_decl.name, bytes },
);
const val_pl = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
return sema.mod.constInst(sema.arena, inst_src, .{
.ty = dest_type,
.val = val_pl,
});
},
else => unreachable,
}
}
},
else => {},
}

View File

@ -1022,7 +1022,7 @@ pub fn addCases(ctx: *TestContext) !void {
"Hello, World!\n",
);
try case.files.append(.{
.src =
.src =
\\pub fn print() void {
\\ asm volatile ("syscall"
\\ :
@ -1598,4 +1598,43 @@ pub fn addCases(ctx: *TestContext) !void {
"",
);
}
{
var case = ctx.exe("enum_literal -> enum", linux_x64);
case.addCompareOutput(
\\const E = enum { a, b };
\\export fn _start() noreturn {
\\ const a: E = .a;
\\ const b: E = .b;
\\ exit();
\\}
\\fn exit() noreturn {
\\ asm volatile ("syscall"
\\ :
\\ : [number] "{rax}" (231),
\\ [arg1] "{rdi}" (0)
\\ : "rcx", "r11", "memory"
\\ );
\\ unreachable;
\\}
,
"",
);
case.addError(
\\const E = enum { a, b };
\\export fn _start() noreturn {
\\ const a: E = .c;
\\ exit();
\\}
\\fn exit() noreturn {
\\ asm volatile ("syscall"
\\ :
\\ : [number] "{rax}" (231),
\\ [arg1] "{rdi}" (0)
\\ : "rcx", "r11", "memory"
\\ );
\\ unreachable;
\\}
, &.{":3:19: error: enum 'E' has no field named 'c'"});
}
}