| ... | ... | @@ -6765,8 +6765,71 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 6765 | 6765 | const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 6766 | 6766 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 6767 | 6767 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 6768 | const target = sema.mod.getTarget(); |
| 6768 | 6769 | |
| 6769 | 6770 | const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); |
| 6771 | switch (dest_ty.zigTypeTag()) { |
| 6772 | .Type, |
| 6773 | .Void, |
| 6774 | .NoReturn, |
| 6775 | .ComptimeFloat, |
| 6776 | .ComptimeInt, |
| 6777 | .Undefined, |
| 6778 | .Null, |
| 6779 | .Optional, |
| 6780 | .ErrorUnion, |
| 6781 | .ErrorSet, |
| 6782 | .Opaque, |
| 6783 | .Frame, |
| 6784 | .AnyFrame, |
| 6785 | .EnumLiteral, |
| 6786 | .Union, |
| 6787 | .Fn, |
| 6788 | => return sema.fail(block, dest_ty_src, "invalid type '{}' for @bitCast", .{dest_ty.fmt(target)}), |
| 6789 | |
| 6790 | .Pointer => { |
| 6791 | const msg = msg: { |
| 6792 | const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to pointer type '{}'", .{dest_ty.fmt(target)}); |
| 6793 | errdefer msg.destroy(sema.gpa); |
| 6794 | |
| 6795 | const pointee_ty = dest_ty.ptrInfo().data.pointee_type; |
| 6796 | try sema.errNote(block, dest_ty_src, msg, "to cast to a pointer type, use @ptrCast({}, ...)", .{dest_ty.fmt(target)}); |
| 6797 | try sema.errNote(block, dest_ty_src, msg, "to cast to a non-pointer type, use @bitCast({}, ...)", .{pointee_ty.fmt(target)}); |
| 6798 | break :msg msg; |
| 6799 | }; |
| 6800 | return sema.failWithOwnedErrorMsg(block, msg); |
| 6801 | }, |
| 6802 | .Struct => { |
| 6803 | if (dest_ty.containerLayout() == .Auto) { |
| 6804 | const msg = msg: { |
| 6805 | const msg = try sema.errMsg( |
| 6806 | block, |
| 6807 | dest_ty_src, |
| 6808 | "cannot @bitCast to '{}', struct does not have a specified layout", |
| 6809 | .{dest_ty.fmt(target)}, |
| 6810 | ); |
| 6811 | errdefer msg.destroy(sema.gpa); |
| 6812 | |
| 6813 | const ty_decl_src = dest_ty.declSrcLoc(); |
| 6814 | try sema.mod.errNoteNonLazy( |
| 6815 | ty_decl_src, |
| 6816 | msg, |
| 6817 | "consider using 'packed struct' or 'extern struct' for a specified layout.", |
| 6818 | .{}, |
| 6819 | ); |
| 6820 | break :msg msg; |
| 6821 | }; |
| 6822 | return sema.failWithOwnedErrorMsg(block, msg); |
| 6823 | } |
| 6824 | }, |
| 6825 | .BoundFn => @panic("TODO remove this type from the language and compiler"), |
| 6826 | else => {}, |
| 6827 | } |
| 6828 | |
| 6829 | // When bitcasting we compare the bit size of the types, so we need to |
| 6830 | // fully resolve all composite types to finalize the layout. |
| 6831 | try sema.resolveTypeFully(block, dest_ty_src, dest_ty); |
| 6832 | |
| 6770 | 6833 | const operand = sema.resolveInst(extra.rhs); |
| 6771 | 6834 | return sema.bitCast(block, dest_ty, operand, operand_src); |
| 6772 | 6835 | } |
| ... | ... | @@ -18995,7 +19058,19 @@ fn bitCast( |
| 18995 | 19058 | const old_ty = try sema.resolveTypeFields(block, inst_src, sema.typeOf(inst)); |
| 18996 | 19059 | try sema.resolveTypeLayout(block, inst_src, old_ty); |
| 18997 | 19060 | |
| 18998 | | // TODO validate the type size and other compile errors |
| 19061 | const target = sema.mod.getTarget(); |
| 19062 | var dest_bits = dest_ty.bitSize(target); |
| 19063 | var old_bits = old_ty.bitSize(target); |
| 19064 | |
| 19065 | if (old_bits != dest_bits) { |
| 19066 | return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{ |
| 19067 | dest_ty.fmt(target), |
| 19068 | dest_bits, |
| 19069 | old_ty.fmt(target), |
| 19070 | old_bits, |
| 19071 | }); |
| 19072 | } |
| 19073 | |
| 18999 | 19074 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 19000 | 19075 | const result_val = try sema.bitCastVal(block, inst_src, val, old_ty, dest_ty, 0); |
| 19001 | 19076 | return sema.addConstant(dest_ty, result_val); |