mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-07 22:34:28 +00:00
stage2: actually coerce in coerce_result_ptr at comptime
This commit is contained in:
parent
b3aa1ab693
commit
ee149aaa03
5 changed files with 63 additions and 10 deletions
31
src/Sema.zig
31
src/Sema.zig
|
|
@ -1598,11 +1598,37 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
|
||||||
// we cannot do it.
|
// we cannot do it.
|
||||||
if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
|
if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
|
||||||
if (ptr_val.isComptimeMutablePtr()) {
|
if (ptr_val.isComptimeMutablePtr()) {
|
||||||
|
const sentinel_val = try sema.addConstant(pointee_ty, Value.initTag(.unreachable_value));
|
||||||
|
const coerced = try sema.coerce(block, sema.typeOf(ptr).childType(), sentinel_val, src);
|
||||||
|
|
||||||
|
var res_ptr = ptr_val;
|
||||||
|
var cur_val = (try sema.resolveMaybeUndefVal(block, .unneeded, coerced)).?;
|
||||||
|
while (true) switch (cur_val.tag()) {
|
||||||
|
.unreachable_value => break,
|
||||||
|
.opt_payload => {
|
||||||
|
res_ptr = try Value.Tag.opt_payload_ptr.create(sema.arena, res_ptr);
|
||||||
|
cur_val = cur_val.castTag(.opt_payload).?.data;
|
||||||
|
},
|
||||||
|
.eu_payload => {
|
||||||
|
res_ptr = try Value.Tag.eu_payload_ptr.create(sema.arena, res_ptr);
|
||||||
|
cur_val = cur_val.castTag(.eu_payload).?.data;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
if (std.debug.runtime_safety) {
|
||||||
|
std.debug.panic("unexpected Value tag for coerce_result_ptr: {s}", .{
|
||||||
|
cur_val.tag(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const ptr_ty = try Type.ptr(sema.arena, .{
|
const ptr_ty = try Type.ptr(sema.arena, .{
|
||||||
.pointee_type = pointee_ty,
|
.pointee_type = pointee_ty,
|
||||||
.@"addrspace" = addr_space,
|
.@"addrspace" = addr_space,
|
||||||
});
|
});
|
||||||
return sema.addConstant(ptr_ty, ptr_val);
|
return sema.addConstant(ptr_ty, res_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1673,7 +1699,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else unreachable; // TODO should not need else unreachable
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyzeStructDecl(
|
pub fn analyzeStructDecl(
|
||||||
|
|
@ -16937,7 +16963,6 @@ fn wrapErrorUnionPayload(
|
||||||
const dest_payload_ty = dest_ty.errorUnionPayload();
|
const dest_payload_ty = dest_ty.errorUnionPayload();
|
||||||
const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
|
const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
|
||||||
if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {
|
if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {
|
||||||
if (val.isUndef()) return sema.addConstUndef(dest_ty);
|
|
||||||
return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
|
return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
|
||||||
}
|
}
|
||||||
try sema.requireRuntimeBlock(block, inst_src);
|
try sema.requireRuntimeBlock(block, inst_src);
|
||||||
|
|
|
||||||
|
|
@ -3980,7 +3980,7 @@ pub const Type = extern union {
|
||||||
|
|
||||||
pub fn structFields(ty: Type) Module.Struct.Fields {
|
pub fn structFields(ty: Type) Module.Struct.Fields {
|
||||||
switch (ty.tag()) {
|
switch (ty.tag()) {
|
||||||
.empty_struct => return .{},
|
.empty_struct, .empty_struct_literal => return .{},
|
||||||
.@"struct" => {
|
.@"struct" => {
|
||||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||||
assert(struct_obj.haveFieldTypes());
|
assert(struct_obj.haveFieldTypes());
|
||||||
|
|
@ -3996,7 +3996,7 @@ pub const Type = extern union {
|
||||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||||
return struct_obj.fields.count();
|
return struct_obj.fields.count();
|
||||||
},
|
},
|
||||||
.empty_struct => return 0,
|
.empty_struct, .empty_struct_literal => return 0,
|
||||||
.tuple => return ty.castTag(.tuple).?.data.types.len,
|
.tuple => return ty.castTag(.tuple).?.data.types.len,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -371,7 +371,9 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "implicitly cast from T to anyerror!?T" {
|
test "implicitly cast from T to anyerror!?T" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||||
|
|
||||||
try castToOptionalTypeError(1);
|
try castToOptionalTypeError(1);
|
||||||
comptime try castToOptionalTypeError(1);
|
comptime try castToOptionalTypeError(1);
|
||||||
|
|
@ -387,7 +389,7 @@ fn castToOptionalTypeError(z: i32) !void {
|
||||||
|
|
||||||
const f = z;
|
const f = z;
|
||||||
const g: anyerror!?i32 = f;
|
const g: anyerror!?i32 = f;
|
||||||
_ = g catch {};
|
_ = try g;
|
||||||
|
|
||||||
const a = A{ .a = z };
|
const a = A{ .a = z };
|
||||||
const b: anyerror!?A = a;
|
const b: anyerror!?A = a;
|
||||||
|
|
|
||||||
|
|
@ -294,10 +294,11 @@ fn quux_1() !i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "error: Zero sized error set returned with value payload crash" {
|
test "error: Zero sized error set returned with value payload crash" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
|
|
||||||
_ = foo3(0) catch {};
|
_ = try foo3(0);
|
||||||
_ = comptime foo3(0) catch {};
|
_ = comptime try foo3(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Error = error{};
|
const Error = error{};
|
||||||
|
|
|
||||||
|
|
@ -1237,3 +1237,28 @@ test "anon init through error union" {
|
||||||
try S.doTheTest();
|
try S.doTheTest();
|
||||||
comptime try S.doTheTest();
|
comptime try S.doTheTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "typed init through error unions and optionals" {
|
||||||
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
const S = struct {
|
||||||
|
a: u32,
|
||||||
|
|
||||||
|
fn foo() anyerror!?anyerror!@This() {
|
||||||
|
return @This(){ .a = 1 };
|
||||||
|
}
|
||||||
|
fn bar() ?anyerror![2]u8 {
|
||||||
|
return [2]u8{ 1, 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn doTheTest() !void {
|
||||||
|
var a = try (try foo()).?;
|
||||||
|
var b = try bar().?;
|
||||||
|
try expect(a.a + b[1] == 3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try S.doTheTest();
|
||||||
|
comptime try S.doTheTest();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue