Commit 0370006c1f

Veikka Tuominen <git@vexu.eu>
2022-07-11 10:38:04
Sema: only add note about int mismatch if not coercible
`unsigned 64-bit int cannot represent all possible unsigned 63-bit values` is nonsensical.
1 parent e644a2a
Changed files (2)
src/Sema.zig
@@ -20411,7 +20411,7 @@ fn coerceExtra(
 const InMemoryCoercionResult = union(enum) {
     ok,
     no_match: Pair,
-    int_mismatch: Int,
+    int_not_coercible: Int,
     error_union_payload: PairAndChild,
     array_len: IntPair,
     array_sentinel: Sentinel,
@@ -20527,7 +20527,7 @@ const InMemoryCoercionResult = union(enum) {
                 try sema.addDeclaredHereNote(msg, types.actual);
                 break;
             },
-            .int_mismatch => |int| {
+            .int_not_coercible => |int| {
                 try sema.errNote(block, src, msg, "{s} {d}-bit int cannot represent all possible {s} {d}-bit values", .{
                     @tagName(int.wanted_signedness), int.wanted_bits, @tagName(int.actual_signedness), int.actual_bits,
                 });
@@ -20768,17 +20768,25 @@ fn coerceInMemoryAllowed(
     if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) {
         const dest_info = dest_ty.intInfo(target);
         const src_info = src_ty.intInfo(target);
-        if (dest_info.signedness != src_info.signedness or
-            dest_info.bits != src_info.bits)
+
+        if (dest_info.signedness == src_info.signedness and
+            dest_info.bits == src_info.bits)
+        {
+            return .ok;
+        }
+
+        if ((src_info.signedness == dest_info.signedness and dest_info.bits < src_info.bits) or
+            // small enough unsigned ints can get casted to large enough signed ints
+            (dest_info.signedness == .signed and (src_info.signedness == .unsigned or dest_info.bits <= src_info.bits)) or
+            (dest_info.signedness == .unsigned and src_info.signedness == .signed))
         {
-            return InMemoryCoercionResult{ .int_mismatch = .{
+            return InMemoryCoercionResult{ .int_not_coercible = .{
                 .actual_signedness = src_info.signedness,
                 .wanted_signedness = dest_info.signedness,
                 .actual_bits = src_info.bits,
                 .wanted_bits = dest_info.bits,
             } };
         }
-        return .ok;
     }
 
     // Differently-named floats with the same number of bits.
test/cases/compile_errors/cast_between_optional_T_where_T_is_not_a_pointer.zig
@@ -1,11 +1,18 @@
 pub const fnty1 = ?*const fn (i8) void;
 pub const fnty2 = ?*const fn (u64) void;
-export fn entry() void {
+export fn entry1() void {
     var a: fnty1 = undefined;
     var b: fnty2 = undefined;
     a = b;
 }
 
+pub const fnty3 = ?*const fn (u63) void;
+export fn entry2() void {
+    var a: fnty3 = undefined;
+    var b: fnty2 = undefined;
+    a = b;
+}
+
 // error
 // backend=stage2
 // target=native
@@ -14,3 +21,6 @@ export fn entry() void {
 // :6:9: note: pointer type child 'fn(u64) void' cannot cast into pointer type child 'fn(i8) void'
 // :6:9: note: parameter 0 'u64' cannot cast into 'i8'
 // :6:9: note: unsigned 64-bit int cannot represent all possible signed 8-bit values
+// :13:9: error: expected type '?*const fn(u63) void', found '?*const fn(u64) void'
+// :13:9: note: pointer type child 'fn(u64) void' cannot cast into pointer type child 'fn(u63) void'
+// :13:9: note: parameter 0 'u64' cannot cast into 'u63'