|
| 1 | +# Autoref/Autoderef in operators |
| 2 | + |
| 3 | +Rust permits overriding most of the operators (e.g., `+`, `-`, `+=`). In part |
| 4 | +due to `Copy` types not auto-dereferencing, it is common to have `T + &T` |
| 5 | +or `&T + &T`, with potentially many levels of indirection on either side of the |
| 6 | +operator. |
| 7 | + |
| 8 | +There is desire in general to avoid needing to both add impls for referenced |
| 9 | +versions of types because they: |
| 10 | + |
| 11 | +- bloat documentation |
| 12 | +- are never quite sufficient (always more references are possible) |
| 13 | +- can cause inference regressions, as the compiler cannot in general know that |
| 14 | + `&T + &T` is essentially equivalent at runtime to `T + T`. |
| 15 | + |
| 16 | +The inference regressions are the primary target of historical discussions. |
| 17 | + |
| 18 | +The tradeoff to some feature like this may either mean that the exact impl |
| 19 | +executed at runtime is harder to determine, or that the compiler is |
| 20 | +synthetically generating new implementations for some subset of types, |
| 21 | +potentially adding confusion around which impls are actually present. |
| 22 | + |
| 23 | +However, generic code may want the impls on references because the generic code |
| 24 | +may not want to require `T: Copy`. One version of this could involve |
| 25 | +something like `default impl<T:Copy> Add<&T> for &T` so that people don't *need* |
| 26 | +to write special impls themselves. It's worth noting that this still would need |
| 27 | +some special support in the compiler to avoid the two possible impls leading to |
| 28 | +inference regressions. |
| 29 | + |
| 30 | +## History |
| 31 | + |
| 32 | +The standard library initially had just the basic impls of the operator traits |
| 33 | +(e.g., `impl Add<u64> for u64`) but has since gained `&u64 + &u64`, `u64 + &u64` |
| 34 | +and `&u64 + u64`. These impls usually cause some amount of inference breakage in |
| 35 | +practice. |
| 36 | + |
| 37 | +Especially with non-Copy types (for example bigints), forcing users to add references can be |
| 38 | +increasingly verbose: `&u * &(&(&u.square() + &(&a * &u)) + &one)`, for example. |
| 39 | + |
| 40 | +There have also been a number of discussions on RFCs and issues, including: |
| 41 | +- [Rust tracking issue #44762](https://github.com/rust-lang/rust/issues/44762) |
| 42 | + - This includes some implementation/mentoring notes. |
| 43 | +- [RFC 2147](https://github.com/rust-lang/rfcs/pull/2147) |
| 44 | +- [Trying to add T op= &T](https://github.com/rust-lang/rust/pull/41336) |
| 45 | + - Showcases dealing with inference breakage regressions when adding new |
| 46 | + reference-taking impls. |
0 commit comments