| author | |
| committer | |
| log | 06d08dababda8fde2fef8267698a712d1966045d |
| tree | 2517a590fd472799ebea1eee4f39cf92de023230 |
| parent | c6b5945356568f6ec70ca00f9a844bd180f8ca62 |
Moves a premature check that allowed pointers to mutable pointers to coerce
to any other pointer to a mutable pointer.2 files changed, 66 insertions(+), 6 deletions(-)
src/Sema.zig+14-6| ... | ... | @@ -29385,14 +29385,18 @@ const InMemoryCoercionResult = union(enum) { |
| 29385 | 29385 | break; |
| 29386 | 29386 | }, |
| 29387 | 29387 | .array_sentinel => |sentinel| { |
| 29388 | if (sentinel.actual.toIntern() != .unreachable_value) { | |
| 29389 | try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{ | |
| 29390 | sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema), | |
| 29388 | if (sentinel.wanted.toIntern() == .unreachable_value) { | |
| 29389 | try sema.errNote(src, msg, "source array cannot be guaranteed to maintain '{f}' sentinel", .{ | |
| 29390 | sentinel.actual.fmtValueSema(pt, sema), | |
| 29391 | 29391 | }); |
| 29392 | } else { | |
| 29392 | } else if (sentinel.actual.toIntern() == .unreachable_value) { | |
| 29393 | 29393 | try sema.errNote(src, msg, "destination array requires '{f}' sentinel", .{ |
| 29394 | 29394 | sentinel.wanted.fmtValueSema(pt, sema), |
| 29395 | 29395 | }); |
| 29396 | } else { | |
| 29397 | try sema.errNote(src, msg, "array sentinel '{f}' cannot cast into array sentinel '{f}'", .{ | |
| 29398 | sentinel.actual.fmtValueSema(pt, sema), sentinel.wanted.fmtValueSema(pt, sema), | |
| 29399 | }); | |
| 29396 | 29400 | } |
| 29397 | 29401 | break; |
| 29398 | 29402 | }, |
| ... | ... | @@ -30179,10 +30183,14 @@ fn coerceInMemoryAllowedPtrs( |
| 30179 | 30183 | src_src, |
| 30180 | 30184 | null, |
| 30181 | 30185 | ); |
| 30182 | if (child != .ok and !dest_is_mut) allow: { | |
| 30186 | if (child != .ok) allow: { | |
| 30183 | 30187 | // As a special case, we also allow coercing `*[n:s]T` to `*[n]T`, akin to dropping the sentinel from a slice. |
| 30184 | 30188 | // `*[n:s]T` cannot coerce in memory to `*[n]T` since they have different sizes. |
| 30185 | if (src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and | |
| 30189 | // | |
| 30190 | // We must once again include `dest_is_mut` because `**[n:s]T -> **[n]T` | |
| 30191 | // is not allowed, as it would make it possible to assign an illegal value | |
| 30192 | // to the sentinel-terminated side. | |
| 30193 | if (!dest_is_mut and src_child.zigTypeTag(zcu) == .array and dest_child.zigTypeTag(zcu) == .array and | |
| 30186 | 30194 | src_child.arrayLen(zcu) == dest_child.arrayLen(zcu) and |
| 30187 | 30195 | src_child.sentinel(zcu) != null and dest_child.sentinel(zcu) == null and |
| 30188 | 30196 | .ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src, null)) |
test/cases/compile_errors/coerce_pointers_with_uncoercable_child_pointers.zig created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | export fn entry1() void { | |
| 2 | const p: **u32 = undefined; | |
| 3 | const q: **i32 = p; | |
| 4 | _ = q; | |
| 5 | } | |
| 6 | ||
| 7 | export fn entry2() void { | |
| 8 | const p: [*]*u32 = undefined; | |
| 9 | const q: [*]*i32 = p; | |
| 10 | _ = q; | |
| 11 | } | |
| 12 | ||
| 13 | export fn entry3() void { | |
| 14 | const p: []*u32 = undefined; | |
| 15 | const q: []*i32 = p; | |
| 16 | _ = q; | |
| 17 | } | |
| 18 | ||
| 19 | export fn entry4() void { | |
| 20 | const p: [*c]*u32 = undefined; | |
| 21 | const q: [*c]*i32 = p; | |
| 22 | _ = q; | |
| 23 | } | |
| 24 | ||
| 25 | export fn entry5() void { | |
| 26 | const p: **[1:42]u8 = undefined; | |
| 27 | const q: **[1]u8 = p; | |
| 28 | _ = q; | |
| 29 | } | |
| 30 | ||
| 31 | // error | |
| 32 | // | |
| 33 | // :3:22: error: expected type '**i32', found '**u32' | |
| 34 | // :3:22: note: pointer type child '*u32' cannot cast into pointer type child '*i32' | |
| 35 | // :3:22: note: pointer type child 'u32' cannot cast into pointer type child 'i32' | |
| 36 | // :3:22: note: signed 32-bit int cannot represent all possible unsigned 32-bit values | |
| 37 | // :9:24: error: expected type '[*]*i32', found '[*]*u32' | |
| 38 | // :9:24: note: pointer type child '*u32' cannot cast into pointer type child '*i32' | |
| 39 | // :9:24: note: pointer type child 'u32' cannot cast into pointer type child 'i32' | |
| 40 | // :9:24: note: signed 32-bit int cannot represent all possible unsigned 32-bit values | |
| 41 | // :15:23: error: expected type '[]*i32', found '[]*u32' | |
| 42 | // :15:23: note: pointer type child '*u32' cannot cast into pointer type child '*i32' | |
| 43 | // :15:23: note: pointer type child 'u32' cannot cast into pointer type child 'i32' | |
| 44 | // :15:23: note: signed 32-bit int cannot represent all possible unsigned 32-bit values | |
| 45 | // :21:25: error: expected type '[*c]*i32', found '[*c]*u32' | |
| 46 | // :21:25: note: pointer type child '*u32' cannot cast into pointer type child '*i32' | |
| 47 | // :21:25: note: pointer type child 'u32' cannot cast into pointer type child 'i32' | |
| 48 | // :21:25: note: signed 32-bit int cannot represent all possible unsigned 32-bit values | |
| 49 | // :27:24: error: expected type '**[1]u8', found '**[1:42]u8' | |
| 50 | // :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8' | |
| 51 | // :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8' | |
| 52 | // :27:24: note: source array cannot be guaranteed to maintain '42' sentinel |