mirror of
https://github.com/ziglang/zig.git
synced 2026-01-05 04:53:17 +00:00
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).
This commit is contained in:
parent
c7e4c711fc
commit
c9fac41368
@ -1319,25 +1319,25 @@ fn arrayInitExpr(
|
||||
},
|
||||
.ref => {
|
||||
if (types.array != .none) {
|
||||
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, .array_init_ref);
|
||||
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init_ref);
|
||||
} else {
|
||||
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref);
|
||||
}
|
||||
},
|
||||
.none => {
|
||||
if (types.array != .none) {
|
||||
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, .array_init);
|
||||
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init);
|
||||
} else {
|
||||
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
|
||||
}
|
||||
},
|
||||
.ty, .coerced_ty => |ty_inst| {
|
||||
if (types.array != .none) {
|
||||
const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, .array_init);
|
||||
const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.array, .array_init);
|
||||
return rvalue(gz, rl, result, node);
|
||||
} else {
|
||||
const elem_type = try gz.addUnNode(.elem_type, ty_inst, node);
|
||||
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, elem_type, .array_init);
|
||||
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, elem_type, types.array, .array_init);
|
||||
}
|
||||
},
|
||||
.ptr => |ptr_inst| {
|
||||
@ -1387,14 +1387,18 @@ fn arrayInitExprRlTy(
|
||||
node: Ast.Node.Index,
|
||||
elements: []const Ast.Node.Index,
|
||||
elem_ty_inst: Zir.Inst.Ref,
|
||||
array_ty: Zir.Inst.Ref,
|
||||
tag: Zir.Inst.Tag,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const astgen = gz.astgen;
|
||||
|
||||
const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
|
||||
.operands_len = @intCast(u32, elements.len),
|
||||
.operands_len = @intCast(u32, elements.len + 1),
|
||||
});
|
||||
var extra_index = try reserveExtra(astgen, elements.len);
|
||||
var extra_index = try reserveExtra(astgen, elements.len + 1);
|
||||
|
||||
astgen.extra.items[extra_index] = @enumToInt(array_ty);
|
||||
extra_index += 1;
|
||||
|
||||
const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
|
||||
for (elements) |elem_init| {
|
||||
|
||||
31
src/Sema.zig
31
src/Sema.zig
@ -11796,23 +11796,34 @@ fn zirArrayInit(
|
||||
|
||||
for (args) |arg, i| resolved_args[i] = sema.resolveInst(arg);
|
||||
|
||||
const elem_ty = sema.typeOf(resolved_args[0]);
|
||||
const elem_ty = sema.typeOf(resolved_args[1]);
|
||||
const array_ty = switch (resolved_args[0]) {
|
||||
.none => try Type.Tag.array.create(sema.arena, .{
|
||||
.len = resolved_args.len,
|
||||
.elem_type = elem_ty,
|
||||
}),
|
||||
|
||||
const array_ty = try Type.Tag.array.create(sema.arena, .{
|
||||
.len = resolved_args.len,
|
||||
.elem_type = elem_ty,
|
||||
});
|
||||
else => |ref| blk: {
|
||||
assert(sema.typeOf(ref).zigTypeTag() == .Type);
|
||||
var buffer: Value.ToTypeBuffer = undefined;
|
||||
const val = try sema.resolveConstValue(block, src, ref);
|
||||
const ty = val.toType(&buffer);
|
||||
break :blk try ty.copy(sema.arena);
|
||||
},
|
||||
};
|
||||
|
||||
const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {
|
||||
const elems = resolved_args[1..];
|
||||
|
||||
const opt_runtime_src: ?LazySrcLoc = for (elems) |arg| {
|
||||
const arg_src = src; // TODO better source location
|
||||
const comptime_known = try sema.isComptimeKnown(block, arg_src, arg);
|
||||
if (!comptime_known) break arg_src;
|
||||
} else null;
|
||||
|
||||
const runtime_src = opt_runtime_src orelse {
|
||||
const elem_vals = try sema.arena.alloc(Value, resolved_args.len);
|
||||
const elem_vals = try sema.arena.alloc(Value, elems.len);
|
||||
|
||||
for (resolved_args) |arg, i| {
|
||||
for (elems) |arg, i| {
|
||||
// We checked that all args are comptime above.
|
||||
elem_vals[i] = (sema.resolveMaybeUndefVal(block, src, arg) catch unreachable).?;
|
||||
}
|
||||
@ -11839,7 +11850,7 @@ fn zirArrayInit(
|
||||
});
|
||||
const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
|
||||
|
||||
for (resolved_args) |arg, i| {
|
||||
for (elems) |arg, i| {
|
||||
const index = try sema.addIntUnsigned(Type.usize, i);
|
||||
const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);
|
||||
_ = try block.addBinOp(.store, elem_ptr, arg);
|
||||
@ -11847,7 +11858,7 @@ fn zirArrayInit(
|
||||
return alloc;
|
||||
}
|
||||
|
||||
return block.addAggregateInit(array_ty, resolved_args);
|
||||
return block.addAggregateInit(array_ty, elems);
|
||||
}
|
||||
|
||||
fn zirArrayInitAnon(
|
||||
|
||||
@ -270,6 +270,14 @@ test "assign null directly to C pointer and test null equality" {
|
||||
comptime try expect((y1 orelse &othery) == y1);
|
||||
}
|
||||
|
||||
test "array initialization types" {
|
||||
const E = enum { A, B, C };
|
||||
try expect(@TypeOf([_]u8{}) == [0]u8);
|
||||
try expect(@TypeOf([_:0]u8{}) == [0:0]u8);
|
||||
try expect(@TypeOf([_:.A]E{}) == [0:.A]E);
|
||||
try expect(@TypeOf([_:0]u8{ 1, 2, 3 }) == [3:0]u8);
|
||||
}
|
||||
|
||||
test "null terminated pointer" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user