|
| 1 | +- Feature Name: `allow_self_in_where_clauses` |
| 2 | +- Start Date: 2016-06-13 |
| 3 | +- RFC PR: [#1647](https://github.com/rust-lang/rfcs/pull/1647) |
| 4 | +- Rust Issue: [#38864](https://github.com/rust-lang/rust/issues/38864) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +This RFC proposes allowing the `Self` type to be used in every position in trait |
| 10 | +implementations, including where clauses and other parameters to the trait being |
| 11 | +implemented. |
| 12 | + |
| 13 | +# Motivation |
| 14 | +[motivation]: #motivation |
| 15 | + |
| 16 | +`Self` is a useful tool to have to reduce churn when the type changes for |
| 17 | +various reasons. One would expect to be able to write |
| 18 | + |
| 19 | +```rust |
| 20 | +impl SomeTrait for MySuperLongType<T, U, V, W, X> where |
| 21 | + Self: SomeOtherTrait, |
| 22 | +``` |
| 23 | + |
| 24 | +but this will fail to compile today, forcing you to repeat the type, and adding |
| 25 | +one more place that has to change if the type ever changes. |
| 26 | + |
| 27 | +By this same logic, we would also like to be able to reference associated types |
| 28 | +from the traits being implemented. When dealing with generic code, patterns like |
| 29 | +this often emerge: |
| 30 | + |
| 31 | +```rust |
| 32 | +trait MyTrait { |
| 33 | + type MyType: SomeBound; |
| 34 | +} |
| 35 | + |
| 36 | +impl<T, U, V> MyTrait for SomeStruct<T, U, V> where |
| 37 | + SomeOtherStruct<T, U, V>: SomeBound, |
| 38 | +{ |
| 39 | + type MyType = SomeOtherStruct<T, U, V>; |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +the only reason the associated type is repeated at all is to restate the bound |
| 44 | +on the associated type. It would be nice to reduce some of that duplication. |
| 45 | + |
| 46 | +# Detailed design |
| 47 | +[design]: #detailed-design |
| 48 | + |
| 49 | +Instead of blocking `Self` from being used in the "header" of a trait impl, |
| 50 | +it will be understood to be a reference to the implementation type. For example, |
| 51 | +all of these would be valid: |
| 52 | + |
| 53 | +```rust |
| 54 | +impl SomeTrait for SomeType where Self: SomeOtherTrait { } |
| 55 | + |
| 56 | +impl SomeTrait<Self> for SomeType { } |
| 57 | + |
| 58 | +impl SomeTrait for SomeType where SomeOtherType<Self>: SomeTrait { } |
| 59 | + |
| 60 | +impl SomeTrait for SomeType where Self::AssocType: SomeOtherTrait { |
| 61 | + AssocType = SomeOtherType; |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +If the `Self` type is parameterized by `Self`, an error that the type definition |
| 66 | +is recursive is thrown, rather than not recognizing self. |
| 67 | + |
| 68 | +```rust |
| 69 | +// The error here is because this would be Vec<Vec<Self>>, Vec<Vec<Vec<Self>>>, ... |
| 70 | +impl SomeTrait for Vec<Self> { } |
| 71 | +``` |
| 72 | + |
| 73 | +# Drawbacks |
| 74 | +[drawbacks]: #drawbacks |
| 75 | + |
| 76 | +`Self` is always less explicit than the alternative. |
| 77 | + |
| 78 | +# Alternatives |
| 79 | +[alternatives]: #alternatives |
| 80 | + |
| 81 | +Not implementing this is an alternative, as is accepting Self only in where clauses |
| 82 | +and not other positions in the impl header. |
| 83 | + |
| 84 | +# Unresolved questions |
| 85 | +[unresolved]: #unresolved-questions |
| 86 | + |
| 87 | +None |
0 commit comments