authorgravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2023-04-29 17:07:54+02:00
committergravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2023-05-06 09:32:34+02:00
log3485a0e7fbff913e6c934fbc843a02ac08f024f2
treeb1565b93bd8d6ea9a47e734204faa309fdc3f597
parent743976ef48f5efa89ada76dc5b8cea08a4626035

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.

7 files changed, 39 insertions(+), 42 deletions(-)

src/Sema.zig+23-31
...@@ -3401,8 +3401,8 @@ fn indexablePtrLen(...@@ -3401,8 +3401,8 @@ fn indexablePtrLen(
3401) CompileError!Air.Inst.Ref {3401) CompileError!Air.Inst.Ref {
3402 const object_ty = sema.typeOf(object);3402 const object_ty = sema.typeOf(object);
3403 const is_pointer_to = object_ty.isSinglePointer();3403 const is_pointer_to = object_ty.isSinglePointer();
3404 const array_ty = if (is_pointer_to) object_ty.childType() else object_ty;3404 const indexable_ty = if (is_pointer_to) object_ty.childType() else object_ty;
3405 try checkIndexable(sema, block, src, array_ty);3405 try checkIndexable(sema, block, src, indexable_ty);
3406 return sema.fieldVal(block, src, object, "len", src);3406 return sema.fieldVal(block, src, object, "len", src);
3407}3407}
34083408
...@@ -3413,7 +3413,7 @@ fn indexablePtrLenOrNone(...@@ -3413,7 +3413,7 @@ fn indexablePtrLenOrNone(
3413 object: Air.Inst.Ref,3413 object: Air.Inst.Ref,
3414) CompileError!Air.Inst.Ref {3414) CompileError!Air.Inst.Ref {
3415 const object_ty = sema.typeOf(object);3415 const object_ty = sema.typeOf(object);
3416 const array_ty = t: {3416 const indexable_ty = t: {
3417 const ptr_size = object_ty.ptrSizeOrNull() orelse break :t object_ty;3417 const ptr_size = object_ty.ptrSizeOrNull() orelse break :t object_ty;
3418 break :t switch (ptr_size) {3418 break :t switch (ptr_size) {
3419 .Many => return .none,3419 .Many => return .none,
...@@ -3421,7 +3421,7 @@ fn indexablePtrLenOrNone(...@@ -3421,7 +3421,7 @@ fn indexablePtrLenOrNone(
3421 else => object_ty,3421 else => object_ty,
3422 };3422 };
3423 };3423 };
3424 try checkIndexable(sema, block, src, array_ty);3424 try checkIndexable(sema, block, src, indexable_ty);
3425 return sema.fieldVal(block, src, object, "len", src);3425 return sema.fieldVal(block, src, object, "len", src);
3426}3426}
34273427
...@@ -3991,7 +3991,16 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -3991,7 +3991,16 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
3991 .input_index = i,3991 .input_index = i,
3992 } };3992 } };
3993 const arg_len_uncoerced = if (is_int) object else l: {3993 const arg_len_uncoerced = if (is_int) object else l: {
3994 try checkIndexable(sema, block, arg_src, object_ty);3994 if (!object_ty.isIndexable()) {
3995 // Instead of using checkIndexable we customize this error.
3996 const msg = msg: {
3997 const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)});
3998 errdefer msg.destroy(sema.gpa);
3999 try sema.errNote(block, arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{});
4000 break :msg msg;
4001 };
4002 return sema.failWithOwnedErrorMsg(msg);
4003 }
3995 if (!object_ty.indexableHasLen()) continue;4004 if (!object_ty.indexableHasLen()) continue;
39964005
3997 break :l try sema.fieldVal(block, arg_src, object, "len", arg_src);4006 break :l try sema.fieldVal(block, arg_src, object, "len", arg_src);
...@@ -24767,9 +24776,7 @@ fn elemPtr(...@@ -24767,9 +24776,7 @@ fn elemPtr(
24767 .Pointer => indexable_ptr_ty.elemType(),24776 .Pointer => indexable_ptr_ty.elemType(),
24768 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}),24777 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}),
24769 };24778 };
24770 if (!indexable_ty.isIndexable()) {24779 try checkIndexable(sema, block, src, indexable_ty);
24771 return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)});
24772 }
2477324780
24774 switch (indexable_ty.zigTypeTag()) {24781 switch (indexable_ty.zigTypeTag()) {
24775 .Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),24782 .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(...@@ -24801,9 +24808,7 @@ fn elemPtrOneLayerOnly(
24801 const indexable_ty = sema.typeOf(indexable);24808 const indexable_ty = sema.typeOf(indexable);
24802 const target = sema.mod.getTarget();24809 const target = sema.mod.getTarget();
2480324810
24804 if (!indexable_ty.isIndexable()) {24811 try checkIndexable(sema, block, src, indexable_ty);
24805 return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)});
24806 }
2480724812
24808 switch (indexable_ty.ptrSize()) {24813 switch (indexable_ty.ptrSize()) {
24809 .Slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),24814 .Slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
...@@ -24824,7 +24829,7 @@ fn elemPtrOneLayerOnly(...@@ -24824,7 +24829,7 @@ fn elemPtrOneLayerOnly(
24824 return block.addPtrElemPtr(indexable, elem_index, result_ty);24829 return block.addPtrElemPtr(indexable, elem_index, result_ty);
24825 },24830 },
24826 .One => {24831 .One => {
24827 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable24832 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable
24828 return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety);24833 return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety);
24829 },24834 },
24830 }24835 }
...@@ -24843,9 +24848,7 @@ fn elemVal(...@@ -24843,9 +24848,7 @@ fn elemVal(
24843 const indexable_ty = sema.typeOf(indexable);24848 const indexable_ty = sema.typeOf(indexable);
24844 const target = sema.mod.getTarget();24849 const target = sema.mod.getTarget();
2484524850
24846 if (!indexable_ty.isIndexable()) {24851 try checkIndexable(sema, block, src, indexable_ty);
24847 return sema.fail(block, src, "element access of non-indexable type '{}'", .{indexable_ty.fmt(sema.mod)});
24848 }
2484924852
24850 // TODO in case of a vector of pointers, we need to detect whether the element24853 // TODO in case of a vector of pointers, we need to detect whether the element
24851 // index is a scalar or vector instead of unconditionally casting to usize.24854 // index is a scalar or vector instead of unconditionally casting to usize.
...@@ -24873,7 +24876,7 @@ fn elemVal(...@@ -24873,7 +24876,7 @@ fn elemVal(
24873 return block.addBinOp(.ptr_elem_val, indexable, elem_index);24876 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
24874 },24877 },
24875 .One => {24878 .One => {
24876 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable24879 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable
24877 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);24880 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);
24878 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);24881 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
24879 },24882 },
...@@ -30997,23 +31000,12 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_...@@ -30997,23 +31000,12 @@ fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_
30997 }31000 }
30998}31001}
3099931002
31000fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, array_ty: Type) !void {31003fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31001 if (!array_ty.isIndexable()) {31004 if (!ty.isIndexable()) {
31002 const msg = msg: {31005 const msg = msg: {
31003 const msg = try sema.errMsg(31006 const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)});
31004 block,
31005 src,
31006 "type '{}' does not support indexing",
31007 .{array_ty.fmt(sema.mod)},
31008 );
31009 errdefer msg.destroy(sema.gpa);31007 errdefer msg.destroy(sema.gpa);
31010 try sema.errNote(31008 try sema.errNote(block, src, msg, "operand must be an array, slice, tuple, or vector", .{});
31011 block,
31012 src,
31013 msg,
31014 "for loop operand must be an array, slice, tuple, or vector",
31015 .{},
31016 );
31017 break :msg msg;31009 break :msg msg;
31018 };31010 };
31019 return sema.failWithOwnedErrorMsg(msg);31011 return sema.failWithOwnedErrorMsg(msg);
test/cases/compile_errors/array_access_of_non_array.zig+6-4
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1export fn f() void {1export fn f() void {
2 var bad : bool = undefined;2 var bad: bool = undefined;
3 bad[0] = bad[0];3 bad[0] = bad[0];
4}4}
5export fn g() void {5export fn g() void {
6 var bad : bool = undefined;6 var bad: bool = undefined;
7 _ = bad[0];7 _ = bad[0];
8}8}
99
...@@ -11,5 +11,7 @@ export fn g() void {...@@ -11,5 +11,7 @@ export fn g() void {
11// backend=stage211// backend=stage2
12// target=native12// target=native
13//13//
14// :3:8: error: element access of non-indexable type 'bool'14// :3:8: error: type 'bool' does not support indexing
15// :7:12: error: element access of non-indexable type 'bool'15// :3:8: note: operand must be an array, slice, tuple, or vector
16// :7:12: error: type 'bool' does not support indexing
17// :7:12: note: operand must be an array, slice, tuple, or vector
test/cases/compile_errors/array_access_of_type.zig+2-1
...@@ -7,4 +7,5 @@ export fn foo() void {...@@ -7,4 +7,5 @@ export fn foo() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :2:14: error: element access of non-indexable type 'type'10// :2:14: error: type 'type' does not support indexing
11// :2:14: note: operand must be an array, slice, tuple, or vector
test/cases/compile_errors/for.zig+2-2
...@@ -31,8 +31,8 @@ export fn d() void {...@@ -31,8 +31,8 @@ export fn d() void {
31// :2:5: error: non-matching for loop lengths31// :2:5: error: non-matching for loop lengths
32// :2:11: note: length 10 here32// :2:11: note: length 10 here
33// :2:19: note: length 11 here33// :2:19: note: length 11 here
34// :9:14: error: type 'bool' does not support indexing34// :9:14: error: type 'bool' is not indexable and not a range
35// :9:14: note: for loop operand must be an array, slice, tuple, or vector35// :9:14: note: for loop operand must be a range, array, slice, tuple, or vector
36// :15:16: error: pointer capture of non pointer type '[10]u8'36// :15:16: error: pointer capture of non pointer type '[10]u8'
37// :15:10: note: consider using '&' here37// :15:10: note: consider using '&' here
38// :22:5: error: unbounded for loop38// :22:5: error: unbounded for loop
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig+2-2
...@@ -28,9 +28,9 @@ pub export fn non_matching_lengths() void {...@@ -28,9 +28,9 @@ pub export fn non_matching_lengths() void {
28// :5:18: note: destination type '[*]u8' provides no length28// :5:18: note: destination type '[*]u8' provides no length
29// :5:24: note: source type '[*]align(4) const u8' provides no length29// :5:24: note: source type '[*]align(4) const u8' provides no length
30// :10:13: error: type 'u8' does not support indexing30// :10:13: error: type 'u8' does not support indexing
31// :10:13: note: for loop operand must be an array, slice, tuple, or vector31// :10:13: note: operand must be an array, slice, tuple, or vector
32// :15:13: error: type '*u8' does not support indexing32// :15:13: error: type '*u8' does not support indexing
33// :15:13: note: for loop operand must be an array, slice, tuple, or vector33// :15:13: note: operand must be an array, slice, tuple, or vector
34// :20:5: error: non-matching @memcpy lengths34// :20:5: error: non-matching @memcpy lengths
35// :20:13: note: length 6 here35// :20:13: note: length 6 here
36// :20:20: note: length 5 here36// :20:20: note: length 5 here
test/cases/compile_errors/indexing_non-tuple_struct.zig+2-1
...@@ -8,4 +8,5 @@ export fn a() void {...@@ -8,4 +8,5 @@ export fn a() void {
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :4:6: error: element access of non-indexable type 'tmp.a.S'11// :4:6: error: type 'tmp.a.S' does not support indexing
12// :4:6: note: operand must be an array, slice, tuple, or vector
test/cases/compile_errors/indexing_single-item_pointer.zig+2-1
...@@ -6,4 +6,5 @@ export fn entry(ptr: *i32) i32 {...@@ -6,4 +6,5 @@ export fn entry(ptr: *i32) i32 {
6// backend=stage26// backend=stage2
7// target=native7// target=native
8//8//
9// :2:15: error: element access of non-indexable type '*i32'9// :2:15: error: type '*i32' does not support indexing
10// :2:15: note: operand must be an array, slice, tuple, or vector