authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-30 13:01:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-30 13:02:50-04:00
logb980568c810fda4c014da42be8e5108b4cbadb7c
tree84b8bba60e1bfd206711cccdc95408c556873fa9
parentef419dd72d3fc9ec1454099367bd8d43f1b5037b
signaturelock-open Commit is signed but in an unrecognized format.

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.

2 files changed, 76 insertions(+), 17 deletions(-)

src/ir.cpp+61-17
......@@ -231,6 +231,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
231231static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
232232static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
233233static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
234static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const);
234235static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
235236static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);
236237static 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
2070920733static 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
2072020747static 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
20761static 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
2073120775static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
test/stage1/behavior/cast.zig+15
......@@ -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
794test "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
802test "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}