Skip to content

Commit 5333d24

Browse files
committed
Sema: fix invalid coercion *[n:x]T -> *[m]T for n != m
The change in `Sema.coerceExtra` is just to avoid an unhelpful error message, covered by the added test case. Resolves: #22373
1 parent d02c2c7 commit 5333d24

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

src/Sema.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29736,6 +29736,7 @@ fn coerceExtra(
2973629736
// Coercions where the source is a single pointer to an array.
2973729737
src_array_ptr: {
2973829738
if (!inst_ty.isSinglePointer(zcu)) break :src_array_ptr;
29739+
if (dest_info.flags.size == .One) break :src_array_ptr; // `*[n]T` -> `*T` isn't valid
2973929740
if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
2974029741
const array_ty = inst_ty.childType(zcu);
2974129742
if (array_ty.zigTypeTag(zcu) != .array) break :src_array_ptr;
@@ -29791,7 +29792,7 @@ fn coerceExtra(
2979129792
// *[N]T to [*]T
2979229793
return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2979329794
},
29794-
.One => {},
29795+
.One => unreachable, // early exit at top of block
2979529796
}
2979629797
}
2979729798

@@ -31259,6 +31260,7 @@ fn coerceInMemoryAllowedPtrs(
3125931260
// As a special case, we also allow coercing `*[n:s]T` to `*[n]T`, akin to dropping the sentinel from a slice.
3126031261
// `*[n:s]T` cannot coerce in memory to `*[n]T` since they have different sizes.
3126131262
if (src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and
31263+
src_child.arrayLen(zcu) == dest_child.arrayLen(zcu) and
3126231264
src_child.sentinel(zcu) != null and dest_child.sentinel(zcu) == null and
3126331265
.ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src, null))
3126431266
{
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
export fn bigger(a: *const [10]u32) void {
2+
const b: *const [20]u32 = a;
3+
_ = b;
4+
}
5+
6+
comptime {
7+
const a: *const [10]u32 = &@splat(0);
8+
const b: *const [20]u32 = a;
9+
_ = b;
10+
}
11+
12+
export fn biggerSentinel(a: *const [10:0]u32) void {
13+
const b: *const [20]u32 = a;
14+
_ = b;
15+
}
16+
17+
comptime {
18+
const a: *const [10:0]u32 = &@splat(0);
19+
const b: *const [20]u32 = a;
20+
_ = b;
21+
}
22+
23+
export fn smaller(a: *const [10]u32) void {
24+
const b: *const [5]u32 = a;
25+
_ = b;
26+
}
27+
28+
comptime {
29+
const a: *const [10]u32 = &@splat(0);
30+
const b: *const [5]u32 = a;
31+
_ = b;
32+
}
33+
34+
export fn smallerSentinel(a: *const [10:0]u32) void {
35+
const b: *const [5]u32 = a;
36+
_ = b;
37+
}
38+
39+
comptime {
40+
const a: *const [10:0]u32 = &@splat(0);
41+
const b: *const [5]u32 = a;
42+
_ = b;
43+
}
44+
45+
// error
46+
//
47+
// :2:31: error: expected type '*const [20]u32', found '*const [10]u32'
48+
// :2:31: note: pointer type child '[10]u32' cannot cast into pointer type child '[20]u32'
49+
// :2:31: note: array of length 10 cannot cast into an array of length 20
50+
// :8:31: error: expected type '*const [20]u32', found '*const [10]u32'
51+
// :8:31: note: pointer type child '[10]u32' cannot cast into pointer type child '[20]u32'
52+
// :8:31: note: array of length 10 cannot cast into an array of length 20
53+
// :13:31: error: expected type '*const [20]u32', found '*const [10:0]u32'
54+
// :13:31: note: pointer type child '[10:0]u32' cannot cast into pointer type child '[20]u32'
55+
// :13:31: note: array of length 10 cannot cast into an array of length 20
56+
// :19:31: error: expected type '*const [20]u32', found '*const [10:0]u32'
57+
// :19:31: note: pointer type child '[10:0]u32' cannot cast into pointer type child '[20]u32'
58+
// :19:31: note: array of length 10 cannot cast into an array of length 20
59+
// :24:30: error: expected type '*const [5]u32', found '*const [10]u32'
60+
// :24:30: note: pointer type child '[10]u32' cannot cast into pointer type child '[5]u32'
61+
// :24:30: note: array of length 10 cannot cast into an array of length 5
62+
// :30:30: error: expected type '*const [5]u32', found '*const [10]u32'
63+
// :30:30: note: pointer type child '[10]u32' cannot cast into pointer type child '[5]u32'
64+
// :30:30: note: array of length 10 cannot cast into an array of length 5
65+
// :35:30: error: expected type '*const [5]u32', found '*const [10:0]u32'
66+
// :35:30: note: pointer type child '[10:0]u32' cannot cast into pointer type child '[5]u32'
67+
// :35:30: note: array of length 10 cannot cast into an array of length 5
68+
// :41:30: error: expected type '*const [5]u32', found '*const [10:0]u32'
69+
// :41:30: note: pointer type child '[10:0]u32' cannot cast into pointer type child '[5]u32'
70+
// :41:30: note: array of length 10 cannot cast into an array of length 5

0 commit comments

Comments
 (0)