mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 06:15:21 +00:00
AstGen: use elem_{ptr,val}_node for array access syntax
This commit is contained in:
parent
a6bf8c2593
commit
2029601cb2
@ -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,
|
||||
|
||||
39
src/Sema.zig
39
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) {
|
||||
|
||||
19
src/Zir.zig
19
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,
|
||||
|
||||
@ -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),
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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`
|
||||
@ -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`
|
||||
20
test/cases/compile_errors/illegal_comparison_of_types.zig
Normal file
20
test/cases/compile_errors/illegal_comparison_of_types.zig
Normal file
@ -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'
|
||||
@ -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'
|
||||
@ -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'
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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'
|
||||
@ -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'
|
||||
@ -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
|
||||
|
||||
@ -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'
|
||||
Loading…
x
Reference in New Issue
Block a user