Commit 3c4b255a3c

Andrew Kelley <andrew@ziglang.org>
2019-06-22 19:37:13
fix implicit cast fn call result to optional in field result
1 parent 65997f8
Changed files (2)
src
test
stage1
behavior
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;
     }
 
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();
+}