There are subtly different requirements at work here. The code that spawned the issue was due to unergonomic access to pointer math for fields. Your code actually needs to read from the field inner to get the second pointer. And that should be a strong distinction, I think. Another reason why I dislike the current code patterns because it very much conflates the two issues.
&(*ptr).inner as *const _ // 'Just' pointer math
&(*(*ptr).inner).field) as *const _ // Reads from inner
With respect to code, the problem I see new syntax being most useful in solving would be
struct FooMe { inner: BarMe }
struct BarMe { field: u8 }
unsafe fn init_field(ptr: *const FooMe) -> *const u8 {
ptr~inner~field // Bikeshedding but that's free as binary operator?
}
// Also helps and makes explicit your version:
unsafe fn init_through_field(ptr: *const Foo) -> *const u8 {
(*ptr~inner)~field
}
And in the context of MaybeUnint I'm dreaming of a safe solution to grabbing a pointer to initialize fields.
Note that there’s intent to make &(*ptr).inner as *const _ be something like &raw const (*ptr).inner (or maybe even ptr.inner), as it’s potentially very tricky to make &(*ptr).inner as *const _ guarantee that it doesn’t actually deref ptr and, as you’ve noted, it visually looks as if it does. When the conversion to pointer is later than an immediate cast (such as when done by a conversion), it’s even trickier a question.
A minimalistic, maybe stupid, idea for syntax that could provide pointer offset but still leverage . for structural fields without ambiguity:
&.ptr.inner.field
Justification: A pointer result without involving & in the expression may be confusing given precendence set by the current language. However, if the inner expression can stand alone as with other place borrow expressions then the confusing part is that no access to the place happens. Thus combine both aspects and also hint to . operating on the pointer type.