Another option is to say that accessing a flattened field (say, foo.bar
) results in an rvalue. Thus, &foo.bar
would be legal, but would simply copy the value to the stack and take a reference to that, same as e.g. &123
. The same would happen if you called foo.bar.baz()
, where baz
is some method that requires &self
. ptr::addr_of!(foo.bar)
, on the other hand, would be an error, just as ptr::addr_of!(123)
is.
This way you avoid the problem with is_some()
and similar.
Note that this mostly only makes sense if the type is Copy
. If not, &foo.bar
could still be treated as moving foo.bar
and taking a reference to the result, but that's kind of surprising.