Autoref/Autoderef in operators

Rust permits overriding most of the operators (e.g., +, -, +=). In part due to Copy types not auto-dereferencing, it is common to have T + &T or &T + &T, with potentially many levels of indirection on either side of the operator.

There is desire in general to avoid needing to both add impls for referenced versions of types because they:

  • bloat documentation
  • are never quite sufficient (always more references are possible)
  • can cause inference regressions, as the compiler cannot in general know that &T + &T is essentially equivalent at runtime to T + T.

The inference regressions are the primary target of historical discussions.

The tradeoff to some feature like this may either mean that the exact impl executed at runtime is harder to determine, or that the compiler is synthetically generating new implementations for some subset of types, potentially adding confusion around which impls are actually present.

However, generic code may want the impls on references because the generic code may not want to require T: Copy. One version of this could involve something like default impl<T:Copy> Add<&T> for &T so that people don't need to write special impls themselves. It's worth noting that this still would need some special support in the compiler to avoid the two possible impls leading to inference regressions.

History

The standard library initially had just the basic impls of the operator traits (e.g., impl Add<u64> for u64) but has since gained &u64 + &u64, u64 + &u64 and &u64 + u64. These impls usually cause some amount of inference breakage in practice.

Especially with non-Copy types (for example bigints), forcing users to add references can be increasingly verbose: &u * &(&(&u.square() + &(&a * &u)) + &one), for example.

There have also been a number of discussions on RFCs and issues, including: