| ... | ... | @@ -17282,12 +17282,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17282 | 17282 | for (enum_field_vals, 0..) |*field_val, i| { |
| 17283 | 17283 | const enum_type = ip.indexToKey(ty.toIntern()).enum_type; |
| 17284 | 17284 | const value_val = if (enum_type.values.len > 0) |
| 17285 | | try mod.intern_pool.getCoerced(gpa, enum_type.values.get(ip)[i], .comptime_int_type) |
| 17285 | try mod.intern_pool.getCoercedInts( |
| 17286 | mod.gpa, |
| 17287 | mod.intern_pool.indexToKey(enum_type.values.get(ip)[i]).int, |
| 17288 | .comptime_int_type, |
| 17289 | ) |
| 17286 | 17290 | else |
| 17287 | | try mod.intern(.{ .int = .{ |
| 17288 | | .ty = .comptime_int_type, |
| 17289 | | .storage = .{ .u64 = @intCast(i) }, |
| 17290 | | } }); |
| 17291 | (try mod.intValue(Type.comptime_int, i)).toIntern(); |
| 17291 | 17292 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 17292 | 17293 | const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names.get(ip)[i])); |
| 17293 | 17294 | const name_val = v: { |
| ... | ... | @@ -21259,7 +21260,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21259 | 21260 | try sema.checkFloatType(block, operand_src, operand_scalar_ty); |
| 21260 | 21261 | |
| 21261 | 21262 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { |
| 21262 | | const result_val = try sema.intFromFloat(block, operand_src, operand_val, operand_ty, dest_ty); |
| 21263 | const result_val = try sema.intFromFloat(block, operand_src, operand_val, operand_ty, dest_ty, .truncate); |
| 21263 | 21264 | return Air.internedToRef(result_val.toIntern()); |
| 21264 | 21265 | } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 21265 | 21266 | return sema.failWithNeededComptime(block, operand_src, .{ |
| ... | ... | @@ -27575,21 +27576,21 @@ fn coerceExtra( |
| 27575 | 27576 | return block.addBitCast(dest_ty, inst); |
| 27576 | 27577 | } |
| 27577 | 27578 | |
| 27578 | | const is_undef = inst_ty.zigTypeTag(mod) == .Undefined; |
| 27579 | | |
| 27580 | 27579 | switch (dest_ty.zigTypeTag(mod)) { |
| 27581 | 27580 | .Optional => optional: { |
| 27582 | | // undefined sets the optional bit also to undefined. |
| 27583 | | if (is_undef) { |
| 27584 | | return mod.undefRef(dest_ty); |
| 27585 | | } |
| 27581 | if (maybe_inst_val) |val| { |
| 27582 | // undefined sets the optional bit also to undefined. |
| 27583 | if (val.toIntern() == .undef) { |
| 27584 | return mod.undefRef(dest_ty); |
| 27585 | } |
| 27586 | 27586 | |
| 27587 | | // null to ?T |
| 27588 | | if (inst_ty.zigTypeTag(mod) == .Null) { |
| 27589 | | return Air.internedToRef((try mod.intern(.{ .opt = .{ |
| 27590 | | .ty = dest_ty.toIntern(), |
| 27591 | | .val = .none, |
| 27592 | | } }))); |
| 27587 | // null to ?T |
| 27588 | if (val.toIntern() == .null_value) { |
| 27589 | return Air.internedToRef((try mod.intern(.{ .opt = .{ |
| 27590 | .ty = dest_ty.toIntern(), |
| 27591 | .val = .none, |
| 27592 | } }))); |
| 27593 | } |
| 27593 | 27594 | } |
| 27594 | 27595 | |
| 27595 | 27596 | // cast from ?*T and ?[*]T to ?*anyopaque |
| ... | ... | @@ -27681,7 +27682,9 @@ fn coerceExtra( |
| 27681 | 27682 | |
| 27682 | 27683 | if (dest_info.sentinel != .none) { |
| 27683 | 27684 | if (array_ty.sentinel(mod)) |inst_sent| { |
| 27684 | | if (dest_info.sentinel != (try mod.getCoerced(inst_sent, dst_elem_type)).toIntern()) { |
| 27685 | if (Air.internedToRef(dest_info.sentinel) != |
| 27686 | try sema.coerceInMemory(inst_sent, dst_elem_type)) |
| 27687 | { |
| 27685 | 27688 | in_memory_result = .{ .ptr_sentinel = .{ |
| 27686 | 27689 | .actual = inst_sent, |
| 27687 | 27690 | .wanted = dest_info.sentinel.toValue(), |
| ... | ... | @@ -27758,9 +27761,10 @@ fn coerceExtra( |
| 27758 | 27761 | switch (dest_info.flags.size) { |
| 27759 | 27762 | // coercion to C pointer |
| 27760 | 27763 | .C => switch (inst_ty.zigTypeTag(mod)) { |
| 27761 | | .Null => { |
| 27762 | | return Air.internedToRef((try mod.getCoerced(Value.null, dest_ty)).toIntern()); |
| 27763 | | }, |
| 27764 | .Null => return Air.internedToRef(try mod.intern(.{ .ptr = .{ |
| 27765 | .ty = dest_ty.toIntern(), |
| 27766 | .addr = .{ .int = .zero_usize }, |
| 27767 | } })), |
| 27764 | 27768 | .ComptimeInt => { |
| 27765 | 27769 | const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) { |
| 27766 | 27770 | error.NotCoercible => break :pointer, |
| ... | ... | @@ -27865,10 +27869,19 @@ fn coerceExtra( |
| 27865 | 27869 | // we use a dummy pointer value with the required alignment. |
| 27866 | 27870 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 27867 | 27871 | .ty = dest_ty.toIntern(), |
| 27868 | | .addr = .{ .int = (if (dest_info.flags.alignment != .none) |
| 27869 | | try mod.intValue(Type.usize, dest_info.flags.alignment.toByteUnitsOptional().?) |
| 27872 | .addr = .{ .int = if (dest_info.flags.alignment != .none) |
| 27873 | (try mod.intValue( |
| 27874 | Type.usize, |
| 27875 | dest_info.flags.alignment.toByteUnitsOptional().?, |
| 27876 | )).toIntern() |
| 27870 | 27877 | else |
| 27871 | | try mod.getCoerced(try dest_info.child.toType().lazyAbiAlignment(mod), Type.usize)).toIntern() }, |
| 27878 | try mod.intern_pool.getCoercedInts( |
| 27879 | mod.gpa, |
| 27880 | mod.intern_pool.indexToKey( |
| 27881 | (try dest_info.child.toType().lazyAbiAlignment(mod)).toIntern(), |
| 27882 | ).int, |
| 27883 | .usize_type, |
| 27884 | ) }, |
| 27872 | 27885 | .len = (try mod.intValue(Type.usize, 0)).toIntern(), |
| 27873 | 27886 | } }))); |
| 27874 | 27887 | } |
| ... | ... | @@ -27904,8 +27917,8 @@ fn coerceExtra( |
| 27904 | 27917 | } |
| 27905 | 27918 | |
| 27906 | 27919 | if (dest_info.sentinel == .none or inst_info.sentinel == .none or |
| 27907 | | dest_info.sentinel != |
| 27908 | | try mod.intern_pool.getCoerced(sema.gpa, inst_info.sentinel, dest_info.child)) |
| 27920 | Air.internedToRef(dest_info.sentinel) != |
| 27921 | try sema.coerceInMemory(inst_info.sentinel.toValue(), dest_info.child.toType())) |
| 27909 | 27922 | break :p; |
| 27910 | 27923 | |
| 27911 | 27924 | const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty); |
| ... | ... | @@ -27915,10 +27928,7 @@ fn coerceExtra( |
| 27915 | 27928 | }, |
| 27916 | 27929 | .Int, .ComptimeInt => switch (inst_ty.zigTypeTag(mod)) { |
| 27917 | 27930 | .Float, .ComptimeFloat => float: { |
| 27918 | | if (is_undef) { |
| 27919 | | return mod.undefRef(dest_ty); |
| 27920 | | } |
| 27921 | | const val = (try sema.resolveMaybeUndefVal(inst)) orelse { |
| 27931 | const val = maybe_inst_val orelse { |
| 27922 | 27932 | if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 27923 | 27933 | if (!opts.report_err) return error.NotCoercible; |
| 27924 | 27934 | return sema.failWithNeededComptime(block, inst_src, .{ |
| ... | ... | @@ -27927,29 +27937,23 @@ fn coerceExtra( |
| 27927 | 27937 | } |
| 27928 | 27938 | break :float; |
| 27929 | 27939 | }; |
| 27930 | | |
| 27931 | | if (val.floatHasFraction(mod)) { |
| 27932 | | return sema.fail( |
| 27933 | | block, |
| 27934 | | inst_src, |
| 27935 | | "fractional component prevents float value '{}' from coercion to type '{}'", |
| 27936 | | .{ val.fmtValue(inst_ty, mod), dest_ty.fmt(mod) }, |
| 27937 | | ); |
| 27938 | | } |
| 27939 | | const result_val = try sema.intFromFloat(block, inst_src, val, inst_ty, dest_ty); |
| 27940 | const result_val = try sema.intFromFloat(block, inst_src, val, inst_ty, dest_ty, .exact); |
| 27940 | 27941 | return Air.internedToRef(result_val.toIntern()); |
| 27941 | 27942 | }, |
| 27942 | 27943 | .Int, .ComptimeInt => { |
| 27943 | | if (is_undef) { |
| 27944 | | return mod.undefRef(dest_ty); |
| 27945 | | } |
| 27946 | | if (try sema.resolveMaybeUndefVal(inst)) |val| { |
| 27944 | if (maybe_inst_val) |val| { |
| 27947 | 27945 | // comptime-known integer to other number |
| 27948 | 27946 | if (!(try sema.intFitsInType(val, dest_ty, null))) { |
| 27949 | 27947 | if (!opts.report_err) return error.NotCoercible; |
| 27950 | 27948 | return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) }); |
| 27951 | 27949 | } |
| 27952 | | return Air.internedToRef((try mod.getCoerced(val, dest_ty)).toIntern()); |
| 27950 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 27951 | .undef => try mod.undefRef(dest_ty), |
| 27952 | .int => |int| Air.internedToRef( |
| 27953 | try mod.intern_pool.getCoercedInts(mod.gpa, int, dest_ty.toIntern()), |
| 27954 | ), |
| 27955 | else => unreachable, |
| 27956 | }; |
| 27953 | 27957 | } |
| 27954 | 27958 | if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 27955 | 27959 | if (!opts.report_err) return error.NotCoercible; |
| ... | ... | @@ -27970,9 +27974,6 @@ fn coerceExtra( |
| 27970 | 27974 | return block.addTyOp(.intcast, dest_ty, inst); |
| 27971 | 27975 | } |
| 27972 | 27976 | }, |
| 27973 | | .Undefined => { |
| 27974 | | return mod.undefRef(dest_ty); |
| 27975 | | }, |
| 27976 | 27977 | else => {}, |
| 27977 | 27978 | }, |
| 27978 | 27979 | .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -27982,10 +27983,7 @@ fn coerceExtra( |
| 27982 | 27983 | return Air.internedToRef(result_val.toIntern()); |
| 27983 | 27984 | }, |
| 27984 | 27985 | .Float => { |
| 27985 | | if (is_undef) { |
| 27986 | | return mod.undefRef(dest_ty); |
| 27987 | | } |
| 27988 | | if (try sema.resolveMaybeUndefVal(inst)) |val| { |
| 27986 | if (maybe_inst_val) |val| { |
| 27989 | 27987 | const result_val = try val.floatCast(dest_ty, mod); |
| 27990 | 27988 | if (!val.eql(try result_val.floatCast(inst_ty, mod), inst_ty, mod)) { |
| 27991 | 27989 | return sema.fail( |
| ... | ... | @@ -28012,10 +28010,7 @@ fn coerceExtra( |
| 28012 | 28010 | } |
| 28013 | 28011 | }, |
| 28014 | 28012 | .Int, .ComptimeInt => int: { |
| 28015 | | if (is_undef) { |
| 28016 | | return mod.undefRef(dest_ty); |
| 28017 | | } |
| 28018 | | const val = (try sema.resolveMaybeUndefVal(inst)) orelse { |
| 28013 | const val = maybe_inst_val orelse { |
| 28019 | 28014 | if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) { |
| 28020 | 28015 | if (!opts.report_err) return error.NotCoercible; |
| 28021 | 28016 | return sema.failWithNeededComptime(block, inst_src, .{ |
| ... | ... | @@ -28037,9 +28032,6 @@ fn coerceExtra( |
| 28037 | 28032 | //} |
| 28038 | 28033 | return Air.internedToRef(result_val.toIntern()); |
| 28039 | 28034 | }, |
| 28040 | | .Undefined => { |
| 28041 | | return mod.undefRef(dest_ty); |
| 28042 | | }, |
| 28043 | 28035 | else => {}, |
| 28044 | 28036 | }, |
| 28045 | 28037 | .Enum => switch (inst_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -28070,9 +28062,6 @@ fn coerceExtra( |
| 28070 | 28062 | return sema.unionToTag(block, dest_ty, inst, inst_src); |
| 28071 | 28063 | } |
| 28072 | 28064 | }, |
| 28073 | | .Undefined => { |
| 28074 | | return mod.undefRef(dest_ty); |
| 28075 | | }, |
| 28076 | 28065 | else => {}, |
| 28077 | 28066 | }, |
| 28078 | 28067 | .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -28107,9 +28096,6 @@ fn coerceExtra( |
| 28107 | 28096 | // E to E!T |
| 28108 | 28097 | return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src); |
| 28109 | 28098 | }, |
| 28110 | | .Undefined => { |
| 28111 | | return mod.undefRef(dest_ty); |
| 28112 | | }, |
| 28113 | 28099 | else => eu: { |
| 28114 | 28100 | // T to E!T |
| 28115 | 28101 | return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src) catch |err| switch (err) { |
| ... | ... | @@ -28125,9 +28111,6 @@ fn coerceExtra( |
| 28125 | 28111 | return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src); |
| 28126 | 28112 | } |
| 28127 | 28113 | }, |
| 28128 | | .Undefined => { |
| 28129 | | return mod.undefRef(dest_ty); |
| 28130 | | }, |
| 28131 | 28114 | else => {}, |
| 28132 | 28115 | }, |
| 28133 | 28116 | .Array => switch (inst_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -28140,9 +28123,6 @@ fn coerceExtra( |
| 28140 | 28123 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); |
| 28141 | 28124 | } |
| 28142 | 28125 | }, |
| 28143 | | .Undefined => { |
| 28144 | | return mod.undefRef(dest_ty); |
| 28145 | | }, |
| 28146 | 28126 | else => {}, |
| 28147 | 28127 | }, |
| 28148 | 28128 | .Vector => switch (inst_ty.zigTypeTag(mod)) { |
| ... | ... | @@ -28152,9 +28132,6 @@ fn coerceExtra( |
| 28152 | 28132 | return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src); |
| 28153 | 28133 | } |
| 28154 | 28134 | }, |
| 28155 | | .Undefined => { |
| 28156 | | return mod.undefRef(dest_ty); |
| 28157 | | }, |
| 28158 | 28135 | else => {}, |
| 28159 | 28136 | }, |
| 28160 | 28137 | .Struct => blk: { |
| ... | ... | @@ -28174,9 +28151,7 @@ fn coerceExtra( |
| 28174 | 28151 | // undefined to anything. We do this after the big switch above so that |
| 28175 | 28152 | // special logic has a chance to run first, such as `*[N]T` to `[]T` which |
| 28176 | 28153 | // should initialize the length field of the slice. |
| 28177 | | if (is_undef) { |
| 28178 | | return mod.undefRef(dest_ty); |
| 28179 | | } |
| 28154 | if (maybe_inst_val) |val| if (val.toIntern() == .undef) return mod.undefRef(dest_ty); |
| 28180 | 28155 | |
| 28181 | 28156 | if (!opts.report_err) return error.NotCoercible; |
| 28182 | 28157 | |
| ... | ... | @@ -34043,10 +34018,10 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { |
| 34043 | 34018 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 34044 | 34019 | .int => |int| switch (int.storage) { |
| 34045 | 34020 | .u64, .i64, .big_int => return val, |
| 34046 | | .lazy_align, .lazy_size => return (try mod.intern(.{ .int = .{ |
| 34047 | | .ty = int.ty, |
| 34048 | | .storage = .{ .u64 = (try val.getUnsignedIntAdvanced(mod, sema)).? }, |
| 34049 | | } })).toValue(), |
| 34021 | .lazy_align, .lazy_size => return mod.intValue( |
| 34022 | int.ty.toType(), |
| 34023 | (try val.getUnsignedIntAdvanced(mod, sema)).?, |
| 34024 | ), |
| 34050 | 34025 | }, |
| 34051 | 34026 | .ptr => |ptr| { |
| 34052 | 34027 | const resolved_len = switch (ptr.len) { |
| ... | ... | @@ -36217,20 +36192,21 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36217 | 36192 | .auto, .explicit => { |
| 36218 | 36193 | if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null; |
| 36219 | 36194 | |
| 36220 | | switch (enum_type.names.len) { |
| 36221 | | 0 => { |
| 36222 | | const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() }); |
| 36223 | | return only.toValue(); |
| 36224 | | }, |
| 36225 | | 1 => return try mod.getCoerced((if (enum_type.values.len == 0) |
| 36226 | | try mod.intern(.{ .int = .{ |
| 36227 | | .ty = enum_type.tag_ty, |
| 36228 | | .storage = .{ .u64 = 0 }, |
| 36229 | | } }) |
| 36230 | | else |
| 36231 | | enum_type.values.get(ip)[0]).toValue(), ty), |
| 36195 | return switch (enum_type.names.len) { |
| 36196 | 0 => try mod.intern(.{ .empty_enum_value = ty.toIntern() }), |
| 36197 | 1 => try mod.intern(.{ .enum_tag = .{ |
| 36198 | .ty = ty.toIntern(), |
| 36199 | .int = if (enum_type.values.len == 0) |
| 36200 | (try mod.intValue(enum_type.tag_ty.toType(), 0)).toIntern() |
| 36201 | else |
| 36202 | try mod.intern_pool.getCoercedInts( |
| 36203 | mod.gpa, |
| 36204 | mod.intern_pool.indexToKey(enum_type.values.get(ip)[0]).int, |
| 36205 | enum_type.tag_ty, |
| 36206 | ), |
| 36207 | } }), |
| 36232 | 36208 | else => return null, |
| 36233 | | } |
| 36209 | }.toValue(); |
| 36234 | 36210 | }, |
| 36235 | 36211 | }, |
| 36236 | 36212 | |
| ... | ... | @@ -37069,6 +37045,8 @@ fn intSubWithOverflowScalar( |
| 37069 | 37045 | }; |
| 37070 | 37046 | } |
| 37071 | 37047 | |
| 37048 | const IntFromFloatMode = enum { exact, truncate }; |
| 37049 | |
| 37072 | 37050 | fn intFromFloat( |
| 37073 | 37051 | sema: *Sema, |
| 37074 | 37052 | block: *Block, |
| ... | ... | @@ -37076,6 +37054,7 @@ fn intFromFloat( |
| 37076 | 37054 | val: Value, |
| 37077 | 37055 | float_ty: Type, |
| 37078 | 37056 | int_ty: Type, |
| 37057 | mode: IntFromFloatMode, |
| 37079 | 37058 | ) CompileError!Value { |
| 37080 | 37059 | const mod = sema.mod; |
| 37081 | 37060 | if (float_ty.zigTypeTag(mod) == .Vector) { |
| ... | ... | @@ -37084,14 +37063,14 @@ fn intFromFloat( |
| 37084 | 37063 | const scalar_ty = int_ty.scalarType(mod); |
| 37085 | 37064 | for (result_data, 0..) |*scalar, i| { |
| 37086 | 37065 | const elem_val = try val.elemValue(sema.mod, i); |
| 37087 | | scalar.* = try (try sema.intFromFloatScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod))).intern(scalar_ty, mod); |
| 37066 | scalar.* = try (try sema.intFromFloatScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod), mode)).intern(scalar_ty, mod); |
| 37088 | 37067 | } |
| 37089 | 37068 | return (try mod.intern(.{ .aggregate = .{ |
| 37090 | 37069 | .ty = int_ty.toIntern(), |
| 37091 | 37070 | .storage = .{ .elems = result_data }, |
| 37092 | 37071 | } })).toValue(); |
| 37093 | 37072 | } |
| 37094 | | return sema.intFromFloatScalar(block, src, val, float_ty, int_ty); |
| 37073 | return sema.intFromFloatScalar(block, src, val, float_ty, int_ty, mode); |
| 37095 | 37074 | } |
| 37096 | 37075 | |
| 37097 | 37076 | // float is expected to be finite and non-NaN |
| ... | ... | @@ -37126,9 +37105,19 @@ fn intFromFloatScalar( |
| 37126 | 37105 | val: Value, |
| 37127 | 37106 | float_ty: Type, |
| 37128 | 37107 | int_ty: Type, |
| 37108 | mode: IntFromFloatMode, |
| 37129 | 37109 | ) CompileError!Value { |
| 37130 | 37110 | const mod = sema.mod; |
| 37131 | 37111 | |
| 37112 | if (val.isUndef(mod)) return sema.failWithUseOfUndef(block, src); |
| 37113 | |
| 37114 | if (mode == .exact and val.floatHasFraction(mod)) return sema.fail( |
| 37115 | block, |
| 37116 | src, |
| 37117 | "fractional component prevents float value '{}' from coercion to type '{}'", |
| 37118 | .{ val.fmtValue(float_ty, mod), int_ty.fmt(mod) }, |
| 37119 | ); |
| 37120 | |
| 37132 | 37121 | const float = val.toFloat(f128, mod); |
| 37133 | 37122 | if (std.math.isNan(float)) { |
| 37134 | 37123 | return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{ |