Skip to content

Commit b980568

Browse files
committed
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.
1 parent ef419dd commit b980568

File tree

2 files changed

+76
-17
lines changed

2 files changed

+76
-17
lines changed

src/ir.cpp

+61-17
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
231231
static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
232232
static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
233233
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
234+
static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const);
234235
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
235236
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);
236237
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
1184411845

1184511846
bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull);
1184611847
bool convert_to_const_slice = false;
11848+
bool make_the_slice_const = false;
1184711849
for (; i < instruction_count; i += 1) {
1184811850
IrInstGen *cur_inst = instructions[i];
1184911851
ZigType *cur_type = cur_inst->value->type;
@@ -12357,12 +12359,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1235712359
ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
1235812360
prev_type->data.error_union.payload_type : prev_type;
1235912361
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
12360-
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
12361-
!cur_type->data.pointer.is_const) &&
12362-
types_match_const_cast_only(ira,
12363-
slice_ptr_type->data.pointer.child_type,
12362+
if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
1236412363
array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
1236512364
{
12365+
bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
12366+
!cur_type->data.pointer.is_const);
12367+
if (!const_ok) make_the_slice_const = true;
1236612368
convert_to_const_slice = false;
1236712369
continue;
1236812370
}
@@ -12391,12 +12393,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1239112393
break;
1239212394
}
1239312395
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
12394-
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
12395-
!prev_type->data.pointer.is_const) &&
12396-
types_match_const_cast_only(ira,
12397-
slice_ptr_type->data.pointer.child_type,
12396+
if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
1239812397
array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
1239912398
{
12399+
bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
12400+
!prev_type->data.pointer.is_const);
12401+
if (!const_ok) make_the_slice_const = true;
1240012402
prev_inst = cur_inst;
1240112403
convert_to_const_slice = false;
1240212404
continue;
@@ -12408,8 +12410,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1240812410
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
1240912411
prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
1241012412
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
12411-
(cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
12412-
prev_type->data.pointer.child_type->data.array.len == 0) &&
1241312413
(
1241412414
prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
1241512415
(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
1242112421
prev_type->data.pointer.child_type->data.array.child_type,
1242212422
source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
1242312423
{
12424+
bool const_ok = (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
12425+
prev_type->data.pointer.child_type->data.array.len == 0);
12426+
if (!const_ok) make_the_slice_const = true;
1242412427
prev_inst = cur_inst;
1242512428
convert_to_const_slice = true;
1242612429
continue;
@@ -12429,8 +12432,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1242912432
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
1243012433
cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
1243112434
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
12432-
(prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
12433-
cur_type->data.pointer.child_type->data.array.len == 0) &&
1243412435
(
1243512436
cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
1243612437
(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
1244212443
cur_type->data.pointer.child_type->data.array.child_type,
1244312444
source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
1244412445
{
12446+
bool const_ok = (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
12447+
cur_type->data.pointer.child_type->data.array.len == 0);
12448+
if (!const_ok) make_the_slice_const = true;
1244512449
convert_to_const_slice = true;
1244612450
continue;
1244712451
}
@@ -12486,7 +12490,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1248612490
src_assert(array_type->id == ZigTypeIdArray, source_node);
1248712491
ZigType *ptr_type = get_pointer_to_type_extra2(
1248812492
ira->codegen, array_type->data.array.child_type,
12489-
prev_inst->value->type->data.pointer.is_const, false,
12493+
prev_inst->value->type->data.pointer.is_const || make_the_slice_const, false,
1249012494
PtrLenUnknown,
1249112495
0, 0, 0, false,
1249212496
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
1253712541
return ira->codegen->builtin_types.entry_invalid;
1253812542
return get_optional_type(ira->codegen, prev_inst->value->type);
1253912543
}
12544+
} else if (make_the_slice_const) {
12545+
ZigType *slice_type;
12546+
if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
12547+
slice_type = prev_inst->value->type->data.error_union.payload_type;
12548+
} else if (is_slice(prev_inst->value->type)) {
12549+
slice_type = prev_inst->value->type;
12550+
} else {
12551+
zig_unreachable();
12552+
}
12553+
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
12554+
ZigType *adjusted_ptr_type = adjust_ptr_const(ira->codegen, slice_ptr_type, make_the_slice_const);
12555+
ZigType *adjusted_slice_type = get_slice_type(ira->codegen, adjusted_ptr_type);
12556+
if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
12557+
return get_error_union_type(ira->codegen, prev_inst->value->type->data.error_union.err_set_type,
12558+
adjusted_slice_type);
12559+
} else if (is_slice(prev_inst->value->type)) {
12560+
return adjusted_slice_type;
12561+
} else {
12562+
zig_unreachable();
12563+
}
1254012564
} else {
1254112565
return prev_inst->value->type;
1254212566
}
@@ -20708,24 +20732,44 @@ static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new
2070820732

2070920733
static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
2071020734
assert(ptr_type->id == ZigTypeIdPointer);
20711-
return get_pointer_to_type_extra(g,
20735+
return get_pointer_to_type_extra2(g,
2071220736
ptr_type->data.pointer.child_type,
2071320737
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
2071420738
ptr_len,
2071520739
ptr_type->data.pointer.explicit_alignment,
2071620740
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
20717-
ptr_type->data.pointer.allow_zero);
20741+
ptr_type->data.pointer.allow_zero,
20742+
ptr_type->data.pointer.vector_index,
20743+
ptr_type->data.pointer.inferred_struct_field,
20744+
ptr_type->data.pointer.sentinel);
2071820745
}
2071920746

2072020747
static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_zero) {
2072120748
assert(ptr_type->id == ZigTypeIdPointer);
20722-
return get_pointer_to_type_extra(g,
20749+
return get_pointer_to_type_extra2(g,
2072320750
ptr_type->data.pointer.child_type,
2072420751
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
2072520752
ptr_type->data.pointer.ptr_len,
2072620753
ptr_type->data.pointer.explicit_alignment,
2072720754
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
20728-
allow_zero);
20755+
allow_zero,
20756+
ptr_type->data.pointer.vector_index,
20757+
ptr_type->data.pointer.inferred_struct_field,
20758+
ptr_type->data.pointer.sentinel);
20759+
}
20760+
20761+
static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const) {
20762+
assert(ptr_type->id == ZigTypeIdPointer);
20763+
return get_pointer_to_type_extra2(g,
20764+
ptr_type->data.pointer.child_type,
20765+
is_const, ptr_type->data.pointer.is_volatile,
20766+
ptr_type->data.pointer.ptr_len,
20767+
ptr_type->data.pointer.explicit_alignment,
20768+
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
20769+
ptr_type->data.pointer.allow_zero,
20770+
ptr_type->data.pointer.vector_index,
20771+
ptr_type->data.pointer.inferred_struct_field,
20772+
ptr_type->data.pointer.sentinel);
2072920773
}
2073020774

2073120775
static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,

test/stage1/behavior/cast.zig

+15
Original file line numberDiff line numberDiff line change
@@ -790,3 +790,18 @@ test "assignment to optional pointer result loc" {
790790
var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
791791
expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
792792
}
793+
794+
test "peer type resolve string lit with sentinel-terminated mutable slice" {
795+
var array: [4:0]u8 = undefined;
796+
array[4] = 0; // TODO remove this when #4372 is solved
797+
var slice: [:0]u8 = array[0..4 :0];
798+
comptime expect(@TypeOf(slice, "hi") == [:0]const u8);
799+
comptime expect(@TypeOf("hi", slice) == [:0]const u8);
800+
}
801+
802+
test "peer type resolve array pointers, one of them const" {
803+
var array1: [4]u8 = undefined;
804+
const array2: [5]u8 = undefined;
805+
comptime expect(@TypeOf(&array1, &array2) == []const u8);
806+
comptime expect(@TypeOf(&array2, &array1) == []const u8);
807+
}

0 commit comments

Comments
 (0)