diff --git a/src/ir.cpp b/src/ir.cpp index 42ad7d868..d203e0aa9 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16966,8 +16966,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, new_type->data.structure.special = StructSpecialInferredTuple; new_type->data.structure.resolve_status = ResolveStatusBeingInferred; - bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope); - IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(), new_type, nullptr, false, true); uint32_t new_field_count = op1_field_count + op2_field_count; @@ -16995,7 +16993,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; ZigList const_ptrs = {}; - IrInstGen *first_non_const_instruction = nullptr; for (uint32_t i = 0; i < new_field_count; i += 1) { TypeStructField *dst_field = new_type->data.structure.fields[i]; IrInstGen *src_struct_op; @@ -17017,8 +17014,6 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; if (instr_is_comptime(field_value)) { const_ptrs.append(dest_ptr); - } else { - first_non_const_instruction = field_value; } IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value, true); @@ -17035,20 +17030,13 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr, continue; } IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr); - elem_result_loc->value->special = ConstValSpecialRuntime; - ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, false); + if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) { + elem_result_loc->value->special = ConstValSpecialRuntime; + } + ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, true); } } IrInstGen *result = ir_get_deref(ira, source_instr, new_struct_ptr, nullptr); - if (instr_is_comptime(result)) - return result; - - if (is_comptime) { - ir_add_error(ira, &first_non_const_instruction->base, - buf_sprintf("unable to evaluate constant expression")); - return ira->codegen->invalid_inst_gen; - } - return result; } @@ -23065,8 +23053,11 @@ static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira, } } + const_ptrs.deinit(); + IrInstGen *result = ir_get_deref(ira, &instruction->base.base, result_loc, nullptr); - if (instr_is_comptime(result)) + // If the result is a tuple, we are allowed to return a struct that uses ConstValSpecialRuntime fields at comptime. + if (instr_is_comptime(result) || is_tuple(container_type)) return result; if (is_comptime) { diff --git a/test/stage1/behavior/tuple.zig b/test/stage1/behavior/tuple.zig index 13d3d0568..686a9ad83 100644 --- a/test/stage1/behavior/tuple.zig +++ b/test/stage1/behavior/tuple.zig @@ -15,4 +15,42 @@ test "tuple concatenation" { }; S.doTheTest(); comptime S.doTheTest(); + + const T = struct { + fn consume_tuple(tuple: var, len: usize) void { + expect(tuple.len == len); + } + + fn doTheTest() void { + const t1 = .{}; + + var rt_var: u8 = 42; + const t2 = .{rt_var} ++ .{}; + + expect(t2.len == 1); + expect(t2.@"0" == rt_var); + expect(t2.@"0" == 42); + expect(&t2.@"0" != &rt_var); + + consume_tuple(t1 ++ t1, 0); + consume_tuple(.{} ++ .{}, 0); + consume_tuple(.{0} ++ .{}, 1); + consume_tuple(.{0} ++ .{1}, 2); + consume_tuple(.{0, 1, 2} ++ .{u8, 1, noreturn}, 6); + consume_tuple(t2 ++ t1, 1); + consume_tuple(t1 ++ t2, 1); + consume_tuple(t2 ++ t2, 2); + consume_tuple(.{rt_var} ++ .{}, 1); + consume_tuple(.{rt_var} ++ t1, 1); + consume_tuple(.{} ++ .{rt_var}, 1); + consume_tuple(t2 ++ .{void}, 2); + consume_tuple(t2 ++ .{0}, 2); + consume_tuple(.{0} ++ t2, 2); + consume_tuple(.{void} ++ t2, 2); + consume_tuple(.{u8} ++ .{rt_var} ++ .{true}, 3); + } + }; + + T.doTheTest(); + comptime T.doTheTest(); }