mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Merge pull request #11958 from ziglang/store-to-inferred-ptr
stage2: fix miscompilations for peer expressions any time they needed coercions to runtime types
This commit is contained in:
commit
98681b2da0
@ -286,7 +286,6 @@ const PQlt = PriorityQueue(u32, void, lessThan);
|
||||
const PQgt = PriorityQueue(u32, void, greaterThan);
|
||||
|
||||
test "std.PriorityQueue: add and remove min heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -305,7 +304,6 @@ test "std.PriorityQueue: add and remove min heap" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: add and remove same min heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -355,7 +353,6 @@ test "std.PriorityQueue: peek" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: sift up with odd indices" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
|
||||
@ -370,7 +367,6 @@ test "std.PriorityQueue: sift up with odd indices" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: addSlice" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
|
||||
@ -403,7 +399,6 @@ test "std.PriorityQueue: fromOwnedSlice trivial case 1" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: fromOwnedSlice" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
|
||||
const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
|
||||
const heap_items = try testing.allocator.dupe(u32, items[0..]);
|
||||
var queue = PQlt.fromOwnedSlice(testing.allocator, heap_items[0..], {});
|
||||
@ -416,7 +411,6 @@ test "std.PriorityQueue: fromOwnedSlice" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: add and remove max heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQgt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -435,7 +429,6 @@ test "std.PriorityQueue: add and remove max heap" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: add and remove same max heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQgt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -476,7 +469,6 @@ test "std.PriorityQueue: iterator" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: remove at index" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -512,7 +504,6 @@ test "std.PriorityQueue: iterator while empty" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: shrinkAndFree" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -536,7 +527,6 @@ test "std.PriorityQueue: shrinkAndFree" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: update min heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -552,7 +542,6 @@ test "std.PriorityQueue: update min heap" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: update same min heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -569,7 +558,6 @@ test "std.PriorityQueue: update same min heap" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: update max heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQgt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -585,7 +573,6 @@ test "std.PriorityQueue: update max heap" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: update same max heap" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQgt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -602,7 +589,6 @@ test "std.PriorityQueue: update same max heap" {
|
||||
}
|
||||
|
||||
test "std.PriorityQueue: siftUp in remove" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
var queue = PQlt.init(testing.allocator, {});
|
||||
defer queue.deinit();
|
||||
|
||||
@ -623,7 +609,6 @@ fn contextLessThan(context: []const u32, a: usize, b: usize) Order {
|
||||
const CPQlt = PriorityQueue(usize, []const u32, contextLessThan);
|
||||
|
||||
test "std.PriorityQueue: add and remove min heap with contextful comparator" {
|
||||
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
const context = [_]u32{ 5, 3, 4, 2, 2, 8, 0 };
|
||||
|
||||
var queue = CPQlt.init(testing.allocator, context[0..]);
|
||||
|
||||
@ -10007,7 +10007,7 @@ const GenZir = struct {
|
||||
.inferred_ptr => |ptr| {
|
||||
gz.rl_ty_inst = .none;
|
||||
gz.rl_ptr = ptr;
|
||||
gz.break_result_loc = parent_rl;
|
||||
gz.break_result_loc = .{ .block_ptr = gz };
|
||||
},
|
||||
|
||||
.block_ptr => |parent_block_scope| {
|
||||
|
||||
23
src/Sema.zig
23
src/Sema.zig
@ -3079,28 +3079,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
|
||||
|
||||
if (var_is_mut) {
|
||||
try sema.validateVarType(block, ty_src, final_elem_ty, false);
|
||||
|
||||
// The value might have been bitcasted into a comptime only
|
||||
// pointer type such as `*@Type(.EnumLiteral)` so we must now
|
||||
// update all the stores to not give backends invalid AIR.
|
||||
|
||||
var air_tags = sema.air_instructions.items(.tag);
|
||||
var air_data = sema.air_instructions.items(.data);
|
||||
var peer_inst_index: usize = 0;
|
||||
var i = ptr_inst;
|
||||
while (i < air_tags.len and peer_inst_index < peer_inst_list.len) : (i += 1) {
|
||||
if (air_tags[i] != .store) continue;
|
||||
if (air_data[i].bin_op.rhs == peer_inst_list[peer_inst_index]) {
|
||||
peer_inst_index += 1;
|
||||
_ = (try sema.resolveMaybeUndefVal(block, .unneeded, air_data[i].bin_op.rhs)) orelse continue;
|
||||
const coerced_val = try sema.coerce(block, final_elem_ty, air_data[i].bin_op.rhs, .unneeded);
|
||||
air_tags = sema.air_instructions.items(.tag);
|
||||
air_data = sema.air_instructions.items(.data);
|
||||
|
||||
air_data[i].bin_op.lhs = ptr;
|
||||
air_data[i].bin_op.rhs = coerced_val;
|
||||
}
|
||||
}
|
||||
} else ct: {
|
||||
// Detect if the value is comptime known. In such case, the
|
||||
// last 3 AIR instructions of the block will look like this:
|
||||
@ -4478,6 +4456,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
.label = &label,
|
||||
.inlining = parent_block.inlining,
|
||||
.is_comptime = parent_block.is_comptime,
|
||||
.want_safety = parent_block.want_safety,
|
||||
};
|
||||
|
||||
defer child_block.instructions.deinit(gpa);
|
||||
|
||||
@ -427,15 +427,63 @@ pub fn print(
|
||||
},
|
||||
.eu_payload_ptr => {
|
||||
try writer.writeAll("&");
|
||||
val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
|
||||
ty = ty.elemType2().errorUnionPayload();
|
||||
|
||||
const data = val.castTag(.eu_payload_ptr).?.data;
|
||||
|
||||
var ty_val: Value.Payload.Ty = .{
|
||||
.base = .{ .tag = .ty },
|
||||
.data = ty,
|
||||
};
|
||||
|
||||
try writer.writeAll("@as(");
|
||||
try print(.{
|
||||
.ty = Type.type,
|
||||
.val = Value.initPayload(&ty_val.base),
|
||||
}, writer, level - 1, mod);
|
||||
|
||||
try writer.writeAll(", &(payload of ");
|
||||
|
||||
var ptr_ty: Type.Payload.ElemType = .{
|
||||
.base = .{ .tag = .single_mut_pointer },
|
||||
.data = data.container_ty,
|
||||
};
|
||||
|
||||
try print(.{
|
||||
.ty = Type.initPayload(&ptr_ty.base),
|
||||
.val = data.container_ptr,
|
||||
}, writer, level - 1, mod);
|
||||
|
||||
try writer.writeAll("))");
|
||||
return;
|
||||
},
|
||||
.opt_payload_ptr => {
|
||||
try writer.writeAll("&");
|
||||
val = val.castTag(.opt_payload).?.data;
|
||||
var buf: Type.Payload.ElemType = undefined;
|
||||
ty = ty.elemType2().optionalChild(&buf);
|
||||
return print(.{ .ty = ty, .val = val }, writer, level, mod);
|
||||
const data = val.castTag(.opt_payload_ptr).?.data;
|
||||
|
||||
var ty_val: Value.Payload.Ty = .{
|
||||
.base = .{ .tag = .ty },
|
||||
.data = ty,
|
||||
};
|
||||
|
||||
try writer.writeAll("@as(");
|
||||
try print(.{
|
||||
.ty = Type.type,
|
||||
.val = Value.initPayload(&ty_val.base),
|
||||
}, writer, level - 1, mod);
|
||||
|
||||
try writer.writeAll(", &(payload of ");
|
||||
|
||||
var ptr_ty: Type.Payload.ElemType = .{
|
||||
.base = .{ .tag = .single_mut_pointer },
|
||||
.data = data.container_ty,
|
||||
};
|
||||
|
||||
try print(.{
|
||||
.ty = Type.initPayload(&ptr_ty.base),
|
||||
.val = data.container_ptr,
|
||||
}, writer, level - 1, mod);
|
||||
|
||||
try writer.writeAll("))");
|
||||
return;
|
||||
},
|
||||
|
||||
// TODO these should not appear in this function
|
||||
|
||||
@ -2217,6 +2217,7 @@ const Writer = struct {
|
||||
|
||||
fn writeUnreachable(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].@"unreachable";
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
|
||||
@ -928,18 +928,6 @@ test "try in labeled block doesn't cast to wrong type" {
|
||||
_ = s;
|
||||
}
|
||||
|
||||
test "comptime int in switch in catch is casted to correct inferred type" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
|
||||
var a: error{ A, B }!u64 = 0;
|
||||
var b = a catch |err| switch (err) {
|
||||
error.A => 0,
|
||||
else => unreachable,
|
||||
};
|
||||
_ = b;
|
||||
}
|
||||
|
||||
test "vector initialized with array init syntax has proper type" {
|
||||
comptime {
|
||||
const actual = -@Vector(4, i32){ 1, 2, 3, 4 };
|
||||
|
||||
@ -812,6 +812,7 @@ test "peer type resolution: error union after non-error" {
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to E![]const T" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
@ -826,6 +827,7 @@ test "peer cast *[0]T to E![]const T" {
|
||||
}
|
||||
|
||||
test "peer cast *[0]T to []const T" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
@ -709,7 +709,7 @@ test "simple else prong allowed even when all errors handled" {
|
||||
}
|
||||
};
|
||||
var value = S.foo() catch |err| switch (err) {
|
||||
error.Foo => 255,
|
||||
error.Foo => @as(u8, 255),
|
||||
else => |e| return e,
|
||||
};
|
||||
try expect(value == 255);
|
||||
|
||||
@ -111,3 +111,20 @@ test "if prongs cast to expected type instead of peer type resolution" {
|
||||
try S.doTheTest(false);
|
||||
comptime try S.doTheTest(false);
|
||||
}
|
||||
|
||||
test "if peer expressions inferred optional type" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
var self: []const u8 = "abcdef";
|
||||
var index: usize = 0;
|
||||
var left_index = (index << 1) + 1;
|
||||
var right_index = left_index + 1;
|
||||
var left = if (left_index < self.len) self[left_index] else null;
|
||||
var right = if (right_index < self.len) self[right_index] else null;
|
||||
try expect(left_index < self.len);
|
||||
try expect(right_index < self.len);
|
||||
try expect(left.? == 98);
|
||||
try expect(right.? == 99);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user