mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 03:03:09 +00:00
Sema: fix and improve errors for for loop objects and non-indexables
Operands to @memcpy and @memset were being called "for loop operands" in the error.
This commit is contained in:
parent
743976ef48
commit
3485a0e7fb
54
src/Sema.zig
54
src/Sema.zig
@ -3401,8 +3401,8 @@ fn indexablePtrLen(
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const object_ty = sema.typeOf(object);
|
||||
const is_pointer_to = object_ty.isSinglePointer();
|
||||
const array_ty = if (is_pointer_to) object_ty.childType() else object_ty;
|
||||
try checkIndexable(sema, block, src, array_ty);
|
||||
const indexable_ty = if (is_pointer_to) object_ty.childType() else object_ty;
|
||||
try checkIndexable(sema, block, src, indexable_ty);
|
||||
return sema.fieldVal(block, src, object, "len", src);
|
||||
}
|
||||
|
||||
@ -3413,7 +3413,7 @@ fn indexablePtrLenOrNone(
|
||||
object: Air.Inst.Ref,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const object_ty = sema.typeOf(object);
|
||||
const array_ty = t: {
|
||||
const indexable_ty = t: {
|
||||
const ptr_size = object_ty.ptrSizeOrNull() orelse break :t object_ty;
|
||||
break :t switch (ptr_size) {
|
||||
.Many => return .none,
|
||||
@ -3421,7 +3421,7 @@ fn indexablePtrLenOrNone(
|
||||
else => object_ty,
|
||||
};
|
||||
};
|
||||
try checkIndexable(sema, block, src, array_ty);
|
||||
try checkIndexable(sema, block, src, indexable_ty);
|
||||
return sema.fieldVal(block, src, object, "len", src);
|
||||
}
|
||||
|
||||
@ -3991,7 +3991,16 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||
.input_index = i,
|
||||
} };
|
||||
const arg_len_uncoerced = if (is_int) object else l: {
|
||||
try checkIndexable(sema, block, arg_src, object_ty);
|
||||
if (!object_ty.isIndexable()) {
|
||||
// Instead of using checkIndexable we customize this error.
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.errNote(block, arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{});
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
if (!object_ty.indexableHasLen()) continue;
|
||||
|
||||
break :l try sema.fieldVal(block, arg_src, object, "len", arg_src);
|
||||
@ -24767,9 +24776,7 @@ fn elemPtr(
|
||||
.Pointer => indexable_ptr_ty.elemType(),
|
||||
else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}),
|
||||
};
|
||||
if (!indexable_ty.isIndexable()) {
|
||||
return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)});
|
||||
}
|
||||
try checkIndexable(sema, block, src, indexable_ty);
|
||||
|
||||
switch (indexable_ty.zigTypeTag()) {
|
||||
.Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),
|
||||
@ -24801,9 +24808,7 @@ fn elemPtrOneLayerOnly(
|
||||
const indexable_ty = sema.typeOf(indexable);
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
if (!indexable_ty.isIndexable()) {
|
||||
return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)});
|
||||
}
|
||||
try checkIndexable(sema, block, src, indexable_ty);
|
||||
|
||||
switch (indexable_ty.ptrSize()) {
|
||||
.Slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
|
||||
@ -24824,7 +24829,7 @@ fn elemPtrOneLayerOnly(
|
||||
return block.addPtrElemPtr(indexable, elem_index, result_ty);
|
||||
},
|
||||
.One => {
|
||||
assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable
|
||||
assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable
|
||||
return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety);
|
||||
},
|
||||
}
|
||||
@ -24843,9 +24848,7 @@ fn elemVal(
|
||||
const indexable_ty = sema.typeOf(indexable);
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
if (!indexable_ty.isIndexable()) {
|
||||
return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)});
|
||||
}
|
||||
try checkIndexable(sema, block, src, indexable_ty);
|
||||
|
||||
// TODO in case of a vector of pointers, we need to detect whether the element
|
||||
// index is a scalar or vector instead of unconditionally casting to usize.
|
||||
@ -24873,7 +24876,7 @@ fn elemVal(
|
||||
return block.addBinOp(.ptr_elem_val, indexable, elem_index);
|
||||
},
|
||||
.One => {
|
||||
assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable
|
||||
assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable
|
||||
const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);
|
||||
return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
|
||||
},
|
||||
@ -30997,23 +31000,12 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_
|
||||
}
|
||||
}
|
||||
|
||||
fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, array_ty: Type) !void {
|
||||
if (!array_ty.isIndexable()) {
|
||||
fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
|
||||
if (!ty.isIndexable()) {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(
|
||||
block,
|
||||
src,
|
||||
"type '{}' does not support indexing",
|
||||
.{array_ty.fmt(sema.mod)},
|
||||
);
|
||||
const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.errNote(
|
||||
block,
|
||||
src,
|
||||
msg,
|
||||
"for loop operand must be an array, slice, tuple, or vector",
|
||||
.{},
|
||||
);
|
||||
try sema.errNote(block, src, msg, "operand must be an array, slice, tuple, or vector", .{});
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
export fn f() void {
|
||||
var bad : bool = undefined;
|
||||
var bad: bool = undefined;
|
||||
bad[0] = bad[0];
|
||||
}
|
||||
export fn g() void {
|
||||
var bad : bool = undefined;
|
||||
var bad: bool = undefined;
|
||||
_ = bad[0];
|
||||
}
|
||||
|
||||
@ -11,5 +11,7 @@ export fn g() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:8: error: element access of non-indexable type 'bool'
|
||||
// :7:12: error: element access of non-indexable type 'bool'
|
||||
// :3:8: error: type 'bool' does not support indexing
|
||||
// :3:8: note: operand must be an array, slice, tuple, or vector
|
||||
// :7:12: error: type 'bool' does not support indexing
|
||||
// :7:12: note: operand must be an array, slice, tuple, or vector
|
||||
|
||||
@ -7,4 +7,5 @@ export fn foo() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:14: error: element access of non-indexable type 'type'
|
||||
// :2:14: error: type 'type' does not support indexing
|
||||
// :2:14: note: operand must be an array, slice, tuple, or vector
|
||||
|
||||
@ -31,8 +31,8 @@ export fn d() void {
|
||||
// :2:5: error: non-matching for loop lengths
|
||||
// :2:11: note: length 10 here
|
||||
// :2:19: note: length 11 here
|
||||
// :9:14: error: type 'bool' does not support indexing
|
||||
// :9:14: note: for loop operand must be an array, slice, tuple, or vector
|
||||
// :9:14: error: type 'bool' is not indexable and not a range
|
||||
// :9:14: note: for loop operand must be a range, array, slice, tuple, or vector
|
||||
// :15:16: error: pointer capture of non pointer type '[10]u8'
|
||||
// :15:10: note: consider using '&' here
|
||||
// :22:5: error: unbounded for loop
|
||||
|
||||
@ -28,9 +28,9 @@ pub export fn non_matching_lengths() void {
|
||||
// :5:18: note: destination type '[*]u8' provides no length
|
||||
// :5:24: note: source type '[*]align(4) const u8' provides no length
|
||||
// :10:13: error: type 'u8' does not support indexing
|
||||
// :10:13: note: for loop operand must be an array, slice, tuple, or vector
|
||||
// :10:13: note: operand must be an array, slice, tuple, or vector
|
||||
// :15:13: error: type '*u8' does not support indexing
|
||||
// :15:13: note: for loop operand must be an array, slice, tuple, or vector
|
||||
// :15:13: note: operand must be an array, slice, tuple, or vector
|
||||
// :20:5: error: non-matching @memcpy lengths
|
||||
// :20:13: note: length 6 here
|
||||
// :20:20: note: length 5 here
|
||||
|
||||
@ -8,4 +8,5 @@ export fn a() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :4:6: error: element access of non-indexable type 'tmp.a.S'
|
||||
// :4:6: error: type 'tmp.a.S' does not support indexing
|
||||
// :4:6: note: operand must be an array, slice, tuple, or vector
|
||||
|
||||
@ -6,4 +6,5 @@ export fn entry(ptr: *i32) i32 {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:15: error: element access of non-indexable type '*i32'
|
||||
// :2:15: error: type '*i32' does not support indexing
|
||||
// :2:15: note: operand must be an array, slice, tuple, or vector
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user