| 1 | //! This file contains pointer coercions which are invalid because the element types are only |
| 2 | //! in-memory coercible *in one direction*. When casting a mutable pointer, the element type |
| 3 | //! must coerce in both directions for the pointer to coerce. Otherwise, you could do something |
| 4 | //! like this, where `A` coerces to `B` but not vice-versa: |
| 5 | //! |
| 6 | //! ``` |
| 7 | //! var x: A = undefined; |
| 8 | //! const p: *B = &x; // `*A` -> `*B` |
| 9 | //! p.* = some_b; |
| 10 | //! const some_b_as_a = x; |
| 11 | //! ``` |
| 12 | |
| 13 | export fn error_set_to_larger() void { |
| 14 | var x: error{Foo} = undefined; |
| 15 | _ = @as(*const error{ Foo, Bar }, &x); // this is ok |
| 16 | _ = @as(*error{ Foo, Bar }, &x); // compile error |
| 17 | } |
| 18 | |
| 19 | export fn error_set_to_anyerror() void { |
| 20 | var x: error{Foo} = undefined; |
| 21 | _ = @as(*const anyerror, &x); // this is ok |
| 22 | _ = @as(*anyerror, &x); // compile error |
| 23 | } |
| 24 | |
| 25 | export fn error_union_to_anyerror_union() void { |
| 26 | var x: error{Foo}!u32 = undefined; |
| 27 | _ = @as(*const anyerror!u32, &x); // this is ok |
| 28 | _ = @as(*anyerror!u32, &x); // compile error |
| 29 | } |
| 30 | |
| 31 | export fn ptr_to_const_ptr() void { |
| 32 | var x: *u32 = undefined; |
| 33 | _ = @as(*const *const u32, &x); // this is ok |
| 34 | _ = @as(**const u32, &x); // compile error |
| 35 | } |
| 36 | |
| 37 | export fn ptr_to_allowzero_ptr() void { |
| 38 | var x: *u32 = undefined; |
| 39 | _ = @as(*const *allowzero u32, &x); // this is ok |
| 40 | _ = @as(**allowzero u32, &x); // compile error |
| 41 | } |
| 42 | |
| 43 | export fn ptr_to_volatile_ptr() void { |
| 44 | var x: *u32 = undefined; |
| 45 | _ = @as(*const *volatile u32, &x); // this is ok |
| 46 | _ = @as(**volatile u32, &x); // compile error |
| 47 | } |
| 48 | |
| 49 | export fn ptr_to_underaligned_ptr() void { |
| 50 | var x: *u32 = undefined; |
| 51 | _ = @as(*const *align(1) u32, &x); // this is ok |
| 52 | _ = @as(**align(1) u32, &x); // compile error |
| 53 | } |
| 54 | |
| 55 | // error |
| 56 | // |
| 57 | // :16:33: error: expected type '*error{Bar,Foo}', found '*error{Foo}' |
| 58 | // :16:33: note: pointer type child 'error{Foo}' cannot cast into pointer type child 'error{Bar,Foo}' |
| 59 | // :16:33: note: 'error.Bar' not a member of destination error set |
| 60 | // :22:24: error: expected type '*anyerror', found '*error{Foo}' |
| 61 | // :22:24: note: pointer type child 'error{Foo}' cannot cast into pointer type child 'anyerror' |
| 62 | // :22:24: note: global error set cannot cast into a smaller set |
| 63 | // :28:28: error: expected type '*anyerror!u32', found '*error{Foo}!u32' |
| 64 | // :28:28: note: pointer type child 'error{Foo}!u32' cannot cast into pointer type child 'anyerror!u32' |
| 65 | // :28:28: note: global error set cannot cast into a smaller set |
| 66 | // :34:26: error: expected type '**const u32', found '**u32' |
| 67 | // :34:26: note: pointer type child '*u32' cannot cast into pointer type child '*const u32' |
| 68 | // :34:26: note: mutable '*const u32' would allow illegal const pointers stored to type '*u32' |
| 69 | // :40:30: error: expected type '**allowzero u32', found '**u32' |
| 70 | // :40:30: note: pointer type child '*u32' cannot cast into pointer type child '*allowzero u32' |
| 71 | // :40:30: note: mutable '*allowzero u32' would allow illegal null values stored to type '*u32' |
| 72 | // :46:29: error: expected type '**volatile u32', found '**u32' |
| 73 | // :46:29: note: pointer type child '*u32' cannot cast into pointer type child '*volatile u32' |
| 74 | // :46:29: note: mutable '*volatile u32' would allow illegal volatile pointers stored to type '*u32' |
| 75 | // :52:29: error: expected type '**align(1) u32', found '**u32' |
| 76 | // :52:29: note: pointer type child '*u32' cannot cast into pointer type child '*align(1) u32' |
| 77 | // :52:29: note: pointer alignment '4' cannot cast into pointer alignment '1' |