mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
fix 0-bit child type coerced to optional return ptr result location
by un-special-casing 0 bit types in result locations
This commit is contained in:
parent
8710fdbf39
commit
287d3c37e1
@ -5700,6 +5700,9 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||
assert(field_type != nullptr);
|
||||
result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
|
||||
}
|
||||
} else if (result->type->id == ZigTypeIdPointer) {
|
||||
result->data.x_ptr.special = ConstPtrSpecialRef;
|
||||
result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
|
||||
}
|
||||
g->one_possible_values.put(type_entry, result);
|
||||
return result;
|
||||
@ -9471,7 +9474,11 @@ static void dump_value_indent(ZigValue *val, int indent) {
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
fprintf(stderr, "%s: ", buf_ptr(val->type->data.structure.fields[i]->name));
|
||||
dump_value_indent(val->data.x_struct.fields[i], 1);
|
||||
if (val->data.x_struct.fields == nullptr) {
|
||||
fprintf(stderr, "<null>\n");
|
||||
} else {
|
||||
dump_value_indent(val->data.x_struct.fields[i], 1);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < indent; i += 1) {
|
||||
fprintf(stderr, " ");
|
||||
@ -9505,6 +9512,9 @@ static void dump_value_indent(ZigValue *val, int indent) {
|
||||
|
||||
case ZigTypeIdPointer:
|
||||
switch (val->data.x_ptr.special) {
|
||||
case ConstPtrSpecialInvalid:
|
||||
fprintf(stderr, "<!invalid ptr!>\n");
|
||||
return;
|
||||
case ConstPtrSpecialRef:
|
||||
fprintf(stderr, "<ref\n");
|
||||
dump_value_indent(val->data.x_ptr.data.ref.pointee, indent + 1);
|
||||
@ -9526,6 +9536,14 @@ static void dump_value_indent(ZigValue *val, int indent) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConstPtrSpecialBaseOptionalPayload: {
|
||||
ZigValue *optional_val = val->data.x_ptr.data.base_optional_payload.optional_val;
|
||||
fprintf(stderr, "<optional %p payload\n", optional_val);
|
||||
if (optional_val != nullptr) {
|
||||
dump_value_indent(optional_val, indent + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "TODO dump more pointer things\n");
|
||||
}
|
||||
|
||||
45
src/ir.cpp
45
src/ir.cpp
@ -18576,7 +18576,6 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
|
||||
ResultLoc *result_loc_pass1, ZigType *value_type, IrInstGen *value, bool force_runtime,
|
||||
bool allow_discard)
|
||||
{
|
||||
Error err;
|
||||
if (!allow_discard && result_loc_is_discard(result_loc_pass1)) {
|
||||
result_loc_pass1 = no_result_loc();
|
||||
}
|
||||
@ -18672,32 +18671,22 @@ static IrInstGen *ir_resolve_result(IrAnalyze *ira, IrInst *suspend_source_instr
|
||||
{
|
||||
bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, actual_elem_type, value_type);
|
||||
if (!same_comptime_repr) {
|
||||
bool has_bits;
|
||||
if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
if (has_bits) {
|
||||
result_loc_pass1->written = false;
|
||||
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
|
||||
}
|
||||
result_loc_pass1->written = false;
|
||||
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, result_loc, false, true);
|
||||
}
|
||||
} else if (actual_elem_type->id == ZigTypeIdErrorUnion && value_type->id != ZigTypeIdErrorUnion) {
|
||||
bool has_bits;
|
||||
if ((err = type_has_bits2(ira->codegen, value_type, &has_bits)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
if (has_bits) {
|
||||
if (value_type->id == ZigTypeIdErrorSet) {
|
||||
return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
|
||||
if (value_type->id == ZigTypeIdErrorSet) {
|
||||
return ir_analyze_unwrap_err_code(ira, suspend_source_instr, result_loc, true);
|
||||
} else {
|
||||
IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
|
||||
result_loc, false, true);
|
||||
ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
|
||||
if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
|
||||
value_type->id != ZigTypeIdNull)
|
||||
{
|
||||
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
|
||||
} else {
|
||||
IrInstGen *unwrapped_err_ptr = ir_analyze_unwrap_error_payload(ira, suspend_source_instr,
|
||||
result_loc, false, true);
|
||||
ZigType *actual_payload_type = actual_elem_type->data.error_union.payload_type;
|
||||
if (actual_payload_type->id == ZigTypeIdOptional && value_type->id != ZigTypeIdOptional &&
|
||||
value_type->id != ZigTypeIdNull)
|
||||
{
|
||||
return ir_analyze_unwrap_optional_payload(ira, suspend_source_instr, unwrapped_err_ptr, false, true);
|
||||
} else {
|
||||
return unwrapped_err_ptr;
|
||||
}
|
||||
return unwrapped_err_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22215,14 +22204,8 @@ static IrInstGen *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInst* sou
|
||||
}
|
||||
break;
|
||||
case OnePossibleValueYes: {
|
||||
ZigValue *pointee = create_const_vals(1);
|
||||
pointee->special = ConstValSpecialStatic;
|
||||
pointee->type = child_type;
|
||||
pointee->parent.id = ConstParentIdOptionalPayload;
|
||||
pointee->parent.data.p_optional_payload.optional_val = optional_val;
|
||||
|
||||
optional_val->special = ConstValSpecialStatic;
|
||||
optional_val->data.x_optional = pointee;
|
||||
optional_val->data.x_optional = get_the_one_possible_value(ira->codegen, child_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,3 +153,25 @@ test "optional with void type" {
|
||||
var x = Foo{ .x = null };
|
||||
expect(x.x == null);
|
||||
}
|
||||
|
||||
test "0-bit child type coerced to optional return ptr result location" {
|
||||
const S = struct {
|
||||
fn doTheTest() void {
|
||||
var y = Foo{};
|
||||
var z = y.thing();
|
||||
expect(z != null);
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
pub const Bar = struct {
|
||||
field: *Foo,
|
||||
};
|
||||
|
||||
pub fn thing(self: *Foo) ?Bar {
|
||||
return Bar{ .field = self };
|
||||
}
|
||||
};
|
||||
};
|
||||
S.doTheTest();
|
||||
comptime S.doTheTest();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user