diff --git a/src/AstGen.zig b/src/AstGen.zig index 30ed680226d2..ba27165cea9e 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -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| { diff --git a/src/Sema.zig b/src/Sema.zig index 80184cb28746..38e5ce083676 100644 --- a/src/Sema.zig +++ b/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 { @@ -18471,6 +18497,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()) { @@ -18526,6 +18571,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/behavior.zig b/test/behavior.zig index 4d8b3587bc96..fabc8c0df1d4 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -81,6 +81,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/11182.zig"); _ = @import("behavior/bugs/11213.zig"); diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index d62ba75dee0e..adcba8721d6d 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.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; +} diff --git a/test/behavior/bugs/11179.zig b/test/behavior/bugs/11179.zig new file mode 100644 index 000000000000..84fa6183f379 --- /dev/null +++ b/test/behavior/bugs/11179.zig @@ -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, + }; +} diff --git a/test/cases/compile_errors/invalid_array_elem_ty.zig b/test/cases/compile_errors/invalid_array_elem_ty.zig new file mode 100644 index 000000000000..bfa79a104bff --- /dev/null +++ b/test/cases/compile_errors/invalid_array_elem_ty.zig @@ -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 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 000000000000..da603d3630fb --- /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