| ... | ... | @@ -504,7 +504,17 @@ pub const Block = struct { |
| 504 | 504 | }; |
| 505 | 505 | } |
| 506 | 506 | |
| 507 | | pub fn wantSafety(block: *const Block) bool { |
| 507 | fn wantSafeTypes(block: *const Block) bool { |
| 508 | return block.want_safety orelse switch (block.sema.pt.zcu.optimizeMode()) { |
| 509 | .Debug => true, |
| 510 | .ReleaseSafe => true, |
| 511 | .ReleaseFast => false, |
| 512 | .ReleaseSmall => false, |
| 513 | }; |
| 514 | } |
| 515 | |
| 516 | fn wantSafety(block: *const Block) bool { |
| 517 | if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks |
| 508 | 518 | return block.want_safety orelse switch (block.sema.pt.zcu.optimizeMode()) { |
| 509 | 519 | .Debug => true, |
| 510 | 520 | .ReleaseSafe => true, |
| ... | ... | @@ -1197,6 +1207,7 @@ fn analyzeBodyInner( |
| 1197 | 1207 | .slice_sentinel => try sema.zirSliceSentinel(block, inst), |
| 1198 | 1208 | .slice_start => try sema.zirSliceStart(block, inst), |
| 1199 | 1209 | .slice_length => try sema.zirSliceLength(block, inst), |
| 1210 | .slice_sentinel_ty => try sema.zirSliceSentinelTy(block, inst), |
| 1200 | 1211 | .str => try sema.zirStr(inst), |
| 1201 | 1212 | .switch_block => try sema.zirSwitchBlock(block, inst, false), |
| 1202 | 1213 | .switch_block_ref => try sema.zirSwitchBlock(block, inst, true), |
| ... | ... | @@ -3293,7 +3304,7 @@ fn zirUnionDecl( |
| 3293 | 3304 | .tagged |
| 3294 | 3305 | else if (small.layout != .auto) |
| 3295 | 3306 | .none |
| 3296 | | else switch (block.wantSafety()) { |
| 3307 | else switch (block.wantSafeTypes()) { |
| 3297 | 3308 | true => .safety, |
| 3298 | 3309 | false => .none, |
| 3299 | 3310 | }, |
| ... | ... | @@ -9144,6 +9155,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 9144 | 9155 | return sema.analyzeErrUnionCode(block, src, operand); |
| 9145 | 9156 | } |
| 9146 | 9157 | |
| 9158 | /// If `operand` is comptime-known, asserts that it is an error value rather than a payload value. |
| 9147 | 9159 | fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref { |
| 9148 | 9160 | const pt = sema.pt; |
| 9149 | 9161 | const zcu = pt.zcu; |
| ... | ... | @@ -10753,6 +10765,46 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10753 | 10765 | return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true); |
| 10754 | 10766 | } |
| 10755 | 10767 | |
| 10768 | fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 10769 | const tracy = trace(@src()); |
| 10770 | defer tracy.end(); |
| 10771 | |
| 10772 | const pt = sema.pt; |
| 10773 | const zcu = pt.zcu; |
| 10774 | |
| 10775 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 10776 | |
| 10777 | const src = block.nodeOffset(inst_data.src_node); |
| 10778 | const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); |
| 10779 | const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); |
| 10780 | |
| 10781 | // This is like the logic in `analyzeSlice`; since we've evaluated the LHS as an lvalue, we will |
| 10782 | // have a double pointer if it was already a pointer. |
| 10783 | |
| 10784 | const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand)); |
| 10785 | const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) { |
| 10786 | .pointer => lhs_ptr_ty.childType(zcu), |
| 10787 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{lhs_ptr_ty.fmt(pt)}), |
| 10788 | }; |
| 10789 | |
| 10790 | const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { |
| 10791 | .array => lhs_ty.childType(zcu), |
| 10792 | .pointer => switch (lhs_ty.ptrSize(zcu)) { |
| 10793 | .many, .c, .slice => lhs_ty.childType(zcu), |
| 10794 | .one => s: { |
| 10795 | const lhs_elem_ty = lhs_ty.childType(zcu); |
| 10796 | break :s switch (lhs_elem_ty.zigTypeTag(zcu)) { |
| 10797 | .array => lhs_elem_ty.childType(zcu), // array element type |
| 10798 | else => return sema.fail(block, sentinel_src, "slice of single-item pointer cannot have sentinel", .{}), |
| 10799 | }; |
| 10800 | }, |
| 10801 | }, |
| 10802 | else => return sema.fail(block, src, "slice of non-array type '{}'", .{lhs_ty.fmt(pt)}), |
| 10803 | }; |
| 10804 | |
| 10805 | return Air.internedToRef(sentinel_ty.toIntern()); |
| 10806 | } |
| 10807 | |
| 10756 | 10808 | /// Holds common data used when analyzing or resolving switch prong bodies, |
| 10757 | 10809 | /// including setting up captures. |
| 10758 | 10810 | const SwitchProngAnalysis = struct { |
| ... | ... | @@ -17558,10 +17610,16 @@ fn analyzeCmp( |
| 17558 | 17610 | return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src); |
| 17559 | 17611 | } |
| 17560 | 17612 | if (is_equality_cmp and lhs_ty.zigTypeTag(zcu) == .error_union and rhs_ty.zigTypeTag(zcu) == .error_set) { |
| 17613 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| 17614 | if (lhs_val.errorUnionIsPayload(zcu)) return .bool_false; |
| 17615 | } |
| 17561 | 17616 | const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs); |
| 17562 | 17617 | return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src); |
| 17563 | 17618 | } |
| 17564 | 17619 | if (is_equality_cmp and lhs_ty.zigTypeTag(zcu) == .error_set and rhs_ty.zigTypeTag(zcu) == .error_union) { |
| 17620 | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { |
| 17621 | if (rhs_val.errorUnionIsPayload(zcu)) return .bool_false; |
| 17622 | } |
| 17565 | 17623 | const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs); |
| 17566 | 17624 | return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src); |
| 17567 | 17625 | } |
| ... | ... | @@ -18087,10 +18145,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18087 | 18145 | |
| 18088 | 18146 | const ret_ty_opt = try pt.intern(.{ .opt = .{ |
| 18089 | 18147 | .ty = try pt.intern(.{ .opt_type = .type_type }), |
| 18090 | | .val = if (func_ty_info.return_type == .generic_poison_type) |
| 18091 | | .none |
| 18092 | | else |
| 18093 | | func_ty_info.return_type, |
| 18148 | .val = opt_val: { |
| 18149 | const ret_ty: Type = .fromInterned(func_ty_info.return_type); |
| 18150 | if (ret_ty.toIntern() == .generic_poison_type) break :opt_val .none; |
| 18151 | if (ret_ty.zigTypeTag(zcu) == .error_union) { |
| 18152 | if (ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) { |
| 18153 | break :opt_val .none; |
| 18154 | } |
| 18155 | } |
| 18156 | break :opt_val ret_ty.toIntern(); |
| 18157 | }, |
| 18094 | 18158 | } }); |
| 18095 | 18159 | |
| 18096 | 18160 | const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); |
| ... | ... | @@ -21401,7 +21465,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 21401 | 21465 | try operand_ty.resolveLayout(pt); |
| 21402 | 21466 | const enum_ty = switch (operand_ty.zigTypeTag(zcu)) { |
| 21403 | 21467 | .enum_literal => { |
| 21404 | | const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, operand, undefined); |
| 21468 | const val = (try sema.resolveDefinedValue(block, operand_src, operand)).?; |
| 21405 | 21469 | const tag_name = ip.indexToKey(val.toIntern()).enum_literal; |
| 21406 | 21470 | return sema.addNullTerminatedStrLit(tag_name); |
| 21407 | 21471 | }, |
| ... | ... | @@ -22171,7 +22235,7 @@ fn reifyUnion( |
| 22171 | 22235 | .tagged |
| 22172 | 22236 | else if (layout != .auto) |
| 22173 | 22237 | .none |
| 22174 | | else switch (block.wantSafety()) { |
| 22238 | else switch (block.wantSafeTypes()) { |
| 22175 | 22239 | true => .safety, |
| 22176 | 22240 | false => .none, |
| 22177 | 22241 | }, |
| ... | ... | @@ -23117,11 +23181,12 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 23117 | 23181 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 23118 | 23182 | const src = block.nodeOffset(extra.node); |
| 23119 | 23183 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 23120 | | const base_dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt, "@errorCast"); |
| 23184 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt, "@errorCast"); |
| 23121 | 23185 | const operand = try sema.resolveInst(extra.rhs); |
| 23122 | | const base_operand_ty = sema.typeOf(operand); |
| 23123 | | const dest_tag = base_dest_ty.zigTypeTag(zcu); |
| 23124 | | const operand_tag = base_operand_ty.zigTypeTag(zcu); |
| 23186 | const operand_ty = sema.typeOf(operand); |
| 23187 | |
| 23188 | const dest_tag = dest_ty.zigTypeTag(zcu); |
| 23189 | const operand_tag = operand_ty.zigTypeTag(zcu); |
| 23125 | 23190 | |
| 23126 | 23191 | if (dest_tag != .error_set and dest_tag != .error_union) { |
| 23127 | 23192 | return sema.fail(block, src, "expected error set or error union type, found '{s}'", .{@tagName(dest_tag)}); |
| ... | ... | @@ -23133,107 +23198,133 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 23133 | 23198 | return sema.fail(block, src, "cannot cast an error union type to error set", .{}); |
| 23134 | 23199 | } |
| 23135 | 23200 | if (dest_tag == .error_union and operand_tag == .error_union and |
| 23136 | | base_dest_ty.errorUnionPayload(zcu).toIntern() != base_operand_ty.errorUnionPayload(zcu).toIntern()) |
| 23201 | dest_ty.errorUnionPayload(zcu).toIntern() != operand_ty.errorUnionPayload(zcu).toIntern()) |
| 23137 | 23202 | { |
| 23138 | 23203 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 23139 | 23204 | const msg = try sema.errMsg(src, "payload types of error unions must match", .{}); |
| 23140 | 23205 | errdefer msg.destroy(sema.gpa); |
| 23141 | | const dest_ty = base_dest_ty.errorUnionPayload(zcu); |
| 23142 | | const operand_ty = base_operand_ty.errorUnionPayload(zcu); |
| 23143 | | try sema.errNote(src, msg, "destination payload is '{}'", .{dest_ty.fmt(pt)}); |
| 23144 | | try sema.errNote(src, msg, "operand payload is '{}'", .{operand_ty.fmt(pt)}); |
| 23206 | const dest_payload_ty = dest_ty.errorUnionPayload(zcu); |
| 23207 | const operand_payload_ty = operand_ty.errorUnionPayload(zcu); |
| 23208 | try sema.errNote(src, msg, "destination payload is '{}'", .{dest_payload_ty.fmt(pt)}); |
| 23209 | try sema.errNote(src, msg, "operand payload is '{}'", .{operand_payload_ty.fmt(pt)}); |
| 23145 | 23210 | try addDeclaredHereNote(sema, msg, dest_ty); |
| 23146 | 23211 | try addDeclaredHereNote(sema, msg, operand_ty); |
| 23147 | 23212 | break :msg msg; |
| 23148 | 23213 | }); |
| 23149 | 23214 | } |
| 23150 | | const dest_ty = if (dest_tag == .error_union) base_dest_ty.errorUnionSet(zcu) else base_dest_ty; |
| 23151 | | const operand_ty = if (operand_tag == .error_union) base_operand_ty.errorUnionSet(zcu) else base_operand_ty; |
| 23152 | | |
| 23153 | | // operand must be defined since it can be an invalid error value |
| 23154 | | const maybe_operand_val = try sema.resolveDefinedValue(block, operand_src, operand); |
| 23215 | const dest_err_ty = switch (dest_tag) { |
| 23216 | .error_union => dest_ty.errorUnionSet(zcu), |
| 23217 | .error_set => dest_ty, |
| 23218 | else => unreachable, |
| 23219 | }; |
| 23220 | const operand_err_ty = switch (operand_tag) { |
| 23221 | .error_union => operand_ty.errorUnionSet(zcu), |
| 23222 | .error_set => operand_ty, |
| 23223 | else => unreachable, |
| 23224 | }; |
| 23155 | 23225 | |
| 23156 | 23226 | const disjoint = disjoint: { |
| 23157 | 23227 | // Try avoiding resolving inferred error sets if we can |
| 23158 | | if (!dest_ty.isAnyError(zcu) and dest_ty.errorSetIsEmpty(zcu)) break :disjoint true; |
| 23159 | | if (!operand_ty.isAnyError(zcu) and operand_ty.errorSetIsEmpty(zcu)) break :disjoint true; |
| 23160 | | if (dest_ty.isAnyError(zcu)) break :disjoint false; |
| 23161 | | if (operand_ty.isAnyError(zcu)) break :disjoint false; |
| 23162 | | const dest_err_names = dest_ty.errorSetNames(zcu); |
| 23228 | if (!dest_err_ty.isAnyError(zcu) and dest_err_ty.errorSetIsEmpty(zcu)) break :disjoint true; |
| 23229 | if (!operand_err_ty.isAnyError(zcu) and operand_err_ty.errorSetIsEmpty(zcu)) break :disjoint true; |
| 23230 | if (dest_err_ty.isAnyError(zcu)) break :disjoint false; |
| 23231 | if (operand_err_ty.isAnyError(zcu)) break :disjoint false; |
| 23232 | const dest_err_names = dest_err_ty.errorSetNames(zcu); |
| 23163 | 23233 | for (0..dest_err_names.len) |dest_err_index| { |
| 23164 | | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) |
| 23234 | if (Type.errorSetHasFieldIp(ip, operand_err_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) |
| 23165 | 23235 | break :disjoint false; |
| 23166 | 23236 | } |
| 23167 | 23237 | |
| 23168 | | if (!ip.isInferredErrorSetType(dest_ty.toIntern()) and |
| 23169 | | !ip.isInferredErrorSetType(operand_ty.toIntern())) |
| 23238 | if (!ip.isInferredErrorSetType(dest_err_ty.toIntern()) and |
| 23239 | !ip.isInferredErrorSetType(operand_err_ty.toIntern())) |
| 23170 | 23240 | { |
| 23171 | 23241 | break :disjoint true; |
| 23172 | 23242 | } |
| 23173 | 23243 | |
| 23174 | | _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern()); |
| 23175 | | _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern()); |
| 23244 | _ = try sema.resolveInferredErrorSetTy(block, src, dest_err_ty.toIntern()); |
| 23245 | _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_err_ty.toIntern()); |
| 23176 | 23246 | for (0..dest_err_names.len) |dest_err_index| { |
| 23177 | | if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) |
| 23247 | if (Type.errorSetHasFieldIp(ip, operand_err_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) |
| 23178 | 23248 | break :disjoint false; |
| 23179 | 23249 | } |
| 23180 | 23250 | |
| 23181 | 23251 | break :disjoint true; |
| 23182 | 23252 | }; |
| 23183 | | if (disjoint and dest_tag != .error_union) { |
| 23253 | if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) { |
| 23184 | 23254 | return sema.fail(block, src, "error sets '{}' and '{}' have no common errors", .{ |
| 23185 | | operand_ty.fmt(pt), dest_ty.fmt(pt), |
| 23255 | operand_err_ty.fmt(pt), dest_err_ty.fmt(pt), |
| 23186 | 23256 | }); |
| 23187 | 23257 | } |
| 23188 | 23258 | |
| 23189 | | if (maybe_operand_val) |val| { |
| 23190 | | if (!dest_ty.isAnyError(zcu)) check: { |
| 23191 | | const operand_val = zcu.intern_pool.indexToKey(val.toIntern()); |
| 23192 | | var error_name: InternPool.NullTerminatedString = undefined; |
| 23193 | | if (operand_tag == .error_union) { |
| 23194 | | if (operand_val.error_union.val != .err_name) break :check; |
| 23195 | | error_name = operand_val.error_union.val.err_name; |
| 23196 | | } else { |
| 23197 | | error_name = operand_val.err.name; |
| 23198 | | } |
| 23199 | | if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) { |
| 23200 | | return sema.fail(block, src, "'error.{}' not a member of error set '{}'", .{ |
| 23201 | | error_name.fmt(ip), dest_ty.fmt(pt), |
| 23202 | | }); |
| 23203 | | } |
| 23259 | // operand must be defined since it can be an invalid error value |
| 23260 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| { |
| 23261 | const err_name: InternPool.NullTerminatedString = switch (operand_tag) { |
| 23262 | .error_set => ip.indexToKey(operand_val.toIntern()).err.name, |
| 23263 | .error_union => switch (ip.indexToKey(operand_val.toIntern()).error_union.val) { |
| 23264 | .err_name => |name| name, |
| 23265 | .payload => |payload_val| { |
| 23266 | assert(dest_tag == .error_union); // should be guaranteed from the type checks above |
| 23267 | return sema.coerce(block, dest_ty, Air.internedToRef(payload_val), operand_src); |
| 23268 | }, |
| 23269 | }, |
| 23270 | else => unreachable, |
| 23271 | }; |
| 23272 | |
| 23273 | if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) { |
| 23274 | return sema.fail(block, src, "'error.{}' not a member of error set '{}'", .{ |
| 23275 | err_name.fmt(ip), dest_err_ty.fmt(pt), |
| 23276 | }); |
| 23204 | 23277 | } |
| 23205 | 23278 | |
| 23206 | | return Air.internedToRef((try pt.getCoerced(val, base_dest_ty)).toIntern()); |
| 23279 | return Air.internedToRef(try pt.intern(switch (dest_tag) { |
| 23280 | .error_set => .{ .err = .{ |
| 23281 | .ty = dest_ty.toIntern(), |
| 23282 | .name = err_name, |
| 23283 | } }, |
| 23284 | .error_union => .{ .error_union = .{ |
| 23285 | .ty = dest_ty.toIntern(), |
| 23286 | .val = .{ .err_name = err_name }, |
| 23287 | } }, |
| 23288 | else => unreachable, |
| 23289 | })); |
| 23207 | 23290 | } |
| 23208 | 23291 | |
| 23209 | | try sema.requireRuntimeBlock(block, src, operand_src); |
| 23210 | 23292 | const err_int_ty = try pt.errorIntType(); |
| 23211 | | if (block.wantSafety() and !dest_ty.isAnyError(zcu) and |
| 23212 | | dest_ty.toIntern() != .adhoc_inferred_error_set_type and |
| 23293 | if (block.wantSafety() and !dest_err_ty.isAnyError(zcu) and |
| 23294 | dest_err_ty.toIntern() != .adhoc_inferred_error_set_type and |
| 23213 | 23295 | zcu.backendSupportsFeature(.error_set_has_value)) |
| 23214 | 23296 | { |
| 23215 | | if (dest_tag == .error_union) { |
| 23216 | | const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand); |
| 23217 | | const err_int = try block.addBitCast(err_int_ty, err_code); |
| 23218 | | const zero_err = try pt.intRef(try pt.errorIntType(), 0); |
| 23297 | const err_code_inst = switch (operand_tag) { |
| 23298 | .error_set => operand, |
| 23299 | .error_union => try block.addTyOp(.unwrap_errunion_err, operand_err_ty, operand), |
| 23300 | else => unreachable, |
| 23301 | }; |
| 23302 | const err_int_inst = try block.addBitCast(err_int_ty, err_code_inst); |
| 23219 | 23303 | |
| 23220 | | const is_zero = try block.addBinOp(.cmp_eq, err_int, zero_err); |
| 23304 | if (dest_tag == .error_union) { |
| 23305 | const zero_err = try pt.intRef(err_int_ty, 0); |
| 23306 | const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err); |
| 23221 | 23307 | if (disjoint) { |
| 23222 | 23308 | // Error must be zero. |
| 23223 | 23309 | try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code); |
| 23224 | 23310 | } else { |
| 23225 | 23311 | // Error must be in destination set or zero. |
| 23226 | | const has_value = try block.addTyOp(.error_set_has_value, dest_ty, err_code); |
| 23312 | const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst); |
| 23227 | 23313 | const ok = try block.addBinOp(.bool_or, has_value, is_zero); |
| 23228 | 23314 | try sema.addSafetyCheck(block, src, ok, .invalid_error_code); |
| 23229 | 23315 | } |
| 23230 | 23316 | } else { |
| 23231 | | const err_int_inst = try block.addBitCast(err_int_ty, operand); |
| 23232 | | const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst); |
| 23317 | const ok = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst); |
| 23233 | 23318 | try sema.addSafetyCheck(block, src, ok, .invalid_error_code); |
| 23234 | 23319 | } |
| 23235 | 23320 | } |
| 23236 | | return block.addBitCast(base_dest_ty, operand); |
| 23321 | |
| 23322 | if (operand_tag == .error_set and dest_tag == .error_union) { |
| 23323 | const err_val = try block.addBitCast(dest_err_ty, operand); |
| 23324 | return block.addTyOp(.wrap_errunion_err, dest_ty, err_val); |
| 23325 | } else { |
| 23326 | return block.addBitCast(dest_ty, operand); |
| 23327 | } |
| 23237 | 23328 | } |
| 23238 | 23329 | |
| 23239 | 23330 | fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -28952,6 +29043,7 @@ fn elemValArray( |
| 28952 | 29043 | } |
| 28953 | 29044 | |
| 28954 | 29045 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src); |
| 29046 | try sema.validateRuntimeValue(block, array_src, array); |
| 28955 | 29047 | |
| 28956 | 29048 | if (oob_safety and block.wantSafety()) { |
| 28957 | 29049 | // Runtime check is only needed if unable to comptime check. |
| ... | ... | @@ -29016,6 +29108,7 @@ fn elemPtrArray( |
| 29016 | 29108 | |
| 29017 | 29109 | if (!init) { |
| 29018 | 29110 | try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(zcu), array_ty, array_ptr_src); |
| 29111 | try sema.validateRuntimeValue(block, array_ptr_src, array_ptr); |
| 29019 | 29112 | } |
| 29020 | 29113 | |
| 29021 | 29114 | // Runtime check is only needed if unable to comptime check. |
| ... | ... | @@ -29073,6 +29166,7 @@ fn elemValSlice( |
| 29073 | 29166 | } |
| 29074 | 29167 | |
| 29075 | 29168 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src); |
| 29169 | try sema.validateRuntimeValue(block, slice_src, slice); |
| 29076 | 29170 | |
| 29077 | 29171 | if (oob_safety and block.wantSafety()) { |
| 29078 | 29172 | const len_inst = if (maybe_slice_val) |slice_val| |
| ... | ... | @@ -29129,6 +29223,7 @@ fn elemPtrSlice( |
| 29129 | 29223 | } |
| 29130 | 29224 | |
| 29131 | 29225 | try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ptr_ty, slice_ty, slice_src); |
| 29226 | try sema.validateRuntimeValue(block, slice_src, slice); |
| 29132 | 29227 | |
| 29133 | 29228 | if (oob_safety and block.wantSafety()) { |
| 29134 | 29229 | const len_inst = len: { |
| ... | ... | @@ -33889,6 +33984,17 @@ fn resolvePeerTypes( |
| 33889 | 33984 | else => {}, |
| 33890 | 33985 | } |
| 33891 | 33986 | |
| 33987 | // Fast path: check if everything has the same type to bypass the main PTR logic. |
| 33988 | same_type: { |
| 33989 | const ty = sema.typeOf(instructions[0]); |
| 33990 | for (instructions[1..]) |inst| { |
| 33991 | if (sema.typeOf(inst).toIntern() != ty.toIntern()) { |
| 33992 | break :same_type; |
| 33993 | } |
| 33994 | } |
| 33995 | return ty; |
| 33996 | } |
| 33997 | |
| 33892 | 33998 | const peer_tys = try sema.arena.alloc(?Type, instructions.len); |
| 33893 | 33999 | const peer_vals = try sema.arena.alloc(?Value, instructions.len); |
| 33894 | 34000 | |
| ... | ... | @@ -34562,14 +34668,14 @@ fn resolvePeerTypesInner( |
| 34562 | 34668 | } |
| 34563 | 34669 | // Clear existing sentinel |
| 34564 | 34670 | ptr_info.sentinel = .none; |
| 34565 | | switch (ip.indexToKey(ptr_info.child)) { |
| 34671 | if (ptr_info.flags.size == .one) switch (ip.indexToKey(ptr_info.child)) { |
| 34566 | 34672 | .array_type => |array_type| ptr_info.child = (try pt.arrayType(.{ |
| 34567 | 34673 | .len = array_type.len, |
| 34568 | 34674 | .child = array_type.child, |
| 34569 | 34675 | .sentinel = .none, |
| 34570 | 34676 | })).toIntern(), |
| 34571 | 34677 | else => {}, |
| 34572 | | } |
| 34678 | }; |
| 34573 | 34679 | } |
| 34574 | 34680 | |
| 34575 | 34681 | opt_ptr_info = ptr_info; |