| ... | ... | @@ -12447,12 +12447,6 @@ fn coerce( |
| 12447 | 12447 | } |
| 12448 | 12448 | assert(inst_ty.zigTypeTag() != .Undefined); |
| 12449 | 12449 | |
| 12450 | | // comptime known number to other number |
| 12451 | | // TODO why is this a separate function? should just be flattened into the |
| 12452 | | // switch expression below. |
| 12453 | | if (try sema.coerceNum(block, dest_ty, inst, inst_src)) |some| |
| 12454 | | return some; |
| 12455 | | |
| 12456 | 12450 | switch (dest_ty.zigTypeTag()) { |
| 12457 | 12451 | .Optional => { |
| 12458 | 12452 | // null to ?T |
| ... | ... | @@ -12584,11 +12578,31 @@ fn coerce( |
| 12584 | 12578 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| 12585 | 12579 | } |
| 12586 | 12580 | }, |
| 12587 | | .Int => { |
| 12588 | | // integer widening |
| 12589 | | if (inst_ty.zigTypeTag() == .Int) { |
| 12590 | | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above |
| 12581 | .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) { |
| 12582 | .Float, .ComptimeFloat => float: { |
| 12583 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :float; |
| 12591 | 12584 | |
| 12585 | if (val.floatHasFraction()) { |
| 12586 | return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_ty }); |
| 12587 | } |
| 12588 | const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) { |
| 12589 | error.FloatCannotFit => { |
| 12590 | return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty }); |
| 12591 | }, |
| 12592 | else => |e| return e, |
| 12593 | }; |
| 12594 | return try sema.addConstant(dest_ty, result_val); |
| 12595 | }, |
| 12596 | .Int, .ComptimeInt => { |
| 12597 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 12598 | // comptime known integer to other number |
| 12599 | if (!val.intFitsInType(dest_ty, target)) { |
| 12600 | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty, val }); |
| 12601 | } |
| 12602 | return try sema.addConstant(dest_ty, val); |
| 12603 | } |
| 12604 | |
| 12605 | // integer widening |
| 12592 | 12606 | const dst_info = dest_ty.intInfo(target); |
| 12593 | 12607 | const src_info = inst_ty.intInfo(target); |
| 12594 | 12608 | if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or |
| ... | ... | @@ -12598,20 +12612,53 @@ fn coerce( |
| 12598 | 12612 | try sema.requireRuntimeBlock(block, inst_src); |
| 12599 | 12613 | return block.addTyOp(.intcast, dest_ty, inst); |
| 12600 | 12614 | } |
| 12601 | | } |
| 12615 | }, |
| 12616 | else => {}, |
| 12602 | 12617 | }, |
| 12603 | | .Float => { |
| 12604 | | // float widening |
| 12605 | | if (inst_ty.zigTypeTag() == .Float) { |
| 12606 | | assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above |
| 12618 | .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) { |
| 12619 | .ComptimeFloat => { |
| 12620 | const val = try sema.resolveConstValue(block, inst_src, inst); |
| 12621 | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 12622 | return try sema.addConstant(dest_ty, result_val); |
| 12623 | }, |
| 12624 | .Float => { |
| 12625 | if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { |
| 12626 | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 12627 | if (!val.eql(result_val, dest_ty)) { |
| 12628 | return sema.fail( |
| 12629 | block, |
| 12630 | inst_src, |
| 12631 | "type {} cannot represent float value {}", |
| 12632 | .{ dest_ty, val }, |
| 12633 | ); |
| 12634 | } |
| 12635 | return try sema.addConstant(dest_ty, result_val); |
| 12636 | } |
| 12607 | 12637 | |
| 12638 | // float widening |
| 12608 | 12639 | const src_bits = inst_ty.floatBits(target); |
| 12609 | 12640 | const dst_bits = dest_ty.floatBits(target); |
| 12610 | 12641 | if (dst_bits >= src_bits) { |
| 12611 | 12642 | try sema.requireRuntimeBlock(block, inst_src); |
| 12612 | 12643 | return block.addTyOp(.fpext, dest_ty, inst); |
| 12613 | 12644 | } |
| 12614 | | } |
| 12645 | }, |
| 12646 | .Int, .ComptimeInt => int: { |
| 12647 | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse break :int; |
| 12648 | const result_val = try val.intToFloat(sema.arena, dest_ty, target); |
| 12649 | // TODO implement this compile error |
| 12650 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 12651 | //if (!int_again_val.eql(val, inst_ty)) { |
| 12652 | // return sema.fail( |
| 12653 | // block, |
| 12654 | // inst_src, |
| 12655 | // "type {} cannot represent integer value {}", |
| 12656 | // .{ dest_ty, val }, |
| 12657 | // ); |
| 12658 | //} |
| 12659 | return try sema.addConstant(dest_ty, result_val); |
| 12660 | }, |
| 12661 | else => {}, |
| 12615 | 12662 | }, |
| 12616 | 12663 | .Enum => switch (inst_ty.zigTypeTag()) { |
| 12617 | 12664 | .EnumLiteral => { |
| ... | ... | @@ -12962,80 +13009,6 @@ fn coerceInMemoryAllowedPtrs( |
| 12962 | 13009 | return .ok; |
| 12963 | 13010 | } |
| 12964 | 13011 | |
| 12965 | | fn coerceNum( |
| 12966 | | sema: *Sema, |
| 12967 | | block: *Block, |
| 12968 | | dest_ty: Type, |
| 12969 | | inst: Air.Inst.Ref, |
| 12970 | | inst_src: LazySrcLoc, |
| 12971 | | ) CompileError!?Air.Inst.Ref { |
| 12972 | | const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse return null; |
| 12973 | | const inst_ty = sema.typeOf(inst); |
| 12974 | | const src_zig_tag = inst_ty.zigTypeTag(); |
| 12975 | | const dst_zig_tag = dest_ty.zigTypeTag(); |
| 12976 | | |
| 12977 | | const target = sema.mod.getTarget(); |
| 12978 | | |
| 12979 | | switch (dst_zig_tag) { |
| 12980 | | .ComptimeInt, .Int => switch (src_zig_tag) { |
| 12981 | | .Float, .ComptimeFloat => { |
| 12982 | | if (val.floatHasFraction()) { |
| 12983 | | return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_ty }); |
| 12984 | | } |
| 12985 | | const result_val = val.floatToInt(sema.arena, dest_ty, target) catch |err| switch (err) { |
| 12986 | | error.FloatCannotFit => { |
| 12987 | | return sema.fail(block, inst_src, "integer value {d} cannot be stored in type '{}'", .{ std.math.floor(val.toFloat(f64)), dest_ty }); |
| 12988 | | }, |
| 12989 | | else => |e| return e, |
| 12990 | | }; |
| 12991 | | return try sema.addConstant(dest_ty, result_val); |
| 12992 | | }, |
| 12993 | | .Int, .ComptimeInt => { |
| 12994 | | if (!val.intFitsInType(dest_ty, target)) { |
| 12995 | | return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_ty, val }); |
| 12996 | | } |
| 12997 | | return try sema.addConstant(dest_ty, val); |
| 12998 | | }, |
| 12999 | | else => {}, |
| 13000 | | }, |
| 13001 | | .ComptimeFloat, .Float => switch (src_zig_tag) { |
| 13002 | | .ComptimeFloat => { |
| 13003 | | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 13004 | | return try sema.addConstant(dest_ty, result_val); |
| 13005 | | }, |
| 13006 | | .Float => { |
| 13007 | | const result_val = try val.floatCast(sema.arena, dest_ty); |
| 13008 | | if (!val.eql(result_val, dest_ty)) { |
| 13009 | | return sema.fail( |
| 13010 | | block, |
| 13011 | | inst_src, |
| 13012 | | "type {} cannot represent float value {}", |
| 13013 | | .{ dest_ty, val }, |
| 13014 | | ); |
| 13015 | | } |
| 13016 | | return try sema.addConstant(dest_ty, result_val); |
| 13017 | | }, |
| 13018 | | .Int, .ComptimeInt => { |
| 13019 | | const result_val = try val.intToFloat(sema.arena, dest_ty, target); |
| 13020 | | // TODO implement this compile error |
| 13021 | | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 13022 | | //if (!int_again_val.eql(val, inst_ty)) { |
| 13023 | | // return sema.fail( |
| 13024 | | // block, |
| 13025 | | // inst_src, |
| 13026 | | // "type {} cannot represent integer value {}", |
| 13027 | | // .{ dest_ty, val }, |
| 13028 | | // ); |
| 13029 | | //} |
| 13030 | | return try sema.addConstant(dest_ty, result_val); |
| 13031 | | }, |
| 13032 | | else => {}, |
| 13033 | | }, |
| 13034 | | else => {}, |
| 13035 | | } |
| 13036 | | return null; |
| 13037 | | } |
| 13038 | | |
| 13039 | 13012 | fn coerceVarArgParam( |
| 13040 | 13013 | sema: *Sema, |
| 13041 | 13014 | block: *Block, |