| ... | @@ -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); |
| ... | @@ -19910,7 +19919,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -19910,7 +19919,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19910 | return sema.failWithUseOfUndef(block, operand_src); | 19919 | return sema.failWithUseOfUndef(block, operand_src); |
| 19911 | } | 19920 | } |
| 19912 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { | 19921 | if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { |
| 19913 | return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); | 19922 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)}); |
| 19914 | } | 19923 | } |
| 19915 | if (dest_ty.zigTypeTag() == .Optional and sema.typeOf(ptr).zigTypeTag() != .Optional) { | 19924 | if (dest_ty.zigTypeTag() == .Optional and sema.typeOf(ptr).zigTypeTag() != .Optional) { |
| 19916 | return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val)); | 19925 | return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val)); |
| ... | @@ -22013,10 +22022,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22013,10 +22022,10 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22013 | const msg = msg: { | 22022 | const msg = msg: { |
| 22014 | const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); | 22023 | const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); |
| 22015 | errdefer msg.destroy(sema.gpa); | 22024 | errdefer msg.destroy(sema.gpa); |
| 22016 | try sema.errNote(block, dest_src, msg, "destination type {} provides no length", .{ | 22025 | try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ |
| 22017 | sema.typeOf(dest_ptr).fmt(sema.mod), | 22026 | sema.typeOf(dest_ptr).fmt(sema.mod), |
| 22018 | }); | 22027 | }); |
| 22019 | try sema.errNote(block, src_src, msg, "source type {} provides no length", .{ | 22028 | try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{ |
| 22020 | sema.typeOf(src_ptr).fmt(sema.mod), | 22029 | sema.typeOf(src_ptr).fmt(sema.mod), |
| 22021 | }); | 22030 | }); |
| 22022 | break :msg msg; | 22031 | break :msg msg; |
| ... | @@ -22746,7 +22755,7 @@ fn resolveExternOptions( | ... | @@ -22746,7 +22755,7 @@ fn resolveExternOptions( |
| 22746 | const payload = library_name_val.castTag(.opt_payload).?.data; | 22755 | const payload = library_name_val.castTag(.opt_payload).?.data; |
| 22747 | const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod); | 22756 | const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod); |
| 22748 | if (library_name.len == 0) { | 22757 | if (library_name.len == 0) { |
| 22749 | return sema.fail(block, library_src, "library name name cannot be empty", .{}); | 22758 | return sema.fail(block, library_src, "library name cannot be empty", .{}); |
| 22750 | } | 22759 | } |
| 22751 | break :blk try sema.handleExternLibName(block, library_src, library_name); | 22760 | break :blk try sema.handleExternLibName(block, library_src, library_name); |
| 22752 | } else null; | 22761 | } else null; |
| ... | @@ -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); |