From 3c4b255a3c184e43e70bb8380f6e388c5594f149 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Jun 2019 13:37:13 -0400 Subject: [PATCH] fix implicit cast fn call result to optional in field result --- src/ir.cpp | 18 ++++++++++-------- test/stage1/behavior/fn.zig | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 08253e748..e943788f9 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -187,7 +187,7 @@ static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *sourc static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *dest_type); static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool non_null_comptime); + ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, @@ -15012,7 +15012,7 @@ static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) { // when calling this function, at the callsite must check for result type noreturn and propagate it up static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, - ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool non_null_comptime) + ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime) { Error err; if (result_loc->resolved_loc != nullptr) { @@ -15108,7 +15108,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if (peer_parent->peers.length == 1) { IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - value_type, value, false, non_null_comptime); + value_type, value, force_runtime, non_null_comptime); result_peer->suspend_pos.basic_block_index = SIZE_MAX; result_peer->suspend_pos.instruction_index = SIZE_MAX; if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || @@ -15128,7 +15128,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe if (peer_parent->skipped) { if (non_null_comptime) { return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - value_type, value, false, non_null_comptime); + value_type, value, force_runtime, non_null_comptime); } return nullptr; } @@ -15146,7 +15146,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, - peer_parent->resolved_type, nullptr, false, non_null_comptime); + peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || parent_result_loc->value.type->id == ZigTypeIdUnreachable) { @@ -15196,7 +15196,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, - dest_type, bitcasted_value, false, non_null_comptime); + dest_type, bitcasted_value, force_runtime, non_null_comptime); if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || parent_result_loc->value.type->id == ZigTypeIdUnreachable) { @@ -15228,11 +15228,13 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s bool non_null_comptime) { IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, - value, non_null_comptime); + value, force_runtime, non_null_comptime); if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type))) return result_loc; - if (force_runtime && result_loc_pass1->written && result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) { + if ((force_runtime || (value != nullptr && !instr_is_comptime(value))) && + result_loc_pass1->written && result_loc->value.data.x_ptr.mut == ConstPtrMutInfer) + { result_loc->value.special = ConstValSpecialRuntime; } diff --git a/test/stage1/behavior/fn.zig b/test/stage1/behavior/fn.zig index e01169c67..d6d670b09 100644 --- a/test/stage1/behavior/fn.zig +++ b/test/stage1/behavior/fn.zig @@ -205,3 +205,26 @@ test "extern struct with stdcallcc fn pointer" { s.ptr = S.foo; expect(s.ptr() == 1234); } + +test "implicit cast fn call result to optional in field result" { + const S = struct { + fn entry() void { + var x = Foo{ + .field = optionalPtr(), + }; + expect(x.field.?.* == 999); + } + + const glob: i32 = 999; + + fn optionalPtr() *const i32 { + return &glob; + } + + const Foo = struct { + field: ?*const i32, + }; + }; + S.entry(); + comptime S.entry(); +}