# Thoughts on `AtomicU32` method calls
## The problem
We would like to be able to call an `atomic_add` method on [`AtomicU32`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicU32.html).
## Options before arbitrary self types
```rust
AtomicU32::atomic_add(addr_of!(self.field), 1)
```
(not a fn that exists today) where `atomic_add` is a new fn with a signature like
```rust
fn atomic_add(p: *const AtomicU32, amount: usize)
```
## With the current simplest arbitrary self types proposal
Currently, the simplest proposal for arbitrary self types does not allow method calls on raw pointers.
## With more complex arbitrary self type proposals
More complex options for arbitrary self types would allow:
```rust
impl AtomicU32 {
fn atomic_add(self: *const Self, amount: usize) { }
}
```
and calls like:
```rust
addr_of!(self.field).atomic_add(1)
```
## Other alternatives
### `act_on_addr!` macro
```rust
act_on_addr!(self.field, atomic_add(1))
```
which expands to
```rust
AtomicU32::atomic_add(addr_of!(self.field), 1)
```
### `call_on_addr!` macro
The same, but more like a method call (would probably need to be a proc macro)
```rust
call_on_addr!(self.field.atomic_add(1))
```
Expands to the same thing, even though `atomic_add` is not a method.
### Newtype wrapper for raw pointers
It's been proposed that we have:
```rust
struct Raw<T>(*const T);
// impls Receiver
```
so that methods could be expressed as:
```rust
impl AtomicU32 {
fn atomic_add(self: &Raw<Self>, amount: usize) { }
}
```
Personally I don't like this. It feels to me like we're (likely) avoiding adding method on `*const T` because we're worried about shadowing methods on `T`; the same problem would prevent us adding methods on `Raw<T>` in future.
But... if we decided to do this it would work like this:
```rust
Raw(addr_of!(self.field)).atomic_add(1)
// or
addr_of!(self.field).as_raw().atomic_add(1)
// or even
addr_of!(self.field).into().atomic_add(1)
```
### `CoerceFromPointer` trait
Maybe `Raw<T>` implements a new trait which provides automatic coercion from `*const T`:
```rust
addr_of!(self.field).atomic_add(1)
```
I can't see a way to do this without all the same old shadowing concerns, but putting it here for thought.
### Change method precedence (references, values, etc.)
We sort of have a 2D grid of method order lookup right now. For `A<B<C>>` this is the order:
| | by value | by reference | by mut reference | by ptr |
|---|---|---|---|----|
| A | 1 | 4 | 7 | 10 |
| B | 2 | 5 | 8 | 11 |
| C | 3 | 6 | 9 | 12 |
In the more complex variants of the arbitrary self types proposal, we talked about sometimes altering the vertical order in the table above. But maybe we could alter the horizontal order:
| | by ptr | by value | by reference | by mut reference |
|---|---|---|---|----|
| A | 1 | 4 | 7 | 10 |
| B | 2 | 5 | 8 | 11 |
| C | 3 | 6 | 9 | 12 |
So, if a type yielded a `*const T` by following its deref chain, we would pick that method instead of any method on the outer type.
I don't know if this would work. But it might be an alternative way for us to allow methods with raw pointer receivers in future. Or perhaps there's a way to do this together with the `CoerceFromPointer` trait.
### All new syntax
`addr_of!` seems a bit weird because syntactically it looks like it's creating a reference.
Maybe we need a `->` operator.
This could either be used as direct syntactic sugar for `addr_of!`:
```rust
let ptr = self->field;
```
or maybe it could be used for method calls:
```rust
self.field->atomic_add(1)
```
by virtue of some new trait, e.g. `CoerceFromPointer` as suggested above, and a method like:
```rust
impl AtomicU32 {
fn atomic_add(self: &Raw<Self>, amount: usize) { }
}
```