mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 06:15:21 +00:00
commit
4994ac18e4
@ -9915,7 +9915,7 @@ const GenZir = struct {
|
||||
.inferred_ptr => |ptr| {
|
||||
gz.rl_ty_inst = .none;
|
||||
gz.rl_ptr = ptr;
|
||||
gz.break_result_loc = .{ .block_ptr = gz };
|
||||
gz.break_result_loc = parent_rl;
|
||||
},
|
||||
|
||||
.block_ptr => |parent_block_scope| {
|
||||
|
||||
70
src/Sema.zig
70
src/Sema.zig
@ -2881,6 +2881,28 @@ 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:
|
||||
@ -5814,8 +5836,10 @@ fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
defer tracy.end();
|
||||
|
||||
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
|
||||
const len = try sema.resolveInt(block, .unneeded, bin_inst.lhs, Type.usize);
|
||||
const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs);
|
||||
const len_src = sema.src; // TODO better source location
|
||||
const elem_src = sema.src; // TODO better source location
|
||||
const len = try sema.resolveInt(block, len_src, bin_inst.lhs, Type.usize);
|
||||
const elem_type = try sema.resolveType(block, elem_src, bin_inst.rhs);
|
||||
const array_ty = try Type.array(sema.arena, len, null, elem_type, sema.mod);
|
||||
|
||||
return sema.addType(array_ty);
|
||||
@ -7307,9 +7331,11 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
defer tracy.end();
|
||||
|
||||
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
|
||||
const src = sema.src; // TODO better source location
|
||||
const elem_index_src = sema.src; // TODO better source location
|
||||
const array = try sema.resolveInst(bin_inst.lhs);
|
||||
const elem_index = try sema.resolveInst(bin_inst.rhs);
|
||||
return sema.elemVal(block, sema.src, array, elem_index, sema.src);
|
||||
return sema.elemVal(block, src, array, elem_index, elem_index_src);
|
||||
}
|
||||
|
||||
fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -18591,6 +18617,25 @@ fn elemValArray(
|
||||
}
|
||||
}
|
||||
|
||||
const valid_rt = try sema.validateRunTimeType(block, elem_index_src, elem_ty, false);
|
||||
if (!valid_rt) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(
|
||||
block,
|
||||
elem_index_src,
|
||||
"values of type '{}' must be comptime known, but index value is runtime known",
|
||||
.{array_ty.fmt(sema.mod)},
|
||||
);
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
const src_decl = sema.mod.declPtr(block.src_decl);
|
||||
try sema.explainWhyTypeIsComptime(block, elem_index_src, msg, array_src.toSrcLoc(src_decl), array_ty);
|
||||
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
}
|
||||
|
||||
const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src;
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
if (block.wantSafety()) {
|
||||
@ -18646,6 +18691,25 @@ fn elemPtrArray(
|
||||
}
|
||||
}
|
||||
|
||||
const valid_rt = try sema.validateRunTimeType(block, elem_index_src, array_ty.elemType2(), false);
|
||||
if (!valid_rt) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(
|
||||
block,
|
||||
elem_index_src,
|
||||
"values of type '{}' must be comptime known, but index value is runtime known",
|
||||
.{array_ty.fmt(sema.mod)},
|
||||
);
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
|
||||
const src_decl = sema.mod.declPtr(block.src_decl);
|
||||
try sema.explainWhyTypeIsComptime(block, elem_index_src, msg, array_ptr_src.toSrcLoc(src_decl), array_ty);
|
||||
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
}
|
||||
|
||||
const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src;
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
if (block.wantSafety()) {
|
||||
|
||||
@ -80,6 +80,7 @@ test {
|
||||
_ = @import("behavior/bugs/11159.zig");
|
||||
_ = @import("behavior/bugs/11162.zig");
|
||||
_ = @import("behavior/bugs/11165.zig");
|
||||
_ = @import("behavior/bugs/11179.zig");
|
||||
_ = @import("behavior/bugs/11181.zig");
|
||||
_ = @import("behavior/bugs/11213.zig");
|
||||
_ = @import("behavior/byteswap.zig");
|
||||
|
||||
@ -933,3 +933,15 @@ 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;
|
||||
}
|
||||
|
||||
18
test/behavior/bugs/11179.zig
Normal file
18
test/behavior/bugs/11179.zig
Normal file
@ -0,0 +1,18 @@
|
||||
const std = @import("std");
|
||||
const Type = std.builtin.Type;
|
||||
|
||||
test "Tuple" {
|
||||
const fields_list = fields(@TypeOf(.{}));
|
||||
if (fields_list.len != 0)
|
||||
@compileError("Argument count mismatch");
|
||||
}
|
||||
|
||||
pub fn fields(comptime T: type) switch (@typeInfo(T)) {
|
||||
.Struct => []const Type.StructField,
|
||||
else => unreachable,
|
||||
} {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Struct => |info| info.fields,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
11
test/cases/compile_errors/invalid_array_elem_ty.zig
Normal file
11
test/cases/compile_errors/invalid_array_elem_ty.zig
Normal file
@ -0,0 +1,11 @@
|
||||
pub fn S() type {
|
||||
return struct {};
|
||||
}
|
||||
pub export fn entry() void {
|
||||
_ = [0]S;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2,llvm
|
||||
//
|
||||
// :4:1: error: expected type, found fn() type
|
||||
@ -0,0 +1,31 @@
|
||||
fn foo() void {}
|
||||
fn bar() void {}
|
||||
|
||||
pub export fn entry1() void {
|
||||
const TestFn = fn () void;
|
||||
const test_fns = [_]TestFn{ foo, bar };
|
||||
for (test_fns) |testFn| {
|
||||
testFn();
|
||||
}
|
||||
}
|
||||
pub export fn entry2() void {
|
||||
const TestFn = fn () void;
|
||||
const test_fns = [_]TestFn{ foo, bar };
|
||||
var i: usize = 0;
|
||||
_ = test_fns[i];
|
||||
}
|
||||
pub export fn entry3() void {
|
||||
const TestFn = fn () void;
|
||||
const test_fns = [_]TestFn{ foo, bar };
|
||||
var i: usize = 0;
|
||||
_ = &test_fns[i];
|
||||
}
|
||||
// error
|
||||
// backend=stage2,llvm
|
||||
//
|
||||
// :6:33: error: values of type '[2]fn() callconv(.C) void' must be comptime known, but index value is runtime known
|
||||
// :6:33: note: use '*const fn() callconv(.C) void' for a function pointer type
|
||||
// :13:33: error: values of type '[2]fn() callconv(.C) void' must be comptime known, but index value is runtime known
|
||||
// :13:33: note: use '*const fn() callconv(.C) void' for a function pointer type
|
||||
// :19:33: error: values of type '[2]fn() callconv(.C) void' must be comptime known, but index value is runtime known
|
||||
// :19:33: note: use '*const fn() callconv(.C) void' for a function pointer type
|
||||
Loading…
x
Reference in New Issue
Block a user