Skip to content

Commit 2594132

Browse files
committedJun 12, 2018
fix ability to call mutating methods on zero size structs
closes #838
1 parent 7580e39 commit 2594132

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed
 

‎src/ir.cpp‎

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8151,6 +8151,17 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
81518151
}
81528152
}
81538153

8154+
// implicit T to *T where T is zero bits
8155+
if (expected_type->id == TypeTableEntryIdPointer && expected_type->data.pointer.ptr_len == PtrLenSingle &&
8156+
types_match_const_cast_only(ira, expected_type->data.pointer.child_type,
8157+
actual_type, source_node).id == ConstCastResultIdOk)
8158+
{
8159+
type_ensure_zero_bits_known(ira->codegen, actual_type);
8160+
if (!type_has_bits(actual_type)) {
8161+
return ImplicitCastMatchResultYes;
8162+
}
8163+
}
8164+
81548165
// implicit undefined literal to anything
81558166
if (actual_type->id == TypeTableEntryIdUndefined) {
81568167
return ImplicitCastMatchResultYes;
@@ -8820,7 +8831,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
88208831
static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
88218832
TypeTableEntry *wanted_type, CastOp cast_op, bool need_alloca)
88228833
{
8823-
if (value->value.special != ConstValSpecialRuntime &&
8834+
if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
88248835
cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice)
88258836
{
88268837
IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
@@ -9382,9 +9393,19 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
93829393

93839394
if (value->id == IrInstructionIdLoadPtr) {
93849395
IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *) value;
9396+
93859397
if (load_ptr_inst->ptr->value.type->data.pointer.is_const) {
93869398
return load_ptr_inst->ptr;
93879399
}
9400+
9401+
type_ensure_zero_bits_known(ira->codegen, value->value.type);
9402+
if (type_is_invalid(value->value.type)) {
9403+
return ira->codegen->invalid_instruction;
9404+
}
9405+
9406+
if (!type_has_bits(value->value.type)) {
9407+
return load_ptr_inst->ptr;
9408+
}
93889409
}
93899410

93909411
if (instr_is_comptime(value)) {
@@ -10340,6 +10361,20 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1034010361
}
1034110362
}
1034210363

10364+
// explicit cast from T to *T where T is zero bits
10365+
if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
10366+
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
10367+
actual_type, source_node).id == ConstCastResultIdOk)
10368+
{
10369+
type_ensure_zero_bits_known(ira->codegen, actual_type);
10370+
if (type_is_invalid(actual_type)) {
10371+
return ira->codegen->invalid_instruction;
10372+
}
10373+
if (!type_has_bits(actual_type)) {
10374+
return ir_get_ref(ira, source_instr, value, false, false);
10375+
}
10376+
}
10377+
1034310378

1034410379
// explicit cast from undefined to anything
1034510380
if (actual_type->id == TypeTableEntryIdUndefined) {

‎test/cases/struct.zig‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,20 @@ const Expr = union(enum) {
421421
fn alloc(comptime T: type) []T {
422422
return []T{};
423423
}
424+
425+
test "call method with mutable reference to struct with no fields" {
426+
const S = struct {
427+
fn doC(s: *const this) bool {
428+
return true;
429+
}
430+
fn do(s: *this) bool {
431+
return true;
432+
}
433+
};
434+
435+
var s = S{};
436+
assert(S.doC(&s));
437+
assert(s.doC());
438+
assert(S.do(&s));
439+
assert(s.do());
440+
}

0 commit comments

Comments
 (0)