Skip to content

Commit 7ae9b50

Browse files
committed
Update to account for associated types.
1 parent 0fc4a04 commit 7ae9b50

File tree

1 file changed

+62
-12
lines changed

1 file changed

+62
-12
lines changed

text/0000-no-unused-impl-parameters.md

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,23 @@
44

55
# Summary
66

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.
915

1016
# Motivation
1117

1218
Today it is legal to have impls with type parameters that are
1319
effectively unconstrainted. This RFC proses to make these illegal by
1420
requiring that all impl type parameters must appear in either the self
1521
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.
1724

1825
There are many reasons to make this change. First, impls are not
1926
explicitly instantiated or named, so there is no way for users to
@@ -81,15 +88,61 @@ impl<A,B:Default> Foo<A> {
8188
B::Default
8289
}
8390
}
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+
}
8497
```
8598

8699
# Detailed design
87100

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.
93146

94147
# Drawbacks
95148

@@ -112,7 +165,4 @@ approach rules out the possibility of impl specialization.
112165

113166
# Unresolved questions
114167

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

Comments
 (0)