Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sema: remove legacy coercion #22979

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions lib/std/compress/lzma/decode.zig
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,17 @@ pub const DecoderState = struct {
.lzma_props = lzma_props,
.unpacked_size = unpacked_size,
.literal_probs = try Vec2D(u16).init(allocator, 0x400, .{ @as(usize, 1) << (lzma_props.lc + lzma_props.lp), 0x300 }),
.pos_slot_decoder = .{.{}} ** 4,
.pos_slot_decoder = @splat(.{}),
.align_decoder = .{},
.pos_decoders = .{0x400} ** 115,
.is_match = .{0x400} ** 192,
.is_rep = .{0x400} ** 12,
.is_rep_g0 = .{0x400} ** 12,
.is_rep_g1 = .{0x400} ** 12,
.is_rep_g2 = .{0x400} ** 12,
.is_rep_0long = .{0x400} ** 192,
.pos_decoders = @splat(0x400),
.is_match = @splat(0x400),
.is_rep = @splat(0x400),
.is_rep_g0 = @splat(0x400),
.is_rep_g1 = @splat(0x400),
.is_rep_g2 = @splat(0x400),
.is_rep_0long = @splat(0x400),
.state = 0,
.rep = .{0} ** 4,
.rep = @splat(0),
.len_decoder = .{},
.rep_len_decoder = .{},
};
Expand All @@ -145,15 +145,15 @@ pub const DecoderState = struct {
self.lzma_props = new_props;
for (&self.pos_slot_decoder) |*t| t.reset();
self.align_decoder.reset();
self.pos_decoders = .{0x400} ** 115;
self.is_match = .{0x400} ** 192;
self.is_rep = .{0x400} ** 12;
self.is_rep_g0 = .{0x400} ** 12;
self.is_rep_g1 = .{0x400} ** 12;
self.is_rep_g2 = .{0x400} ** 12;
self.is_rep_0long = .{0x400} ** 192;
self.pos_decoders = @splat(0x400);
self.is_match = @splat(0x400);
self.is_rep = @splat(0x400);
self.is_rep_g0 = @splat(0x400);
self.is_rep_g1 = @splat(0x400);
self.is_rep_g2 = @splat(0x400);
self.is_rep_0long = @splat(0x400);
self.state = 0;
self.rep = .{0} ** 4;
self.rep = @splat(0);
self.len_decoder.reset();
self.rep_len_decoder.reset();
}
Expand Down
6 changes: 3 additions & 3 deletions lib/std/compress/lzma/decode/rangecoder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub const RangeDecoder = struct {

pub fn BitTree(comptime num_bits: usize) type {
return struct {
probs: [1 << num_bits]u16 = .{0x400} ** (1 << num_bits),
probs: [1 << num_bits]u16 = @splat(0x400),

const Self = @This();

Expand Down Expand Up @@ -151,8 +151,8 @@ pub fn BitTree(comptime num_bits: usize) type {
pub const LenDecoder = struct {
choice: u16 = 0x400,
choice2: u16 = 0x400,
low_coder: [16]BitTree(3) = .{.{}} ** 16,
mid_coder: [16]BitTree(3) = .{.{}} ** 16,
low_coder: [16]BitTree(3) = @splat(.{}),
mid_coder: [16]BitTree(3) = @splat(.{}),
high_coder: BitTree(8) = .{},

pub fn decode(
Expand Down
112 changes: 2 additions & 110 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30053,8 +30053,8 @@ fn coerceExtra(
else => {},
},
.@"struct" => blk: {
if (inst_ty.isTuple(zcu)) {
return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
if (dest_ty.isTuple(zcu) and inst_ty.isTuple(zcu)) {
return sema.coerceTupleToTuple(block, dest_ty, inst, inst_src) catch |err| switch (err) {
error.NotCoercible => break :blk,
else => |e| return e,
};
Expand Down Expand Up @@ -32135,114 +32135,6 @@ fn coerceTupleToArrayPtrs(
return ptr_array;
}

/// Handles both tuples and anon struct literals. Coerces field-wise. Reports
/// errors for both extra fields and missing fields.
fn coerceTupleToStruct(
sema: *Sema,
block: *Block,
struct_ty: Type,
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
) !Air.Inst.Ref {
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
try struct_ty.resolveFields(pt);
try struct_ty.resolveStructFieldInits(pt);

if (struct_ty.isTuple(zcu)) {
return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
}

const struct_type = zcu.typeToStruct(struct_ty).?;
const field_vals = try sema.arena.alloc(InternPool.Index, struct_type.field_types.len);
const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
@memset(field_refs, .none);

const inst_ty = sema.typeOf(inst);
var runtime_src: ?LazySrcLoc = null;
const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
.tuple_type => |tuple| tuple.types.len,
.struct_type => ip.loadStructType(inst_ty.toIntern()).field_types.len,
else => unreachable,
};
for (0..field_count) |tuple_field_index| {
const field_src = inst_src; // TODO better source location
const field_name = inst_ty.structFieldName(tuple_field_index, zcu).unwrap() orelse
try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{tuple_field_index}, .no_embedded_nulls);

const struct_field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
const struct_field_ty = Type.fromInterned(struct_type.field_types.get(ip)[struct_field_index]);
const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, @intCast(tuple_field_index));
const coerced = try sema.coerce(block, struct_field_ty, elem_ref, field_src);
field_refs[struct_field_index] = coerced;
if (struct_type.fieldIsComptime(ip, struct_field_index)) {
const init_val = try sema.resolveValue(coerced) orelse {
return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field });
};

const field_init = Value.fromInterned(struct_type.field_inits.get(ip)[struct_field_index]);
if (!init_val.eql(field_init, struct_field_ty, pt.zcu)) {
return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, tuple_field_index);
}
}
if (runtime_src == null) {
if (try sema.resolveValue(coerced)) |field_val| {
field_vals[struct_field_index] = field_val.toIntern();
} else {
runtime_src = field_src;
}
}
}

// Populate default field values and report errors for missing fields.
var root_msg: ?*Zcu.ErrorMsg = null;
errdefer if (root_msg) |msg| msg.destroy(sema.gpa);

for (field_refs, 0..) |*field_ref, i| {
if (field_ref.* != .none) continue;

const field_name = struct_type.field_names.get(ip)[i];
const field_default_val = struct_type.fieldInit(ip, i);
const field_src = inst_src; // TODO better source location
if (field_default_val == .none) {
const template = "missing struct field: {}";
const args = .{field_name.fmt(ip)};
if (root_msg) |msg| {
try sema.errNote(field_src, msg, template, args);
} else {
root_msg = try sema.errMsg(field_src, template, args);
}
continue;
}
if (runtime_src == null) {
field_vals[i] = field_default_val;
} else {
field_ref.* = Air.internedToRef(field_default_val);
}
}

if (root_msg) |msg| {
try sema.addDeclaredHereNote(msg, struct_ty);
root_msg = null;
return sema.failWithOwnedErrorMsg(block, msg);
}

if (runtime_src) |rs| {
try sema.requireRuntimeBlock(block, inst_src, rs);
return block.addAggregateInit(struct_ty, field_refs);
}

const struct_val = try pt.intern(.{ .aggregate = .{
.ty = struct_ty.toIntern(),
.storage = .{ .elems = field_vals },
} });
// TODO: figure out InternPool removals for incremental compilation
//errdefer ip.remove(struct_val);

return Air.internedToRef(struct_val);
}

fn coerceTupleToTuple(
sema: *Sema,
block: *Block,
Expand Down
2 changes: 1 addition & 1 deletion test/behavior/tuple.zig
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ test "tuple of struct concatenation and coercion to array" {
const SomeStruct = struct { array: [4]StructWithDefault };

const value1 = SomeStruct{ .array = .{StructWithDefault{}} ++ [_]StructWithDefault{.{}} ** 3 };
const value2 = SomeStruct{ .array = .{.{}} ++ [_]StructWithDefault{.{}} ** 3 };
const value2 = SomeStruct{ .array = .{ .{}, .{}, .{}, .{} } };

try expectEqual(value1, value2);
}
Expand Down
21 changes: 21 additions & 0 deletions test/cases/compile_errors/coerce_empty_tuple_to_struct.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const empty = .{};

const Foo = struct {};
const foo: Foo = empty;

const Bar = struct { a: u32 };
const bar: Bar = empty;

comptime {
_ = foo;
}
comptime {
_ = bar;
}

// error
//
// :4:18: error: expected type 'tmp.Foo', found '@TypeOf(.{})'
// :3:13: note: struct declared here
// :7:18: error: expected type 'tmp.Bar', found '@TypeOf(.{})'
// :6:13: note: struct declared here
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export fn entry() void {
}

// error
// target=native
//
// :6:31: error: no field named '0' in struct 'tmp.S'
// :6:31: error: expected type 'tmp.S', found 'struct { comptime void = {} }'
// :1:11: note: struct declared here
Loading