Sema: more runtime indexing comptime value checks
This commit is contained in:
76
src/Sema.zig
76
src/Sema.zig
@@ -19494,6 +19494,34 @@ fn elemVal(
|
||||
}
|
||||
}
|
||||
|
||||
fn validateRuntimeElemAccess(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
elem_index_src: LazySrcLoc,
|
||||
elem_ty: Type,
|
||||
parent_ty: Type,
|
||||
parent_src: LazySrcLoc,
|
||||
) CompileError!void {
|
||||
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",
|
||||
.{parent_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, parent_src.toSrcLoc(src_decl), parent_ty);
|
||||
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn tupleFieldPtr(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
@@ -19534,6 +19562,8 @@ fn tupleFieldPtr(
|
||||
);
|
||||
}
|
||||
|
||||
try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_ptr_src);
|
||||
|
||||
try sema.requireRuntimeBlock(block, tuple_ptr_src);
|
||||
return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty);
|
||||
}
|
||||
@@ -19572,6 +19602,8 @@ fn tupleField(
|
||||
return sema.addConstant(field_ty, field_values[field_index]);
|
||||
}
|
||||
|
||||
try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
|
||||
|
||||
try sema.requireRuntimeBlock(block, tuple_src);
|
||||
return block.addStructFieldVal(tuple, field_index, field_ty);
|
||||
}
|
||||
@@ -19622,24 +19654,7 @@ 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);
|
||||
}
|
||||
try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src);
|
||||
|
||||
const runtime_src = if (maybe_undef_array_val != null) elem_index_src else array_src;
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
@@ -19697,23 +19712,8 @@ fn elemPtrArray(
|
||||
}
|
||||
}
|
||||
|
||||
const valid_rt = try sema.validateRunTimeType(block, elem_index_src, array_ty.elemType2(), false);
|
||||
if (!valid_rt and !init) {
|
||||
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);
|
||||
if (!init) {
|
||||
try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(), array_ty, array_ptr_src);
|
||||
}
|
||||
|
||||
const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src;
|
||||
@@ -19769,6 +19769,8 @@ fn elemValSlice(
|
||||
}
|
||||
}
|
||||
|
||||
try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src);
|
||||
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
if (block.wantSafety()) {
|
||||
const len_inst = if (maybe_slice_val) |slice_val|
|
||||
@@ -19822,6 +19824,8 @@ fn elemPtrSlice(
|
||||
}
|
||||
}
|
||||
|
||||
try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_ty, slice_src);
|
||||
|
||||
const runtime_src = if (maybe_undef_slice_val != null) elem_index_src else slice_src;
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
if (block.wantSafety()) {
|
||||
@@ -22426,7 +22430,7 @@ fn analyzeLoad(
|
||||
}
|
||||
|
||||
if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
|
||||
if (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) |elem_val| {
|
||||
if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
|
||||
return sema.addConstant(elem_ty, elem_val);
|
||||
}
|
||||
if (block.is_typeof) {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
const Foo = struct {
|
||||
name: []const u8,
|
||||
T: type,
|
||||
};
|
||||
export fn entry() void {
|
||||
const xx: [2]Foo = .{ .{ .name = "", .T = u8 }, .{ .name = "", .T = u8 } };
|
||||
for (xx) |f| { _ = f;}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :7:10: error: values of type '[2]tmp.Foo' must be comptime known, but index value is runtime known
|
||||
// :3:8: note: struct requires comptime because of this field
|
||||
// :3:8: note: types are not available at runtime
|
||||
@@ -0,0 +1,20 @@
|
||||
export fn entry() void {
|
||||
foo(452) catch |err| switch (err) {
|
||||
error.Foo ... error.Bar => {},
|
||||
else => {},
|
||||
};
|
||||
}
|
||||
fn foo(x: i32) !void {
|
||||
switch (x) {
|
||||
0 ... 10 => return error.Foo,
|
||||
11 ... 20 => return error.Bar,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=llvm
|
||||
// target=native
|
||||
//
|
||||
// :2:34: error: ranges not allowed when switching on type '@typeInfo(@typeInfo(@TypeOf(tmp.foo)).Fn.return_type.?).ErrorUnion.error_set'
|
||||
// :3:19: note: range here
|
||||
@@ -7,7 +7,7 @@ comptime {
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:5:26: error: attempt to read 4 bytes from [4]u8 at index 1 which is 3 bytes
|
||||
// :5:26: error: dereference of '*const u24' exceeds bounds of containing decl of type '[4]u8'
|
||||
@@ -0,0 +1,20 @@
|
||||
const Struct = struct {
|
||||
a: u32,
|
||||
};
|
||||
fn getIndex() usize {
|
||||
return 2;
|
||||
}
|
||||
export fn entry() void {
|
||||
const index = getIndex();
|
||||
const field = @typeInfo(Struct).Struct.fields[index];
|
||||
_ = field;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :9:51: error: values of type '[]const builtin.Type.StructField' must be comptime known, but index value is runtime known
|
||||
// :287:21: note: struct requires comptime because of this field
|
||||
// :287:21: note: types are not available at runtime
|
||||
// :290:20: note: struct requires comptime because of this field
|
||||
@@ -1,14 +0,0 @@
|
||||
const Foo = struct {
|
||||
name: []const u8,
|
||||
T: type,
|
||||
};
|
||||
export fn entry() void {
|
||||
const xx: [2]Foo = undefined;
|
||||
for (xx) |f| { _ = f;}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:7:5: error: values of type 'Foo' must be comptime known, but index value is runtime known
|
||||
@@ -1,19 +0,0 @@
|
||||
export fn entry() void {
|
||||
try foo(452) catch |err| switch (err) {
|
||||
error.A ... error.B => {},
|
||||
else => {},
|
||||
};
|
||||
}
|
||||
fn foo(x: i32) !void {
|
||||
switch (x) {
|
||||
0 ... 10 => return error.Foo,
|
||||
11 ... 20 => return error.Bar,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:3:17: error: operator not allowed for errors
|
||||
@@ -1,17 +0,0 @@
|
||||
const Struct = struct {
|
||||
a: u32,
|
||||
};
|
||||
fn getIndex() usize {
|
||||
return 2;
|
||||
}
|
||||
export fn entry() void {
|
||||
const index = getIndex();
|
||||
const field = @typeInfo(Struct).Struct.fields[index];
|
||||
_ = field;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:9:51: error: values of type 'std.builtin.Type.StructField' must be comptime known, but index value is runtime known
|
||||
Reference in New Issue
Block a user