Merge pull request #4573 from alexnask/tuple_concat
Allow concatenation of tuples that contain a mix of runtime and comptime valuesmaster
commit
24fc69acad
23
src/ir.cpp
23
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.special = StructSpecialInferredTuple;
|
||||||
new_type->data.structure.resolve_status = ResolveStatusBeingInferred;
|
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(),
|
IrInstGen *new_struct_ptr = ir_resolve_result(ira, source_instr, no_result_loc(),
|
||||||
new_type, nullptr, false, true);
|
new_type, nullptr, false, true);
|
||||||
uint32_t new_field_count = op1_field_count + op2_field_count;
|
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;
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
|
||||||
ZigList<IrInstGen *> const_ptrs = {};
|
ZigList<IrInstGen *> const_ptrs = {};
|
||||||
IrInstGen *first_non_const_instruction = nullptr;
|
|
||||||
for (uint32_t i = 0; i < new_field_count; i += 1) {
|
for (uint32_t i = 0; i < new_field_count; i += 1) {
|
||||||
TypeStructField *dst_field = new_type->data.structure.fields[i];
|
TypeStructField *dst_field = new_type->data.structure.fields[i];
|
||||||
IrInstGen *src_struct_op;
|
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;
|
return ira->codegen->invalid_inst_gen;
|
||||||
if (instr_is_comptime(field_value)) {
|
if (instr_is_comptime(field_value)) {
|
||||||
const_ptrs.append(dest_ptr);
|
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,
|
IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, dest_ptr, field_value,
|
||||||
true);
|
true);
|
||||||
|
@ -17035,20 +17030,13 @@ static IrInstGen *ir_analyze_tuple_cat(IrAnalyze *ira, IrInst* source_instr,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr);
|
IrInstGen *deref = ir_get_deref(ira, &elem_result_loc->base, elem_result_loc, nullptr);
|
||||||
|
if (!type_requires_comptime(ira->codegen, elem_result_loc->value->type->data.pointer.child_type)) {
|
||||||
elem_result_loc->value->special = ConstValSpecialRuntime;
|
elem_result_loc->value->special = ConstValSpecialRuntime;
|
||||||
ir_analyze_store_ptr(ira, &elem_result_loc->base, elem_result_loc, deref, false);
|
}
|
||||||
|
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);
|
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;
|
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);
|
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;
|
return result;
|
||||||
|
|
||||||
if (is_comptime) {
|
if (is_comptime) {
|
||||||
|
|
|
@ -15,4 +15,42 @@ test "tuple concatenation" {
|
||||||
};
|
};
|
||||||
S.doTheTest();
|
S.doTheTest();
|
||||||
comptime 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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue