---
# System prepended metadata

title: Thoughts on AtomicU32 method calls

---

# 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) { }
}
```