authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-12 15:06:02-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-12 15:06:02-04:00
log259413251df478545948fdbc6213669f88f584bd
tree4fe63d9ad6c04de532c19e57ef009be0154b59b9
parent7580e39b388525237a84aabfb41c462376eac28e

fix ability to call mutating methods on zero size structs

closes #838

2 files changed, 53 insertions(+), 1 deletions(-)

src/ir.cpp+36-1
......@@ -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,
88208831static 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+17
......@@ -421,3 +421,20 @@ const Expr = union(enum) {
421421fn alloc(comptime T: type) []T {
422422 return []T{};
423423}
424
425test "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}