4
4
5
5
# Summary
6
6
7
- Disallow impls from having type parameters that do not appear in
8
- either the trait reference or the self type of the impl.
7
+ Disallow unconstrained type parameters from impls. In practice this
8
+ means that every type parameter must either:
9
+
10
+ 1 . appear in the trait reference of the impl, if any;
11
+ 2 . appear in the self type of the impl; or,
12
+ 3 . be bound as an associated type.
13
+
14
+ This is an informal description, see below for full details.
9
15
10
16
# Motivation
11
17
12
18
Today it is legal to have impls with type parameters that are
13
19
effectively unconstrainted. This RFC proses to make these illegal by
14
20
requiring that all impl type parameters must appear in either the self
15
21
type of the impl or, if the impl is a trait impl, an (input) type
16
- parameter of the trait reference.
22
+ parameter of the trait reference. Type parameters can also be constrained
23
+ by associated types.
17
24
18
25
There are many reasons to make this change. First, impls are not
19
26
explicitly instantiated or named, so there is no way for users to
@@ -81,15 +88,61 @@ impl<A,B:Default> Foo<A> {
81
88
B :: Default
82
89
}
83
90
}
91
+
92
+ // Legal: `U` does not appear in the input types,
93
+ // but it bound as an associated type of `T`.
94
+ impl <T ,U > Foo for T
95
+ where T : Bar <Out = U > {
96
+ }
84
97
```
85
98
86
99
# Detailed design
87
100
88
- Require that every impl type parameter appears textually within the
89
- input type parameters of the trait reference or the impl self
90
- type. Even if we introduce variance in the future, this is sufficient
91
- to ensure that the type parameter is constrained modulo lifetimes;
92
- lifetimes are not taken into account when selecting traits.
101
+ Type parameters are legal if they are "constrained" according to the
102
+ following inference rules:
103
+
104
+ ```
105
+ If T appears in the impl trait reference,
106
+ then: T is constrained
107
+
108
+ If T appears in the impl self type,
109
+ then: T is constrained
110
+
111
+ If <T0 as Trait<T1...Tn>>::U == V appears in the impl predicates,
112
+ and T0...Tn are constrained
113
+ and T0 as Trait<T1...Tn> is not the impl trait reference
114
+ then: V is constrained
115
+ ```
116
+
117
+ The interesting rule is of course the final one. It says that type
118
+ parameters whose value is determined by an associated type reference
119
+ are legal. A simple example is:
120
+
121
+ ```
122
+ impl<T,U> Foo for T
123
+ where T : Bar<Out=U>
124
+ ```
125
+
126
+ However, we have to be careful to avoid cases where the associated
127
+ type is an associated type of things that are not themselves
128
+ constrained:
129
+
130
+ ```
131
+ impl<T,U,V> Foo for T
132
+ where U: Bar<Out=V>
133
+ ```
134
+
135
+ Similarly, the final clause in the rule aims to prevent an impl from
136
+ "self-referentially" constraining an output type parameter:
137
+
138
+ ```
139
+ impl<T,U> Bar for T
140
+ where T : Bar<Out=U>
141
+ ```
142
+
143
+ This last case isn't that important because impls like this, when
144
+ used, tend to result in overflow in the compiler, but it's more
145
+ user-friendly to report an error earlier.
93
146
94
147
# Drawbacks
95
148
@@ -112,7 +165,4 @@ approach rules out the possibility of impl specialization.
112
165
113
166
# Unresolved questions
114
167
115
- I am not 100% certain whether it is safe to permit impl type
116
- parameters that only appear in associated types of impls. I am working
117
- through this in the meantime, but for now it seems safer to simply be
118
- restrictive.
168
+ None.
0 commit comments