From e08cdad53b25876b247322aed91257288e8b9230 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 26 May 2022 13:07:51 +0300 Subject: [PATCH] Sema: add error for runtime indexing comptime array --- src/Sema.zig | 42 ++++++++++++++++++- .../runtime_indexing_comptime_array.zig | 31 ++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 test/cases/compile_errors/runtime_indexing_comptime_array.zig diff --git a/src/Sema.zig b/src/Sema.zig index 41111cd650..170f1e5631 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7309,9 +7309,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 { @@ -18473,6 +18475,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()) { @@ -18528,6 +18549,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()) { diff --git a/test/cases/compile_errors/runtime_indexing_comptime_array.zig b/test/cases/compile_errors/runtime_indexing_comptime_array.zig new file mode 100644 index 0000000000..da603d3630 --- /dev/null +++ b/test/cases/compile_errors/runtime_indexing_comptime_array.zig @@ -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