diff options
| -rw-r--r-- | src/ir.cpp | 37 | ||||
| -rw-r--r-- | test/cases/struct.zig | 17 |
2 files changed, 53 insertions, 1 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 4b6d5fdcf1..4cebc488b8 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8151,6 +8151,17 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, } } + // implicit T to *T where T is zero bits + if (expected_type->id == TypeTableEntryIdPointer && expected_type->data.pointer.ptr_len == PtrLenSingle && + types_match_const_cast_only(ira, expected_type->data.pointer.child_type, + actual_type, source_node).id == ConstCastResultIdOk) + { + type_ensure_zero_bits_known(ira->codegen, actual_type); + if (!type_has_bits(actual_type)) { + return ImplicitCastMatchResultYes; + } + } + // implicit undefined literal to anything if (actual_type->id == TypeTableEntryIdUndefined) { return ImplicitCastMatchResultYes; @@ -8820,7 +8831,7 @@ static void eval_const_expr_implicit_cast(CastOp cast_op, static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type, CastOp cast_op, bool need_alloca) { - if (value->value.special != ConstValSpecialRuntime && + if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice) { 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 if (value->id == IrInstructionIdLoadPtr) { IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *) value; + if (load_ptr_inst->ptr->value.type->data.pointer.is_const) { return load_ptr_inst->ptr; } + + type_ensure_zero_bits_known(ira->codegen, value->value.type); + if (type_is_invalid(value->value.type)) { + return ira->codegen->invalid_instruction; + } + + if (!type_has_bits(value->value.type)) { + return load_ptr_inst->ptr; + } } if (instr_is_comptime(value)) { @@ -10340,6 +10361,20 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } } + // explicit cast from T to *T where T is zero bits + if (wanted_type->id == TypeTableEntryIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle && + types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, + actual_type, source_node).id == ConstCastResultIdOk) + { + type_ensure_zero_bits_known(ira->codegen, actual_type); + if (type_is_invalid(actual_type)) { + return ira->codegen->invalid_instruction; + } + if (!type_has_bits(actual_type)) { + return ir_get_ref(ira, source_instr, value, false, false); + } + } + // explicit cast from undefined to anything if (actual_type->id == TypeTableEntryIdUndefined) { diff --git a/test/cases/struct.zig b/test/cases/struct.zig index 6f7d44e09b..6952611a8c 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -421,3 +421,20 @@ const Expr = union(enum) { fn alloc(comptime T: type) []T { return []T{}; } + +test "call method with mutable reference to struct with no fields" { + const S = struct { + fn doC(s: *const this) bool { + return true; + } + fn do(s: *this) bool { + return true; + } + }; + + var s = S{}; + assert(S.doC(&s)); + assert(s.doC()); + assert(S.do(&s)); + assert(s.do()); +} |
