Commit 2029601cb2
Changed files (18)
test
cases
compile_errors
src/AstGen.zig
@@ -5154,16 +5154,14 @@ fn arrayAccess(
const tree = astgen.tree;
const node_datas = tree.nodes.items(.data);
switch (rl) {
- .ref => return gz.addBin(
- .elem_ptr,
- try expr(gz, scope, .ref, node_datas[node].lhs),
- try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
- ),
- else => return rvalue(gz, rl, try gz.addBin(
- .elem_val,
- try expr(gz, scope, .none, node_datas[node].lhs),
- try expr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs),
- ), node),
+ .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{
+ .lhs = try expr(gz, scope, .ref, node_datas[node].lhs),
+ .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
+ }),
+ else => return rvalue(gz, rl, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{
+ .lhs = try expr(gz, scope, .none, node_datas[node].lhs),
+ .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
+ }), node),
}
}
@@ -5685,7 +5683,7 @@ fn whileExpr(
try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
}
if (while_full.ast.cont_expr != 0) {
- _ = try expr(&loop_scope, then_sub_scope, .{ .ty = .void_type }, while_full.ast.cont_expr);
+ _ = try unusedResultExpr(&loop_scope, then_sub_scope, while_full.ast.cont_expr);
}
try then_scope.addDbgBlockEnd();
const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
@@ -5890,7 +5888,10 @@ fn forExpr(
if (!mem.eql(u8, value_name, "_")) {
const name_str_index = try astgen.identAsString(ident);
const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;
- const payload_inst = try then_scope.addBin(tag, array_ptr, index);
+ const payload_inst = try then_scope.addPlNode(tag, for_full.ast.cond_expr, Zir.Inst.Bin{
+ .lhs = array_ptr,
+ .rhs = index,
+ });
try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name);
payload_val_scope = .{
.parent = &then_scope.base,
src/print_zir.zig
@@ -144,8 +144,6 @@ const Writer = struct {
switch (tag) {
.array_type,
.as,
- .elem_ptr,
- .elem_val,
.store,
.store_to_block_ptr,
.store_to_inferred_ptr,
@@ -355,6 +353,8 @@ const Writer = struct {
.minimum,
.elem_ptr_node,
.elem_val_node,
+ .elem_ptr,
+ .elem_val,
.coerce_result_ptr,
=> try self.writePlNodeBin(stream, inst),
src/Sema.zig
@@ -2738,6 +2738,7 @@ fn ensureResultUsed(
const operand_ty = sema.typeOf(operand);
switch (operand_ty.zigTypeTag()) {
.Void, .NoReturn => return,
+ .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is ignored. consider using `try`, `catch`, or `if`", .{}),
else => return sema.fail(block, src, "expression value is ignored", .{}),
}
}
@@ -2751,7 +2752,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
const src = inst_data.src();
const operand_ty = sema.typeOf(operand);
switch (operand_ty.zigTypeTag()) {
- .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discardederror is discarded. consider using `try`, `catch`, or `if`", .{}),
+ .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discarded. consider using `try`, `catch`, or `if`", .{}),
else => return,
}
}
@@ -7092,7 +7093,7 @@ fn funcCommon(
const param_types = try sema.arena.alloc(Type, block.params.items.len);
const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
for (block.params.items) |param, i| {
- const param_src = LazySrcLoc.nodeOffset(src_node_offset); // TODO better src
+ const param_src = LazySrcLoc.nodeOffset(src_node_offset); // TODO better soruce location
param_types[i] = param.ty;
comptime_params[i] = param.is_comptime or
try sema.typeRequiresComptime(block, param_src, param.ty);
@@ -7798,12 +7799,12 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const tracy = trace(@src());
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, src, array, elem_index, elem_index_src);
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
+ const array = try sema.resolveInst(extra.lhs);
+ const elem_index = try sema.resolveInst(extra.rhs);
+ return sema.elemVal(block, src, array, elem_index, src);
}
fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -7823,10 +7824,12 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const tracy = trace(@src());
defer tracy.end();
- const bin_inst = sema.code.instructions.items(.data)[inst].bin;
- const array_ptr = try sema.resolveInst(bin_inst.lhs);
- const elem_index = try sema.resolveInst(bin_inst.rhs);
- return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src, false);
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src = inst_data.src();
+ const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
+ const array_ptr = try sema.resolveInst(extra.lhs);
+ const elem_index = try sema.resolveInst(extra.rhs);
+ return sema.elemPtr(block, src, array_ptr, elem_index, src, false);
}
fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -19454,7 +19457,7 @@ fn tupleFieldPtr(
const tuple_fields = tuple_ty.tupleFields();
if (tuple_fields.types.len == 0) {
- return sema.fail(block, field_index_src, "indexing into empty tuple", .{});
+ return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});
}
if (field_index >= tuple_fields.types.len) {
@@ -19497,7 +19500,7 @@ fn tupleField(
const tuple_fields = tuple_ty.tupleFields();
if (tuple_fields.types.len == 0) {
- return sema.fail(block, field_index_src, "indexing into empty tuple", .{});
+ return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});
}
if (field_index >= tuple_fields.types.len) {
@@ -19538,7 +19541,7 @@ fn elemValArray(
const elem_ty = array_ty.childType();
if (array_len_s == 0) {
- return sema.fail(block, elem_index_src, "indexing into empty array", .{});
+ return sema.fail(block, array_src, "indexing into empty array is not allowed", .{});
}
const maybe_undef_array_val = try sema.resolveMaybeUndefVal(block, array_src, array);
@@ -19618,7 +19621,7 @@ fn elemPtrArray(
const array_len_s = array_len + @boolToInt(array_sent);
if (array_len_s == 0) {
- return sema.fail(block, elem_index_src, "indexing into empty array", .{});
+ return sema.fail(block, array_ptr_src, "indexing into empty array is not allowed", .{});
}
const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(block, array_ptr_src, array_ptr);
@@ -19700,7 +19703,7 @@ fn elemValSlice(
const slice_len = slice_val.sliceLen(sema.mod);
const slice_len_s = slice_len + @boolToInt(slice_sent);
if (slice_len_s == 0) {
- return sema.fail(block, elem_index_src, "indexing into empty slice", .{});
+ return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
}
if (maybe_index_val) |index_val| {
const index = @intCast(usize, index_val.toUnsignedInt(target));
@@ -19757,7 +19760,7 @@ fn elemPtrSlice(
const slice_len = slice_val.sliceLen(sema.mod);
const slice_len_s = slice_len + @boolToInt(slice_sent);
if (slice_len_s == 0) {
- return sema.fail(block, elem_index_src, "indexing into empty slice", .{});
+ return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
}
if (offset) |index| {
if (index >= slice_len_s) {
src/type.zig
@@ -189,7 +189,7 @@ pub const Type = extern union {
.Frame,
=> false,
- .Pointer => is_equality_cmp or ty.isCPtr(),
+ .Pointer => !ty.isSlice() and (is_equality_cmp or ty.isCPtr()),
.Optional => {
if (!is_equality_cmp) return false;
var buf: Payload.ElemType = undefined;
src/Zir.zig
@@ -370,24 +370,23 @@ pub const Inst = struct {
/// Uses the `pl_node` union field. Payload is `Bin`.
div,
/// Given a pointer to an array, slice, or pointer, returns a pointer to the element at
- /// the provided index. Uses the `bin` union field. Source location is implied
- /// to be the same as the previous instruction.
- elem_ptr,
- /// Same as `elem_ptr` except also stores a source location node.
+ /// the provided index.
/// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
elem_ptr_node,
+ /// Same as `elem_ptr_node` but used only for for loop.
+ /// Uses the `pl_node` union field. AST node is the condition of a for loop. Payload is `Bin`.
+ elem_ptr,
/// Same as `elem_ptr_node` except the index is stored immediately rather than
/// as a reference to another ZIR instruction.
/// Uses the `pl_node` union field. AST node is an element inside array initialization
/// syntax. Payload is `ElemPtrImm`.
elem_ptr_imm,
/// Given an array, slice, or pointer, returns the element at the provided index.
- /// Uses the `bin` union field. Source location is implied to be the same
- /// as the previous instruction.
- elem_val,
- /// Same as `elem_val` except also stores a source location node.
/// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
elem_val_node,
+ /// Same as `elem_val_node` but used only for for loop.
+ /// Uses the `pl_node` union field. AST node is the condition of a for loop. Payload is `Bin`.
+ elem_val,
/// Emits a compile error if the operand is not `void`.
/// Uses the `un_node` field.
ensure_result_used,
@@ -1627,10 +1626,10 @@ pub const Inst = struct {
.decl_val = .str_tok,
.load = .un_node,
.div = .pl_node,
- .elem_ptr = .bin,
+ .elem_ptr = .pl_node,
.elem_ptr_node = .pl_node,
.elem_ptr_imm = .pl_node,
- .elem_val = .bin,
+ .elem_val = .pl_node,
.elem_val_node = .pl_node,
.ensure_result_used = .un_node,
.ensure_result_non_error = .un_node,
test/cases/compile_errors/stage1/obj/illegal_comparison_of_types.zig
@@ -1,20 +0,0 @@
-fn bad_eql_1(a: []u8, b: []u8) bool {
- return a == b;
-}
-const EnumWithData = union(enum) {
- One: void,
- Two: i32,
-};
-fn bad_eql_2(a: *const EnumWithData, b: *const EnumWithData) bool {
- return a.* == b.*;
-}
-
-export fn entry1() usize { return @sizeOf(@TypeOf(bad_eql_1)); }
-export fn entry2() usize { return @sizeOf(@TypeOf(bad_eql_2)); }
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:14: error: operator not allowed for type '[]u8'
-// tmp.zig:9:16: error: operator not allowed for type 'EnumWithData'
test/cases/compile_errors/stage1/obj/implicit_cast_from_f64_to_f32.zig → test/cases/compile_errors/stage1/implicit_cast_from_f64_to_f32.zig
File renamed without changes
test/cases/compile_errors/stage1/obj/int_to_ptr_of_0_bits.zig → test/cases/compile_errors/stage1/int_to_ptr_of_0_bits.zig
File renamed without changes
test/cases/compile_errors/stage1/obj/ignored_deferred_function_call.zig → test/cases/compile_errors/ignored_deferred_function_call.zig
@@ -4,7 +4,7 @@ export fn foo() void {
fn bar() anyerror!i32 { return 0; }
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:2:14: error: error is ignored. consider using `try`, `catch`, or `if`
+// :2:14: error: error is ignored. consider using `try`, `catch`, or `if`
test/cases/compile_errors/stage1/obj/ignored_expression_in_while_continuation.zig → test/cases/compile_errors/ignored_expression_in_while_continuation.zig
@@ -14,9 +14,9 @@ fn bad() anyerror!void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:2:24: error: error is ignored. consider using `try`, `catch`, or `if`
-// tmp.zig:6:25: error: error is ignored. consider using `try`, `catch`, or `if`
-// tmp.zig:10:25: error: error is ignored. consider using `try`, `catch`, or `if`
+// :2:24: error: error is ignored. consider using `try`, `catch`, or `if`
+// :6:25: error: error is ignored. consider using `try`, `catch`, or `if`
+// :10:25: error: error is ignored. consider using `try`, `catch`, or `if`
test/cases/compile_errors/illegal_comparison_of_types.zig
@@ -0,0 +1,20 @@
+fn bad_eql_1(a: []u8, b: []u8) bool {
+ return a == b;
+}
+const EnumWithData = union(enum) {
+ One: void,
+ Two: i32,
+};
+fn bad_eql_2(a: *const EnumWithData, b: *const EnumWithData) bool {
+ return a.* == b.*;
+}
+
+export fn entry1() usize { return @sizeOf(@TypeOf(&bad_eql_1)); }
+export fn entry2() usize { return @sizeOf(@TypeOf(&bad_eql_2)); }
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:14: error: operator == not allowed for type '[]u8'
+// :9:16: error: operator == not allowed for type 'tmp.EnumWithData'
test/cases/compile_errors/stage1/obj/implicitly_casting_enum_to_tag_type.zig → test/cases/compile_errors/implicitly_casting_enum_to_tag_type.zig
@@ -11,7 +11,7 @@ export fn entry() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:9:22: error: expected type 'u2', found 'Small'
+// :9:22: error: expected type 'u2', found 'tmp.Small'
test/cases/compile_errors/stage1/obj/incorrect_return_type.zig → test/cases/compile_errors/incorrect_return_type.zig
@@ -15,7 +15,7 @@
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:8:16: error: expected type 'A', found 'B'
+// :8:16: error: expected type 'tmp.A', found 'tmp.B'
test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero.zig → test/cases/compile_errors/indexing_an_array_of_size_zero.zig
@@ -5,7 +5,7 @@ export fn foo() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:3:27: error: accessing a zero length array is not allowed
+// :3:27: error: indexing into empty array is not allowed
test/cases/compile_errors/stage1/obj/indexing_an_array_of_size_zero_with_runtime_index.zig → test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig
@@ -6,7 +6,7 @@ export fn foo() void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:4:27: error: accessing a zero length array is not allowed
+// :4:27: error: indexing into empty array is not allowed
test/cases/compile_errors/stage1/obj/indexing_single-item_pointer.zig → test/cases/compile_errors/indexing_single-item_pointer.zig
@@ -3,7 +3,7 @@ export fn entry(ptr: *i32) i32 {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:2:15: error: index of single-item pointer
+// :2:15: error: element access of non-indexable type '*i32'
test/cases/compile_errors/stage1/obj/invalid_cast_from_integral_type_to_enum.zig → test/cases/compile_errors/invalid_cast_from_integral_type_to_enum.zig
@@ -11,7 +11,7 @@ fn foo(x: usize) void {
}
// error
-// backend=stage1
+// backend=stage2
// target=native
//
-// tmp.zig:9:10: error: expected type 'usize', found 'E'
+// :9:10: error: expected type 'usize', found 'tmp.E'
test/cases/compile_errors/runtime_indexing_comptime_array.zig
@@ -24,9 +24,9 @@ pub export fn entry3() void {
// target=native
// backend=stage2
//
-// :6:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known
-// :6:5: note: use '*const fn() void' for a function pointer type
-// :13:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known
-// :13:5: note: use '*const fn() void' for a function pointer type
-// :19:5: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known
-// :19:5: note: use '*const fn() void' for a function pointer type
+// :7:10: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known
+// :7:10: note: use '*const fn() void' for a function pointer type
+// :15:18: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known
+// :15:17: note: use '*const fn() void' for a function pointer type
+// :21:19: error: values of type '[2]fn() void' must be comptime known, but index value is runtime known
+// :21:18: note: use '*const fn() void' for a function pointer type