authorgravatar for mitchell.hashimoto@gmail.comMitchell Hashimoto <mitchell.hashimoto@gmail.com> 2022-03-06 17:31:43-08:00
committergravatar for mitchell.hashimoto@gmail.comMitchell Hashimoto <mitchell.hashimoto@gmail.com> 2022-03-07 07:30:30-08:00
logc9fac41368c872d424681ea3cf93a9d97157143e
tree887f6058136580aad6110a329d82038ba71ad663
parentc7e4c711fc5795e66f974316611922a0b962eb99
signaturelock-open Commit is signed but in an unrecognized format.

stage2: resolve array type for typed array init expressions

Array types with sentinels were not being typed correctly in the translation from ZIR to Sema (comptime). This modifies the `array_init` ZIR to also retain the type of the init expression (note: untyped array initialization is done via the `array_init_anon` ZIR and so is unchanged in this commit).

3 files changed, 39 insertions(+), 16 deletions(-)

src/AstGen.zig+10-6
......@@ -1319,25 +1319,25 @@ fn arrayInitExpr(
13191319 },
13201320 .ref => {
13211321 if (types.array != .none) {
1322 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, .array_init_ref);
1322 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init_ref);
13231323 } else {
13241324 return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref);
13251325 }
13261326 },
13271327 .none => {
13281328 if (types.array != .none) {
1329 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, .array_init);
1329 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init);
13301330 } else {
13311331 return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
13321332 }
13331333 },
13341334 .ty, .coerced_ty => |ty_inst| {
13351335 if (types.array != .none) {
1336 const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, .array_init);
1336 const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init);
13371337 return rvalue(gz, rl, result, node);
13381338 } else {
13391339 const elem_type = try gz.addUnNode(.elem_type, ty_inst, node);
1340 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, elem_type, .array_init);
1340 return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, elem_type, types.array, .array_init);
13411341 }
13421342 },
13431343 .ptr => |ptr_inst| {
......@@ -1387,14 +1387,18 @@ fn arrayInitExprRlTy(
13871387 node: Ast.Node.Index,
13881388 elements: []const Ast.Node.Index,
13891389 elem_ty_inst: Zir.Inst.Ref,
1390 array_ty: Zir.Inst.Ref,
13901391 tag: Zir.Inst.Tag,
13911392) InnerError!Zir.Inst.Ref {
13921393 const astgen = gz.astgen;
13931394
13941395 const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1395 .operands_len = @intCast(u32, elements.len),
1396 .operands_len = @intCast(u32, elements.len + 1),
13961397 });
1397 var extra_index = try reserveExtra(astgen, elements.len);
1398 var extra_index = try reserveExtra(astgen, elements.len + 1);
1399
1400 astgen.extra.items[extra_index] = @enumToInt(array_ty);
1401 extra_index += 1;
13981402
13991403 const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
14001404 for (elements) |elem_init| {
src/Sema.zig+21-10
......@@ -11796,23 +11796,34 @@ fn zirArrayInit(
1179611796
1179711797 for (args) |arg, i| resolved_args[i] = sema.resolveInst(arg);
1179811798
11799 const elem_ty = sema.typeOf(resolved_args[0]);
11799 const elem_ty = sema.typeOf(resolved_args[1]);
11800 const array_ty = switch (resolved_args[0]) {
11801 .none => try Type.Tag.array.create(sema.arena, .{
11802 .len = resolved_args.len,
11803 .elem_type = elem_ty,
11804 }),
1180011805
11801 const array_ty = try Type.Tag.array.create(sema.arena, .{
11802 .len = resolved_args.len,
11803 .elem_type = elem_ty,
11804 });
11806 else => |ref| blk: {
11807 assert(sema.typeOf(ref).zigTypeTag() == .Type);
11808 var buffer: Value.ToTypeBuffer = undefined;
11809 const val = try sema.resolveConstValue(block, src, ref);
11810 const ty = val.toType(&buffer);
11811 break :blk try ty.copy(sema.arena);
11812 },
11813 };
11814
11815 const elems = resolved_args[1..];
1180511816
11806 const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {
11817 const opt_runtime_src: ?LazySrcLoc = for (elems) |arg| {
1180711818 const arg_src = src; // TODO better source location
1180811819 const comptime_known = try sema.isComptimeKnown(block, arg_src, arg);
1180911820 if (!comptime_known) break arg_src;
1181011821 } else null;
1181111822
1181211823 const runtime_src = opt_runtime_src orelse {
11813 const elem_vals = try sema.arena.alloc(Value, resolved_args.len);
11824 const elem_vals = try sema.arena.alloc(Value, elems.len);
1181411825
11815 for (resolved_args) |arg, i| {
11826 for (elems) |arg, i| {
1181611827 // We checked that all args are comptime above.
1181711828 elem_vals[i] = (sema.resolveMaybeUndefVal(block, src, arg) catch unreachable).?;
1181811829 }
......@@ -11839,7 +11850,7 @@ fn zirArrayInit(
1183911850 });
1184011851 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1184111852
11842 for (resolved_args) |arg, i| {
11853 for (elems) |arg, i| {
1184311854 const index = try sema.addIntUnsigned(Type.usize, i);
1184411855 const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);
1184511856 _ = try block.addBinOp(.store, elem_ptr, arg);
......@@ -11847,7 +11858,7 @@ fn zirArrayInit(
1184711858 return alloc;
1184811859 }
1184911860
11850 return block.addAggregateInit(array_ty, resolved_args);
11861 return block.addAggregateInit(array_ty, elems);
1185111862}
1185211863
1185311864fn zirArrayInitAnon(
test/behavior/pointers.zig+8
......@@ -270,6 +270,14 @@ test "assign null directly to C pointer and test null equality" {
270270 comptime try expect((y1 orelse &othery) == y1);
271271}
272272
273test "array initialization types" {
274 const E = enum { A, B, C };
275 try expect(@TypeOf([_]u8{}) == [0]u8);
276 try expect(@TypeOf([_:0]u8{}) == [0:0]u8);
277 try expect(@TypeOf([_:.A]E{}) == [0:.A]E);
278 try expect(@TypeOf([_:0]u8{ 1, 2, 3 }) == [3:0]u8);
279}
280
273281test "null terminated pointer" {
274282 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
275283