authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 16:09:28-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-01-11 16:09:28-08:00
log025f1559a023d6a1c783d4441eb1cb897797b74a
tree8f1212b6ef93fdf0312a2cbb2012ead1145e977c
parent4f5fa90d6d921eac07f95fa19c8fd7cf80615537
parent1780132d7c552dc191921efdef2adf04aa753830
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7200 from Vexu/arr

Type coercion for pointers to anon literals

6 files changed, 332 insertions(+), 19 deletions(-)

src/stage1/ir.cpp+168-19
...@@ -14981,21 +14981,96 @@ static IrInstGen *ir_analyze_enum_literal(IrAnalyze *ira, IrInst* source_instr,...@@ -14981,21 +14981,96 @@ static IrInstGen *ir_analyze_enum_literal(IrAnalyze *ira, IrInst* source_instr,
14981}14981}
1498214982
14983static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* source_instr,14983static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* source_instr,
14984 IrInstGen *value, ZigType *wanted_type)14984 IrInstGen *struct_ptr, ZigType *actual_type, ZigType *wanted_type)
14985{14985{
14986 ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon list literal to array"));14986 Error err;
14987 return ira->codegen->invalid_inst_gen;14987
14988 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusSizeKnown)))
14989 return ira->codegen->invalid_inst_gen;
14990
14991 size_t array_len = wanted_type->data.array.len;
14992 size_t instr_field_count = actual_type->data.structure.src_field_count;
14993 assert(array_len == instr_field_count);
14994
14995 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
14996 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
14997 bool is_comptime = true;
14998
14999 ZigType *elem_type = wanted_type->data.array.child_type;
15000
15001 // Determine if the struct_operand will be comptime.
15002 ZigValue *elem_values = heap::c_allocator.allocate<ZigValue>(array_len);
15003 IrInstGen **casted_fields = heap::c_allocator.allocate<IrInstGen *>(array_len);
15004 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
15005
15006 for (size_t i = 0; i < array_len; i += 1) {
15007 TypeStructField *src_field = actual_type->data.structure.fields[i];
15008
15009 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
15010 actual_type, false);
15011 if (type_is_invalid(field_ptr->value->type))
15012 return ira->codegen->invalid_inst_gen;
15013 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
15014 if (type_is_invalid(field_value->value->type))
15015 return ira->codegen->invalid_inst_gen;
15016 IrInstGen *casted_value = ir_implicit_cast(ira, field_value, elem_type);
15017 if (type_is_invalid(casted_value->value->type))
15018 return ira->codegen->invalid_inst_gen;
15019
15020 casted_fields[i] = casted_value;
15021 if (need_comptime || instr_is_comptime(casted_value)) {
15022 ZigValue *field_val = ir_resolve_const(ira, casted_value, UndefOk);
15023 if (field_val == nullptr)
15024 return ira->codegen->invalid_inst_gen;
15025
15026 field_val->parent.id = ConstParentIdArray;
15027 field_val->parent.data.p_array.array_val = const_result->value;
15028 field_val->parent.data.p_array.elem_index = i;
15029 elem_values[i] = *field_val;
15030 if (field_val->type->id == ZigTypeIdUndefined) {
15031 elem_values[i].special = ConstValSpecialUndef;
15032 }
15033 } else {
15034 is_comptime = false;
15035 }
15036 }
15037
15038 if (is_comptime) {
15039 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
15040 const_result->value->data.x_array.special = ConstArraySpecialNone;
15041 const_result->value->data.x_array.data.s_none.elements = elem_values;
15042 return const_result;
15043 }
15044
15045 IrInstGen *result_loc_inst = ir_resolve_result(ira, source_instr, no_result_loc(),
15046 wanted_type, nullptr, true, true);
15047 if (type_is_invalid(result_loc_inst->value->type) || result_loc_inst->value->type->id == ZigTypeIdUnreachable) {
15048 return ira->codegen->invalid_inst_gen;
15049 }
15050
15051 ZigType *elem_type_ptr = get_pointer_to_type(ira->codegen, elem_type, false);
15052 for (size_t i = 0; i < array_len; i += 1) {
15053 IrInstGen *index_val = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
15054 bigint_init_unsigned(&index_val->value->data.x_bigint, i);
15055
15056 IrInstGen *elem_ptr = ir_build_elem_ptr_gen(ira, source_instr->scope, source_instr->source_node,
15057 result_loc_inst, index_val, false, elem_type_ptr);
15058 IrInstGen *store_ptr_inst = ir_analyze_store_ptr(ira, source_instr, elem_ptr, casted_fields[i], true);
15059 if (type_is_invalid(store_ptr_inst->value->type))
15060 return ira->codegen->invalid_inst_gen;
15061 }
15062
15063 heap::c_allocator.deallocate(elem_values, array_len);
15064 heap::c_allocator.deallocate(casted_fields, array_len);
15065
15066 return result_loc_inst;
14988}15067}
1498915068
14990static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,15069static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* source_instr,
14991 IrInstGen *struct_operand, ZigType *wanted_type)15070 IrInstGen *struct_ptr, ZigType *actual_type, ZigType *wanted_type)
14992{15071{
14993 Error err;15072 Error err;
1499415073
14995 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
14996 if (type_is_invalid(struct_ptr->value->type))
14997 return ira->codegen->invalid_inst_gen;
14998
14999 if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {15074 if (wanted_type->data.structure.resolve_status == ResolveStatusBeingInferred) {
15000 ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));15075 ir_add_error(ira, source_instr, buf_sprintf("type coercion of anon struct literal to inferred struct"));
15001 return ira->codegen->invalid_inst_gen;15076 return ira->codegen->invalid_inst_gen;
...@@ -15005,7 +15080,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15005,7 +15080,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15005 return ira->codegen->invalid_inst_gen;15080 return ira->codegen->invalid_inst_gen;
1500615081
15007 size_t actual_field_count = wanted_type->data.structure.src_field_count;15082 size_t actual_field_count = wanted_type->data.structure.src_field_count;
15008 size_t instr_field_count = struct_operand->value->type->data.structure.src_field_count;15083 size_t instr_field_count = actual_type->data.structure.src_field_count;
1500915084
15010 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)15085 bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope)
15011 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;15086 || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes;
...@@ -15019,7 +15094,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15019,7 +15094,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15019 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);15094 IrInstGen *const_result = ir_const(ira, source_instr, wanted_type);
1502015095
15021 for (size_t i = 0; i < instr_field_count; i += 1) {15096 for (size_t i = 0; i < instr_field_count; i += 1) {
15022 TypeStructField *src_field = struct_operand->value->type->data.structure.fields[i];15097 TypeStructField *src_field = actual_type->data.structure.fields[i];
15023 TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);15098 TypeStructField *dst_field = find_struct_type_field(wanted_type, src_field->name);
15024 if (dst_field == nullptr) {15099 if (dst_field == nullptr) {
15025 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",15100 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("no field named '%s' in struct '%s'",
...@@ -15043,7 +15118,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15043,7 +15118,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15043 field_assign_nodes[dst_field->src_index] = src_field->decl_node;15118 field_assign_nodes[dst_field->src_index] = src_field->decl_node;
1504415119
15045 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,15120 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, src_field, struct_ptr,
15046 struct_operand->value->type, false);15121 actual_type, false);
15047 if (type_is_invalid(field_ptr->value->type))15122 if (type_is_invalid(field_ptr->value->type))
15048 return ira->codegen->invalid_inst_gen;15123 return ira->codegen->invalid_inst_gen;
15049 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);15124 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
...@@ -15123,14 +15198,13 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so...@@ -15123,14 +15198,13 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so
15123 heap::c_allocator.deallocate(field_values, actual_field_count);15198 heap::c_allocator.deallocate(field_values, actual_field_count);
15124 heap::c_allocator.deallocate(casted_fields, actual_field_count);15199 heap::c_allocator.deallocate(casted_fields, actual_field_count);
1512515200
15126 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);15201 return result_loc_inst;
15127}15202}
1512815203
15129static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,15204static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* source_instr,
15130 IrInstGen *value, ZigType *union_type)15205 IrInstGen *struct_ptr, ZigType *struct_type, ZigType *union_type)
15131{15206{
15132 Error err;15207 Error err;
15133 ZigType *struct_type = value->value->type;
1513415208
15135 assert(struct_type->id == ZigTypeIdStruct);15209 assert(struct_type->id == ZigTypeIdStruct);
15136 assert(union_type->id == ZigTypeIdUnion);15210 assert(union_type->id == ZigTypeIdUnion);
...@@ -15153,7 +15227,11 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou...@@ -15153,7 +15227,11 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
15153 if (payload_type == nullptr)15227 if (payload_type == nullptr)
15154 return ira->codegen->invalid_inst_gen;15228 return ira->codegen->invalid_inst_gen;
1515515229
15156 IrInstGen *field_value = ir_analyze_struct_value_field_value(ira, source_instr, value, only_field);15230 IrInstGen *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, only_field, struct_ptr,
15231 struct_type, false);
15232 if (type_is_invalid(field_ptr->value->type))
15233 return ira->codegen->invalid_inst_gen;
15234 IrInstGen *field_value = ir_get_deref(ira, source_instr, field_ptr, nullptr);
15157 if (type_is_invalid(field_value->value->type))15235 if (type_is_invalid(field_value->value->type))
15158 return ira->codegen->invalid_inst_gen;15236 return ira->codegen->invalid_inst_gen;
1515915237
...@@ -15191,7 +15269,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou...@@ -15191,7 +15269,7 @@ static IrInstGen *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInst* sou
15191 if (type_is_invalid(store_ptr_inst->value->type))15269 if (type_is_invalid(store_ptr_inst->value->type))
15192 return ira->codegen->invalid_inst_gen;15270 return ira->codegen->invalid_inst_gen;
1519315271
15194 return ir_get_deref(ira, source_instr, result_loc_inst, nullptr);15272 return result_loc_inst;
15195}15273}
1519615274
15197// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,15275// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,
...@@ -15824,13 +15902,84 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,...@@ -15824,13 +15902,84 @@ static IrInstGen *ir_analyze_cast(IrAnalyze *ira, IrInst *source_instr,
15824 if (wanted_type->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&15902 if (wanted_type->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
15825 wanted_type->data.array.len == field_count)15903 wanted_type->data.array.len == field_count)
15826 {15904 {
15827 return ir_analyze_struct_literal_to_array(ira, source_instr, value, wanted_type);15905 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, value, true, false);
15906 if (type_is_invalid(struct_ptr->value->type))
15907 return ira->codegen->invalid_inst_gen;
15908
15909 IrInstGen *ptr = ir_analyze_struct_literal_to_array(ira, source_instr, struct_ptr, actual_type, wanted_type);
15910 if (ptr->value->type->id != ZigTypeIdPointer)
15911 return ptr;
15912 return ir_get_deref(ira, source_instr, ptr, nullptr);
15828 } else if (wanted_type->id == ZigTypeIdStruct && !is_slice(wanted_type) &&15913 } else if (wanted_type->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
15829 (!is_array_init || field_count == 0))15914 (!is_array_init || field_count == 0))
15830 {15915 {
15831 return ir_analyze_struct_literal_to_struct(ira, source_instr, value, wanted_type);15916 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, value, true, false);
15917 if (type_is_invalid(struct_ptr->value->type))
15918 return ira->codegen->invalid_inst_gen;
15919
15920 IrInstGen *ptr = ir_analyze_struct_literal_to_struct(ira, source_instr, struct_ptr, actual_type, wanted_type);
15921 if (ptr->value->type->id != ZigTypeIdPointer)
15922 return ptr;
15923 return ir_get_deref(ira, source_instr, ptr, nullptr);
15832 } else if (wanted_type->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {15924 } else if (wanted_type->id == ZigTypeIdUnion && !is_array_init && field_count == 1) {
15833 return ir_analyze_struct_literal_to_union(ira, source_instr, value, wanted_type);15925 IrInstGen *struct_ptr = ir_get_ref(ira, source_instr, value, true, false);
15926 if (type_is_invalid(struct_ptr->value->type))
15927 return ira->codegen->invalid_inst_gen;
15928
15929 IrInstGen *ptr = ir_analyze_struct_literal_to_union(ira, source_instr, struct_ptr, actual_type, wanted_type);
15930 if (ptr->value->type->id != ZigTypeIdPointer)
15931 return ptr;
15932 return ir_get_deref(ira, source_instr, ptr, nullptr);
15933 }
15934 }
15935
15936 // cast from pointer to inferred struct type to pointer to array, union, or struct
15937 if (actual_type->id == ZigTypeIdPointer && is_anon_container(actual_type->data.pointer.child_type)) {
15938 ZigType *anon_type = actual_type->data.pointer.child_type;
15939 const bool is_array_init =
15940 anon_type->data.structure.special == StructSpecialInferredTuple;
15941 const uint32_t field_count = anon_type->data.structure.src_field_count;
15942
15943 if (wanted_type->id == ZigTypeIdPointer &&
15944 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
15945 {
15946 ZigType *wanted_child = wanted_type->data.pointer.child_type;
15947 bool const_ok = (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const);
15948 if (wanted_child->id == ZigTypeIdArray && (is_array_init || field_count == 0) &&
15949 wanted_child->data.array.len == field_count && (const_ok || field_count == 0))
15950 {
15951 IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, wanted_child);
15952 if (res->value->type->id == ZigTypeIdPointer)
15953 return res;
15954 return ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
15955 } else if (wanted_child->id == ZigTypeIdStruct && !is_slice(wanted_type) &&
15956 (!is_array_init || field_count == 0) && const_ok)
15957 {
15958 IrInstGen *res = ir_analyze_struct_literal_to_struct(ira, source_instr, value, anon_type, wanted_child);
15959 if (res->value->type->id == ZigTypeIdPointer)
15960 return res;
15961 return ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
15962 } else if (wanted_child->id == ZigTypeIdUnion && !is_array_init && field_count == 1 && const_ok) {
15963 IrInstGen *res = ir_analyze_struct_literal_to_union(ira, source_instr, value, anon_type, wanted_child);
15964 if (res->value->type->id == ZigTypeIdPointer)
15965 return res;
15966 return ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
15967 }
15968 } else if (is_slice(wanted_type) && (is_array_init || field_count == 0)) {
15969 ZigType *slice_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry;
15970 if ((!actual_type->data.pointer.is_const || slice_type->data.pointer.is_const || field_count == 0) &&
15971 (!actual_type->data.pointer.is_volatile || slice_type->data.pointer.is_volatile))
15972 {
15973 ZigType *slice_child_type = slice_type->data.pointer.child_type;
15974 ZigType *slice_array_type = get_array_type(ira->codegen, slice_child_type, field_count, nullptr);
15975 IrInstGen *res = ir_analyze_struct_literal_to_array(ira, source_instr, value, anon_type, slice_array_type);
15976 if (type_is_invalid(res->value->type))
15977 return ira->codegen->invalid_inst_gen;
15978 if (res->value->type->id != ZigTypeIdPointer)
15979 res = ir_get_ref(ira, source_instr, res, actual_type->data.pointer.is_const, actual_type->data.pointer.is_volatile);
15980
15981 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, res, wanted_type, nullptr);
15982 }
15834 }15983 }
15835 }15984 }
1583615985
test/compile_errors.zig+17
...@@ -22,6 +22,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -22,6 +22,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
22 "tmp.zig:4:17: error: integer value 1 cannot be coerced to type '*[10]u8'",22 "tmp.zig:4:17: error: integer value 1 cannot be coerced to type '*[10]u8'",
23 });23 });
2424
25 cases.add("pointer attributes checked when coercing pointer to anon literal",
26 \\comptime {
27 \\ const c: [][]const u8 = &.{"hello", "world" };
28 \\}
29 \\comptime {
30 \\ const c: *[2][]const u8 = &.{"hello", "world" };
31 \\}
32 \\const S = struct {a: u8 = 1, b: u32 = 2};
33 \\comptime {
34 \\ const c: *S = &.{};
35 \\}
36 , &[_][]const u8{
37 "mp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'",
38 "mp.zig:5:33: error: expected type '*[2][]const u8', found '*const struct:5:33'",
39 "mp.zig:9:21: error: expected type '*S', found '*const struct:9:21'",
40 });
41
25 cases.add("@Type() union payload is undefined",42 cases.add("@Type() union payload is undefined",
26 \\const Foo = @Type(@import("std").builtin.TypeInfo{43 \\const Foo = @Type(@import("std").builtin.TypeInfo{
27 \\ .Struct = undefined,44 \\ .Struct = undefined,
test/stage1/behavior/array.zig+56
...@@ -431,3 +431,59 @@ test "zero-sized array with recursive type definition" {...@@ -431,3 +431,59 @@ test "zero-sized array with recursive type definition" {
431 var t: S = .{ .list = .{ .s = undefined } };431 var t: S = .{ .list = .{ .s = undefined } };
432 expectEqual(@as(usize, 0), t.list.x);432 expectEqual(@as(usize, 0), t.list.x);
433}433}
434
435test "type coercion of anon struct literal to array" {
436 const S = struct {
437 const U = union{
438 a: u32,
439 b: bool,
440 c: []const u8,
441 };
442
443 fn doTheTest() void {
444 var x1: u8 = 42;
445 const t1 = .{ x1, 56, 54 };
446 var arr1: [3]u8 = t1;
447 expect(arr1[0] == 42);
448 expect(arr1[1] == 56);
449 expect(arr1[2] == 54);
450
451 var x2: U = .{ .a = 42 };
452 const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };
453 var arr2: [3]U = t2;
454 expect(arr2[0].a == 42);
455 expect(arr2[1].b == true);
456 expect(mem.eql(u8, arr2[2].c, "hello"));
457 }
458 };
459 S.doTheTest();
460 comptime S.doTheTest();
461}
462
463test "type coercion of pointer to anon struct literal to pointer to array" {
464 const S = struct {
465 const U = union{
466 a: u32,
467 b: bool,
468 c: []const u8,
469 };
470
471 fn doTheTest() void {
472 var x1: u8 = 42;
473 const t1 = &.{ x1, 56, 54 };
474 var arr1: *const[3]u8 = t1;
475 expect(arr1[0] == 42);
476 expect(arr1[1] == 56);
477 expect(arr1[2] == 54);
478
479 var x2: U = .{ .a = 42 };
480 const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } };
481 var arr2: *const [3]U = t2;
482 expect(arr2[0].a == 42);
483 expect(arr2[1].b == true);
484 expect(mem.eql(u8, arr2[2].c, "hello"));
485 }
486 };
487 S.doTheTest();
488 comptime S.doTheTest();
489}
test/stage1/behavior/slice.zig+31
...@@ -304,3 +304,34 @@ test "slice of hardcoded address to pointer" {...@@ -304,3 +304,34 @@ test "slice of hardcoded address to pointer" {
304304
305 S.doTheTest();305 S.doTheTest();
306}306}
307
308test "type coercion of pointer to anon struct literal to pointer to slice" {
309 const S = struct {
310 const U = union{
311 a: u32,
312 b: bool,
313 c: []const u8,
314 };
315
316 fn doTheTest() void {
317 var x1: u8 = 42;
318 const t1 = &.{ x1, 56, 54 };
319 var slice1: []const u8 = t1;
320 expect(slice1.len == 3);
321 expect(slice1[0] == 42);
322 expect(slice1[1] == 56);
323 expect(slice1[2] == 54);
324
325 var x2: []const u8 = "hello";
326 const t2 = &.{ x2, ", ", "world!" };
327 // @compileLog(@TypeOf(t2));
328 var slice2: []const []const u8 = t2;
329 expect(slice2.len == 3);
330 expect(mem.eql(u8, slice2[0], "hello"));
331 expect(mem.eql(u8, slice2[1], ", "));
332 expect(mem.eql(u8, slice2[2], "world!"));
333 }
334 };
335 // S.doTheTest();
336 comptime S.doTheTest();
337}
test/stage1/behavior/struct.zig+33
...@@ -885,6 +885,39 @@ test "type coercion of anon struct literal to struct" {...@@ -885,6 +885,39 @@ test "type coercion of anon struct literal to struct" {
885 comptime S.doTheTest();885 comptime S.doTheTest();
886}886}
887887
888test "type coercion of pointer to anon struct literal to pointer to struct" {
889 const S = struct {
890 const S2 = struct {
891 A: u32,
892 B: []const u8,
893 C: void,
894 D: Foo = .{},
895 };
896
897 const Foo = struct {
898 field: i32 = 1234,
899 };
900
901 fn doTheTest() void {
902 var y: u32 = 42;
903 const t0 = &.{ .A = 123, .B = "foo", .C = {} };
904 const t1 = &.{ .A = y, .B = "foo", .C = {} };
905 const y0: *const S2 = t0;
906 var y1: *const S2 = t1;
907 expect(y0.A == 123);
908 expect(std.mem.eql(u8, y0.B, "foo"));
909 expect(y0.C == {});
910 expect(y0.D.field == 1234);
911 expect(y1.A == y);
912 expect(std.mem.eql(u8, y1.B, "foo"));
913 expect(y1.C == {});
914 expect(y1.D.field == 1234);
915 }
916 };
917 S.doTheTest();
918 comptime S.doTheTest();
919}
920
888test "packed struct with undefined initializers" {921test "packed struct with undefined initializers" {
889 const S = struct {922 const S = struct {
890 const P = packed struct {923 const P = packed struct {
test/stage1/behavior/union.zig+27
...@@ -667,6 +667,33 @@ test "cast from anonymous struct to union" {...@@ -667,6 +667,33 @@ test "cast from anonymous struct to union" {
667 comptime S.doTheTest();667 comptime S.doTheTest();
668}668}
669669
670test "cast from pointer to anonymous struct to pointer to union" {
671 const S = struct {
672 const U = union(enum) {
673 A: u32,
674 B: []const u8,
675 C: void,
676 };
677 fn doTheTest() void {
678 var y: u32 = 42;
679 const t0 = &.{ .A = 123 };
680 const t1 = &.{ .B = "foo" };
681 const t2 = &.{ .C = {} };
682 const t3 = &.{ .A = y };
683 const x0: *const U = t0;
684 var x1: *const U = t1;
685 const x2: *const U = t2;
686 var x3: *const U = t3;
687 expect(x0.A == 123);
688 expect(std.mem.eql(u8, x1.B, "foo"));
689 expect(x2.* == .C);
690 expect(x3.A == y);
691 }
692 };
693 S.doTheTest();
694 comptime S.doTheTest();
695}
696
670test "method call on an empty union" {697test "method call on an empty union" {
671 const S = struct {698 const S = struct {
672 const MyUnion = union(Tag) {699 const MyUnion = union(Tag) {