| ... | @@ -3416,19 +3416,12 @@ fn indexablePtrLenOrNone( | ... | @@ -3416,19 +3416,12 @@ fn indexablePtrLenOrNone( |
| 3416 | sema: *Sema, | 3416 | sema: *Sema, |
| 3417 | block: *Block, | 3417 | block: *Block, |
| 3418 | src: LazySrcLoc, | 3418 | src: LazySrcLoc, |
| 3419 | object: Air.Inst.Ref, | 3419 | operand: Air.Inst.Ref, |
| 3420 | ) CompileError!Air.Inst.Ref { | 3420 | ) CompileError!Air.Inst.Ref { |
| 3421 | const object_ty = sema.typeOf(object); | 3421 | const operand_ty = sema.typeOf(operand); |
| 3422 | const indexable_ty = t: { | 3422 | try checkMemOperand(sema, block, src, operand_ty); |
| 3423 | const ptr_size = object_ty.ptrSizeOrNull() orelse break :t object_ty; | 3423 | if (operand_ty.ptrSize() == .Many) return .none; |
| 3424 | break :t switch (ptr_size) { | 3424 | return sema.fieldVal(block, src, operand, "len", src); |
| 3425 | .Many => return .none, | | |
| 3426 | .One => object_ty.childType(), | | |
| 3427 | else => object_ty, | | |
| 3428 | }; | | |
| 3429 | }; | | |
| 3430 | try checkIndexable(sema, block, src, indexable_ty); | | |
| 3431 | return sema.fieldVal(block, src, object, "len", src); | | |
| 3432 | } | 3425 | } |
| 3433 | | 3426 | |
| 3434 | fn zirAllocExtended( | 3427 | fn zirAllocExtended( |
| ... | @@ -22080,19 +22073,25 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22080,19 +22073,25 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22080 | const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 22073 | const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 22081 | const dest_ptr = try sema.resolveInst(extra.lhs); | 22074 | const dest_ptr = try sema.resolveInst(extra.lhs); |
| 22082 | const src_ptr = try sema.resolveInst(extra.rhs); | 22075 | const src_ptr = try sema.resolveInst(extra.rhs); |
| | 22076 | const dest_ty = sema.typeOf(dest_ptr); |
| | 22077 | const src_ty = sema.typeOf(src_ptr); |
| 22083 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); | 22078 | const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); |
| 22084 | const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr); | 22079 | const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr); |
| 22085 | const target = sema.mod.getTarget(); | 22080 | const target = sema.mod.getTarget(); |
| 22086 | | 22081 | |
| | 22082 | if (dest_ty.isConstPtr()) { |
| | 22083 | return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{}); |
| | 22084 | } |
| | 22085 | |
| 22087 | if (dest_len == .none and src_len == .none) { | 22086 | if (dest_len == .none and src_len == .none) { |
| 22088 | const msg = msg: { | 22087 | const msg = msg: { |
| 22089 | const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); | 22088 | const msg = try sema.errMsg(block, src, "unknown @memcpy length", .{}); |
| 22090 | errdefer msg.destroy(sema.gpa); | 22089 | errdefer msg.destroy(sema.gpa); |
| 22091 | try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ | 22090 | try sema.errNote(block, dest_src, msg, "destination type '{}' provides no length", .{ |
| 22092 | sema.typeOf(dest_ptr).fmt(sema.mod), | 22091 | dest_ty.fmt(sema.mod), |
| 22093 | }); | 22092 | }); |
| 22094 | try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{ | 22093 | try sema.errNote(block, src_src, msg, "source type '{}' provides no length", .{ |
| 22095 | sema.typeOf(src_ptr).fmt(sema.mod), | 22094 | src_ty.fmt(sema.mod), |
| 22096 | }); | 22095 | }); |
| 22097 | break :msg msg; | 22096 | break :msg msg; |
| 22098 | }; | 22097 | }; |
| ... | @@ -22180,9 +22179,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22180,9 +22179,6 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22180 | } else break :rs src_src; | 22179 | } else break :rs src_src; |
| 22181 | } else dest_src; | 22180 | } else dest_src; |
| 22182 | | 22181 | |
| 22183 | const dest_ty = sema.typeOf(dest_ptr); | | |
| 22184 | const src_ty = sema.typeOf(src_ptr); | | |
| 22185 | | | |
| 22186 | // If in-memory coercion is not allowed, explode this memcpy call into a | 22182 | // If in-memory coercion is not allowed, explode this memcpy call into a |
| 22187 | // for loop that copies element-wise. | 22183 | // for loop that copies element-wise. |
| 22188 | // Likewise if this is an iterable rather than a pointer, do the same | 22184 | // Likewise if this is an iterable rather than a pointer, do the same |
| ... | @@ -22274,7 +22270,11 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -22274,7 +22270,11 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 22274 | const dest_ptr = try sema.resolveInst(extra.lhs); | 22270 | const dest_ptr = try sema.resolveInst(extra.lhs); |
| 22275 | const uncoerced_elem = try sema.resolveInst(extra.rhs); | 22271 | const uncoerced_elem = try sema.resolveInst(extra.rhs); |
| 22276 | const dest_ptr_ty = sema.typeOf(dest_ptr); | 22272 | const dest_ptr_ty = sema.typeOf(dest_ptr); |
| 22277 | try checkIndexable(sema, block, dest_src, dest_ptr_ty); | 22273 | try checkMemOperand(sema, block, dest_src, dest_ptr_ty); |
| | 22274 | |
| | 22275 | if (dest_ptr_ty.isConstPtr()) { |
| | 22276 | return sema.fail(block, dest_src, "cannot memset constant pointer", .{}); |
| | 22277 | } |
| 22278 | | 22278 | |
| 22279 | const dest_elem_ty = dest_ptr_ty.elemType2(); | 22279 | const dest_elem_ty = dest_ptr_ty.elemType2(); |
| 22280 | const target = sema.mod.getTarget(); | 22280 | const target = sema.mod.getTarget(); |
| ... | @@ -31102,6 +31102,27 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { | ... | @@ -31102,6 +31102,27 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| 31102 | } | 31102 | } |
| 31103 | } | 31103 | } |
| 31104 | | 31104 | |
| | 31105 | fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { |
| | 31106 | if (ty.zigTypeTag() == .Pointer) { |
| | 31107 | switch (ty.ptrSize()) { |
| | 31108 | .Slice, .Many, .C => return, |
| | 31109 | .One => { |
| | 31110 | const elem_ty = ty.childType(); |
| | 31111 | if (elem_ty.zigTypeTag() == .Array) return; |
| | 31112 | // TODO https://github.com/ziglang/zig/issues/15479 |
| | 31113 | // if (elem_ty.isTuple()) return; |
| | 31114 | }, |
| | 31115 | } |
| | 31116 | } |
| | 31117 | const msg = msg: { |
| | 31118 | const msg = try sema.errMsg(block, src, "type '{}' is not an indexable pointer", .{ty.fmt(sema.mod)}); |
| | 31119 | errdefer msg.destroy(sema.gpa); |
| | 31120 | try sema.errNote(block, src, msg, "operand must be a slice, a many pointer or a pointer to an array", .{}); |
| | 31121 | break :msg msg; |
| | 31122 | }; |
| | 31123 | return sema.failWithOwnedErrorMsg(msg); |
| | 31124 | } |
| | 31125 | |
| 31105 | fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | 31126 | fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31106 | const resolved_ty = try sema.resolveTypeFields(ty); | 31127 | const resolved_ty = try sema.resolveTypeFields(ty); |
| 31107 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; | 31128 | const union_obj = resolved_ty.cast(Type.Payload.Union).?.data; |