Skip to content

Commit abc4087

Browse files
authored
Merge pull request #63 from Mark-Simulacrum/deautoref-ergo
Autoref/autoderef for operators
2 parents 023fa40 + 3ccf343 commit abc4087

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@
2828
- [Extending the capabilities of compiler-generated function types](./design_notes/fn_type_trait_impls.md)
2929
- [Auto traits](./design_notes/auto_traits.md)
3030
- [Eager drop](./design_notes/eager_drop.md)
31+
- [Autoderef and autoref in operators](./design_notes/autoref_ops.md)

src/design_notes/autoref_ops.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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

Comments
 (0)