|
| 1 | +- Feature Name: associated_type_bounds |
| 2 | +- Start Date: 2018-01-13 |
| 3 | +- RFC PR: (leave this empty) |
| 4 | +- Rust Issue: (leave this empty) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Introduce the bound form `MyTrait<AssociatedType: Bounds>`, permitted anywhere |
| 10 | +a bound of the form `MyTrait<AssociatedType = T>` would be allowed. This form |
| 11 | +desugars to `MyTrait<AssociatedType = impl Bounds>`. |
| 12 | + |
| 13 | +# Motivation |
| 14 | +[motivation]: #motivation |
| 15 | + |
| 16 | +Currently, when specifying a bound using a trait that has an associated |
| 17 | +type, the developer can specify the precise type via the syntax |
| 18 | +`MyTrait<AssociatedType = T>`. With the introduction of the `impl Trait` |
| 19 | +syntax for static-dispatch existential types, this syntax also permits |
| 20 | +`MyTrait<AssociatedType = impl Bounds>`, as a shorthand for introducing a |
| 21 | +new type variable and specifying those bounds. |
| 22 | + |
| 23 | +However, this introduces an unnecessary level of indirection that does not |
| 24 | +match the developer's intuition and mental model as well as it could. In |
| 25 | +particular, given the ability to write bounds on a type variable as `T: Bounds`, |
| 26 | +it makes sense to permit writing bounds on an associated type directly. |
| 27 | +This results in the simpler syntax `MyTrait<AssociatedType: Bounds>`. |
| 28 | + |
| 29 | +# Guide-level explanation |
| 30 | +[guide-level-explanation]: #guide-level-explanation |
| 31 | + |
| 32 | +Instead of specifying a concrete type for an associated type, we can |
| 33 | +specify a bound on the associated type, to ensure that it implements |
| 34 | +specific traits, as seen in the example below: |
| 35 | + |
| 36 | +```rust |
| 37 | +fn print_all<T: Iterator<Item: Display>>(printables: T) { |
| 38 | + for p in printables { |
| 39 | + println!("{}", p); |
| 40 | + } |
| 41 | +} |
| 42 | +``` |
| 43 | + |
| 44 | +## In anonymous existential types |
| 45 | + |
| 46 | +```rust |
| 47 | +fn printables() -> impl Iterator<Item: Display> { |
| 48 | + // .. |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +## Further examples |
| 53 | + |
| 54 | +Instead of writing: |
| 55 | + |
| 56 | +```rust |
| 57 | +impl<I> Clone for Peekable<I> |
| 58 | +where |
| 59 | + I: Clone + Iterator, |
| 60 | + <I as Iterator>::Item: Clone, |
| 61 | +{ |
| 62 | + // .. |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +you may write: |
| 67 | + |
| 68 | +```rust |
| 69 | +impl<I> Clone for Peekable<I> |
| 70 | +where |
| 71 | + I: Clone + Iterator<Item: Clone> |
| 72 | +{ |
| 73 | + // .. |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +or replace the `where` clause entirely: |
| 78 | + |
| 79 | +```rust |
| 80 | +impl<I: Clone + Iterator<Item: Clone>> Clone for Peekable<I> { |
| 81 | + // .. |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +# Reference-level explanation |
| 86 | +[reference-level-explanation]: #reference-level-explanation |
| 87 | + |
| 88 | +The surface syntax `Trait<AssociatedType: Bounds>` should desugar to |
| 89 | +`Trait<AssociatedType = impl Bounds>` anywhere it appears. This syntax |
| 90 | +does not introduce any new semantics that the availability of |
| 91 | +`impl Bounds` does not already introduce. |
| 92 | + |
| 93 | +# Drawbacks |
| 94 | +[drawbacks]: #drawbacks |
| 95 | + |
| 96 | +With the introduction of the `impl Trait` syntax, Rust code can already |
| 97 | +express this using the desugared form. This proposal just introduces a |
| 98 | +simpler surface syntax that parallels other uses of bounds. As always, |
| 99 | +when introducing new syntactic forms, an increased burden is put on |
| 100 | +developers to know about and understand those forms, and this proposal |
| 101 | +is no different. However, we believe that the parallel to the use of bounds |
| 102 | +elsewhere makes this new syntax immediately recognizable and understandable. |
| 103 | + |
| 104 | +# Rationale and alternatives |
| 105 | +[alternatives]: #alternatives |
| 106 | + |
| 107 | +As with any new surface syntax, one alternative is simply not introducing |
| 108 | +the syntax at all. That would still leave developers with the |
| 109 | +`MyTrait<AssociatedType = impl Bounds>` form. However, allowing the more |
| 110 | +direct bounds syntax provides a better parallel to the use of bounds elsewhere. |
| 111 | +The introduced form in this RFC is comparatively both shorter and clearer. |
| 112 | + |
| 113 | +# Unresolved questions |
| 114 | +[unresolved]: #unresolved-questions |
| 115 | + |
| 116 | +- Does this introduce any parsing ambiguities? |
| 117 | +- Does allowing this for `dyn` trait objects introduce any unforseen issues? |
0 commit comments