| ... | @@ -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 | } |
| 3408 | | 3408 | |
| ... | @@ -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 | } |
| 3427 | | 3427 | |
| ... | @@ -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; |
| 3996 | | 4005 | |
| 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 | } | | |
| 24773 | | 24780 | |
| 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(); |
| 24803 | | 24810 | |
| 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 | } | | |
| 24807 | | 24812 | |
| 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 isIndexable | 24832 | 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(); |
| 24845 | | 24850 | |
| 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 | } | | |
| 24849 | | 24852 | |
| 24850 | // TODO in case of a vector of pointers, we need to detect whether the element | 24853 | // 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 isIndexable | 24879 | 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 | } |
| 30999 | | 31002 | |
| 31000 | fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, array_ty: Type) !void { | 31003 | fn 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); |