mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
add peer type resolution for mixed-const []T and *[N]T
closes #4766 This commit also fixes the implementation of some utility functions for adjusting properties of pointer types. Previously these functions would incorrectly drop vector, sentinel, and inference metadata.
This commit is contained in:
parent
ef419dd72d
commit
b980568c81
78
src/ir.cpp
78
src/ir.cpp
@ -231,6 +231,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
|
||||
static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
|
||||
static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
|
||||
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
|
||||
static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const);
|
||||
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
|
||||
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);
|
||||
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val);
|
||||
@ -11844,6 +11845,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
|
||||
bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull);
|
||||
bool convert_to_const_slice = false;
|
||||
bool make_the_slice_const = false;
|
||||
for (; i < instruction_count; i += 1) {
|
||||
IrInstGen *cur_inst = instructions[i];
|
||||
ZigType *cur_type = cur_inst->value->type;
|
||||
@ -12357,12 +12359,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
|
||||
prev_type->data.error_union.payload_type : prev_type;
|
||||
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
|
||||
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
|
||||
!cur_type->data.pointer.is_const) &&
|
||||
types_match_const_cast_only(ira,
|
||||
slice_ptr_type->data.pointer.child_type,
|
||||
if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
|
||||
array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
|
||||
{
|
||||
bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
|
||||
!cur_type->data.pointer.is_const);
|
||||
if (!const_ok) make_the_slice_const = true;
|
||||
convert_to_const_slice = false;
|
||||
continue;
|
||||
}
|
||||
@ -12391,12 +12393,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
break;
|
||||
}
|
||||
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
|
||||
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
|
||||
!prev_type->data.pointer.is_const) &&
|
||||
types_match_const_cast_only(ira,
|
||||
slice_ptr_type->data.pointer.child_type,
|
||||
if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
|
||||
array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
|
||||
{
|
||||
bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
|
||||
!prev_type->data.pointer.is_const);
|
||||
if (!const_ok) make_the_slice_const = true;
|
||||
prev_inst = cur_inst;
|
||||
convert_to_const_slice = false;
|
||||
continue;
|
||||
@ -12408,8 +12410,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
|
||||
prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
|
||||
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
|
||||
(cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
|
||||
prev_type->data.pointer.child_type->data.array.len == 0) &&
|
||||
(
|
||||
prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
|
||||
(cur_type->data.pointer.child_type->data.array.sentinel != nullptr &&
|
||||
@ -12421,6 +12421,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
prev_type->data.pointer.child_type->data.array.child_type,
|
||||
source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
|
||||
{
|
||||
bool const_ok = (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
|
||||
prev_type->data.pointer.child_type->data.array.len == 0);
|
||||
if (!const_ok) make_the_slice_const = true;
|
||||
prev_inst = cur_inst;
|
||||
convert_to_const_slice = true;
|
||||
continue;
|
||||
@ -12429,8 +12432,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
|
||||
cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
|
||||
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
|
||||
(prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
|
||||
cur_type->data.pointer.child_type->data.array.len == 0) &&
|
||||
(
|
||||
cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
|
||||
(prev_type->data.pointer.child_type->data.array.sentinel != nullptr &&
|
||||
@ -12442,6 +12443,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
cur_type->data.pointer.child_type->data.array.child_type,
|
||||
source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
|
||||
{
|
||||
bool const_ok = (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
|
||||
cur_type->data.pointer.child_type->data.array.len == 0);
|
||||
if (!const_ok) make_the_slice_const = true;
|
||||
convert_to_const_slice = true;
|
||||
continue;
|
||||
}
|
||||
@ -12486,7 +12490,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
src_assert(array_type->id == ZigTypeIdArray, source_node);
|
||||
ZigType *ptr_type = get_pointer_to_type_extra2(
|
||||
ira->codegen, array_type->data.array.child_type,
|
||||
prev_inst->value->type->data.pointer.is_const, false,
|
||||
prev_inst->value->type->data.pointer.is_const || make_the_slice_const, false,
|
||||
PtrLenUnknown,
|
||||
0, 0, 0, false,
|
||||
VECTOR_INDEX_NONE, nullptr, array_type->data.array.sentinel);
|
||||
@ -12537,6 +12541,26 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
return get_optional_type(ira->codegen, prev_inst->value->type);
|
||||
}
|
||||
} else if (make_the_slice_const) {
|
||||
ZigType *slice_type;
|
||||
if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
|
||||
slice_type = prev_inst->value->type->data.error_union.payload_type;
|
||||
} else if (is_slice(prev_inst->value->type)) {
|
||||
slice_type = prev_inst->value->type;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
|
||||
ZigType *adjusted_ptr_type = adjust_ptr_const(ira->codegen, slice_ptr_type, make_the_slice_const);
|
||||
ZigType *adjusted_slice_type = get_slice_type(ira->codegen, adjusted_ptr_type);
|
||||
if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
|
||||
return get_error_union_type(ira->codegen, prev_inst->value->type->data.error_union.err_set_type,
|
||||
adjusted_slice_type);
|
||||
} else if (is_slice(prev_inst->value->type)) {
|
||||
return adjusted_slice_type;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else {
|
||||
return prev_inst->value->type;
|
||||
}
|
||||
@ -20708,24 +20732,44 @@ static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new
|
||||
|
||||
static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
return get_pointer_to_type_extra(g,
|
||||
return get_pointer_to_type_extra2(g,
|
||||
ptr_type->data.pointer.child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
ptr_len,
|
||||
ptr_type->data.pointer.explicit_alignment,
|
||||
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
|
||||
ptr_type->data.pointer.allow_zero);
|
||||
ptr_type->data.pointer.allow_zero,
|
||||
ptr_type->data.pointer.vector_index,
|
||||
ptr_type->data.pointer.inferred_struct_field,
|
||||
ptr_type->data.pointer.sentinel);
|
||||
}
|
||||
|
||||
static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_zero) {
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
return get_pointer_to_type_extra(g,
|
||||
return get_pointer_to_type_extra2(g,
|
||||
ptr_type->data.pointer.child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
|
||||
ptr_type->data.pointer.ptr_len,
|
||||
ptr_type->data.pointer.explicit_alignment,
|
||||
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
|
||||
allow_zero);
|
||||
allow_zero,
|
||||
ptr_type->data.pointer.vector_index,
|
||||
ptr_type->data.pointer.inferred_struct_field,
|
||||
ptr_type->data.pointer.sentinel);
|
||||
}
|
||||
|
||||
static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const) {
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
return get_pointer_to_type_extra2(g,
|
||||
ptr_type->data.pointer.child_type,
|
||||
is_const, ptr_type->data.pointer.is_volatile,
|
||||
ptr_type->data.pointer.ptr_len,
|
||||
ptr_type->data.pointer.explicit_alignment,
|
||||
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
|
||||
ptr_type->data.pointer.allow_zero,
|
||||
ptr_type->data.pointer.vector_index,
|
||||
ptr_type->data.pointer.inferred_struct_field,
|
||||
ptr_type->data.pointer.sentinel);
|
||||
}
|
||||
|
||||
static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
|
||||
|
||||
@ -790,3 +790,18 @@ test "assignment to optional pointer result loc" {
|
||||
var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
|
||||
expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
|
||||
}
|
||||
|
||||
test "peer type resolve string lit with sentinel-terminated mutable slice" {
|
||||
var array: [4:0]u8 = undefined;
|
||||
array[4] = 0; // TODO remove this when #4372 is solved
|
||||
var slice: [:0]u8 = array[0..4 :0];
|
||||
comptime expect(@TypeOf(slice, "hi") == [:0]const u8);
|
||||
comptime expect(@TypeOf("hi", slice) == [:0]const u8);
|
||||
}
|
||||
|
||||
test "peer type resolve array pointers, one of them const" {
|
||||
var array1: [4]u8 = undefined;
|
||||
const array2: [5]u8 = undefined;
|
||||
comptime expect(@TypeOf(&array1, &array2) == []const u8);
|
||||
comptime expect(@TypeOf(&array2, &array1) == []const u8);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user