| author | |
| committer | |
| log | c9fac41368c872d424681ea3cf93a9d97157143e |
| tree | 887f6058136580aad6110a329d82038ba71ad663 |
| parent | c7e4c711fc5795e66f974316611922a0b962eb99 |
| signature |
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( |
| 1319 | 1319 | }, |
| 1320 | 1320 | .ref => { |
| 1321 | 1321 | 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); | |
| 1323 | 1323 | } else { |
| 1324 | 1324 | return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref); |
| 1325 | 1325 | } |
| 1326 | 1326 | }, |
| 1327 | 1327 | .none => { |
| 1328 | 1328 | 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); | |
| 1330 | 1330 | } else { |
| 1331 | 1331 | return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); |
| 1332 | 1332 | } |
| 1333 | 1333 | }, |
| 1334 | 1334 | .ty, .coerced_ty => |ty_inst| { |
| 1335 | 1335 | 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); | |
| 1337 | 1337 | return rvalue(gz, rl, result, node); |
| 1338 | 1338 | } else { |
| 1339 | 1339 | 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); | |
| 1341 | 1341 | } |
| 1342 | 1342 | }, |
| 1343 | 1343 | .ptr => |ptr_inst| { |
| ... | ... | @@ -1387,14 +1387,18 @@ fn arrayInitExprRlTy( |
| 1387 | 1387 | node: Ast.Node.Index, |
| 1388 | 1388 | elements: []const Ast.Node.Index, |
| 1389 | 1389 | elem_ty_inst: Zir.Inst.Ref, |
| 1390 | array_ty: Zir.Inst.Ref, | |
| 1390 | 1391 | tag: Zir.Inst.Tag, |
| 1391 | 1392 | ) InnerError!Zir.Inst.Ref { |
| 1392 | 1393 | const astgen = gz.astgen; |
| 1393 | 1394 | |
| 1394 | 1395 | const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{ |
| 1395 | .operands_len = @intCast(u32, elements.len), | |
| 1396 | .operands_len = @intCast(u32, elements.len + 1), | |
| 1396 | 1397 | }); |
| 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; | |
| 1398 | 1402 | |
| 1399 | 1403 | const elem_rl: ResultLoc = .{ .ty = elem_ty_inst }; |
| 1400 | 1404 | for (elements) |elem_init| { |
src/Sema.zig+21-10| ... | ... | @@ -11796,23 +11796,34 @@ fn zirArrayInit( |
| 11796 | 11796 | |
| 11797 | 11797 | for (args) |arg, i| resolved_args[i] = sema.resolveInst(arg); |
| 11798 | 11798 | |
| 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 | }), | |
| 11800 | 11805 | |
| 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..]; | |
| 11805 | 11816 | |
| 11806 | const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| { | |
| 11817 | const opt_runtime_src: ?LazySrcLoc = for (elems) |arg| { | |
| 11807 | 11818 | const arg_src = src; // TODO better source location |
| 11808 | 11819 | const comptime_known = try sema.isComptimeKnown(block, arg_src, arg); |
| 11809 | 11820 | if (!comptime_known) break arg_src; |
| 11810 | 11821 | } else null; |
| 11811 | 11822 | |
| 11812 | 11823 | 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); | |
| 11814 | 11825 | |
| 11815 | for (resolved_args) |arg, i| { | |
| 11826 | for (elems) |arg, i| { | |
| 11816 | 11827 | // We checked that all args are comptime above. |
| 11817 | 11828 | elem_vals[i] = (sema.resolveMaybeUndefVal(block, src, arg) catch unreachable).?; |
| 11818 | 11829 | } |
| ... | ... | @@ -11839,7 +11850,7 @@ fn zirArrayInit( |
| 11839 | 11850 | }); |
| 11840 | 11851 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); |
| 11841 | 11852 | |
| 11842 | for (resolved_args) |arg, i| { | |
| 11853 | for (elems) |arg, i| { | |
| 11843 | 11854 | const index = try sema.addIntUnsigned(Type.usize, i); |
| 11844 | 11855 | const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref); |
| 11845 | 11856 | _ = try block.addBinOp(.store, elem_ptr, arg); |
| ... | ... | @@ -11847,7 +11858,7 @@ fn zirArrayInit( |
| 11847 | 11858 | return alloc; |
| 11848 | 11859 | } |
| 11849 | 11860 | |
| 11850 | return block.addAggregateInit(array_ty, resolved_args); | |
| 11861 | return block.addAggregateInit(array_ty, elems); | |
| 11851 | 11862 | } |
| 11852 | 11863 | |
| 11853 | 11864 | fn zirArrayInitAnon( |
test/behavior/pointers.zig+8| ... | ... | @@ -270,6 +270,14 @@ test "assign null directly to C pointer and test null equality" { |
| 270 | 270 | comptime try expect((y1 orelse &othery) == y1); |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | test "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 | ||
| 273 | 281 | test "null terminated pointer" { |
| 274 | 282 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 275 | 283 |