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);...@@ -231,6 +231,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
231static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);231static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
232static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);232static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
233static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);233static 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);
234static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);235static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
235static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);236static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);
236static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val);237static 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...@@ -11844,6 +11845,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1184411845
11845 bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull);11846 bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull);
11846 bool convert_to_const_slice = false;11847 bool convert_to_const_slice = false;
11848 bool make_the_slice_const = false;
11847 for (; i < instruction_count; i += 1) {11849 for (; i < instruction_count; i += 1) {
11848 IrInstGen *cur_inst = instructions[i];11850 IrInstGen *cur_inst = instructions[i];
11849 ZigType *cur_type = cur_inst->value->type;11851 ZigType *cur_type = cur_inst->value->type;
...@@ -12357,12 +12359,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -12357,12 +12359,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12357 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?12359 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
12358 prev_type->data.error_union.payload_type : prev_type;12360 prev_type->data.error_union.payload_type : prev_type;
12359 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;12361 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 ||12362 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
12361 !cur_type->data.pointer.is_const) &&
12362 types_match_const_cast_only(ira,
12363 slice_ptr_type->data.pointer.child_type,
12364 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)12363 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
12365 {12364 {
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;
12366 convert_to_const_slice = false;12368 convert_to_const_slice = false;
12367 continue;12369 continue;
12368 }12370 }
...@@ -12391,12 +12393,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -12391,12 +12393,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12391 break;12393 break;
12392 }12394 }
12393 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;12395 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 ||12396 if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
12395 !prev_type->data.pointer.is_const) &&
12396 types_match_const_cast_only(ira,
12397 slice_ptr_type->data.pointer.child_type,
12398 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)12397 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
12399 {12398 {
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;
12400 prev_inst = cur_inst;12402 prev_inst = cur_inst;
12401 convert_to_const_slice = false;12403 convert_to_const_slice = false;
12402 continue;12404 continue;
...@@ -12408,8 +12410,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -12408,8 +12410,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12408 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&12410 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
12409 prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&12411 prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
12410 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&12412 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) &&
12413 (12413 (
12414 prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||12414 prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
12415 (cur_type->data.pointer.child_type->data.array.sentinel != nullptr &&12415 (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...@@ -12421,6 +12421,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12421 prev_type->data.pointer.child_type->data.array.child_type,12421 prev_type->data.pointer.child_type->data.array.child_type,
12422 source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)12422 source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
12423 {12423 {
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;
12424 prev_inst = cur_inst;12427 prev_inst = cur_inst;
12425 convert_to_const_slice = true;12428 convert_to_const_slice = true;
12426 continue;12429 continue;
...@@ -12429,8 +12432,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -12429,8 +12432,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12429 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&12432 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
12430 cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&12433 cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
12431 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&12434 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) &&
12434 (12435 (
12435 cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||12436 cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
12436 (prev_type->data.pointer.child_type->data.array.sentinel != nullptr &&12437 (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...@@ -12442,6 +12443,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12442 cur_type->data.pointer.child_type->data.array.child_type,12443 cur_type->data.pointer.child_type->data.array.child_type,
12443 source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)12444 source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
12444 {12445 {
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;
12445 convert_to_const_slice = true;12449 convert_to_const_slice = true;
12446 continue;12450 continue;
12447 }12451 }
...@@ -12486,7 +12490,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -12486,7 +12490,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12486 src_assert(array_type->id == ZigTypeIdArray, source_node);12490 src_assert(array_type->id == ZigTypeIdArray, source_node);
12487 ZigType *ptr_type = get_pointer_to_type_extra2(12491 ZigType *ptr_type = get_pointer_to_type_extra2(
12488 ira->codegen, array_type->data.array.child_type,12492 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,
12490 PtrLenUnknown,12494 PtrLenUnknown,
12491 0, 0, 0, false,12495 0, 0, 0, false,
12492 VECTOR_INDEX_NONE, nullptr, array_type->data.array.sentinel);12496 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...@@ -12537,6 +12541,26 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
12537 return ira->codegen->builtin_types.entry_invalid;12541 return ira->codegen->builtin_types.entry_invalid;
12538 return get_optional_type(ira->codegen, prev_inst->value->type);12542 return get_optional_type(ira->codegen, prev_inst->value->type);
12539 }12543 }
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 }
12540 } else {12564 } else {
12541 return prev_inst->value->type;12565 return prev_inst->value->type;
12542 }12566 }
...@@ -20708,24 +20732,44 @@ static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new...@@ -20708,24 +20732,44 @@ static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new
2070820732
20709static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {20733static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
20710 assert(ptr_type->id == ZigTypeIdPointer);20734 assert(ptr_type->id == ZigTypeIdPointer);
20711 return get_pointer_to_type_extra(g,20735 return get_pointer_to_type_extra2(g,
20712 ptr_type->data.pointer.child_type,20736 ptr_type->data.pointer.child_type,
20713 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,20737 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
20714 ptr_len,20738 ptr_len,
20715 ptr_type->data.pointer.explicit_alignment,20739 ptr_type->data.pointer.explicit_alignment,
20716 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,20740 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);
20718}20745}
2071920746
20720static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_zero) {20747static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_zero) {
20721 assert(ptr_type->id == ZigTypeIdPointer);20748 assert(ptr_type->id == ZigTypeIdPointer);
20722 return get_pointer_to_type_extra(g,20749 return get_pointer_to_type_extra2(g,
20723 ptr_type->data.pointer.child_type,20750 ptr_type->data.pointer.child_type,
20724 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,20751 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
20725 ptr_type->data.pointer.ptr_len,20752 ptr_type->data.pointer.ptr_len,
20726 ptr_type->data.pointer.explicit_alignment,20753 ptr_type->data.pointer.explicit_alignment,
20727 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,20754 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);
20729}20773}
2073020774
20731static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,20775static 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" {...@@ -790,3 +790,18 @@ test "assignment to optional pointer result loc" {
790 var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };790 var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
791 expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));791 expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
792}792}
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}