Skip to content

Commit 62dca97

Browse files
authored
Merge pull request #928 from Havvy/constraint
Define constraining an implementation
2 parents 5c76e23 + d15dfcf commit 62dca97

File tree

1 file changed

+85
-7
lines changed

1 file changed

+85
-7
lines changed

src/items/implementations.md

+85-7
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,9 @@ is considered local.
180180

181181
## Generic Implementations
182182

183-
An implementation can take [generic parameters] which are written directly
184-
after the `impl` keyword. The parameters can be used in the rest of the
185-
implementation. Type and const parameters must be used at least once in either
186-
the trait or the implementing type of an implementation. Lifetime parameters
187-
do not need to be used unless they appear in an [associated type].
183+
An implementation can take [generic parameters], which can be used in the rest
184+
of the implementation. Implementation parameters are written directly after the
185+
`impl` keyword.
188186

189187
```rust
190188
# trait Seq<T> { fn dummy(&self, _: T) { } }
@@ -196,6 +194,85 @@ impl Seq<bool> for u32 {
196194
}
197195
```
198196

197+
Generic parameters *constrain* an implementation if the parameter appears at
198+
least once in one of:
199+
200+
* The implemented trait, if it has one
201+
* The implementing type
202+
* As an [associated type] in the [bounds] of a type that contains another
203+
parameter that constrains the implementation
204+
205+
Type and const parameters must always constrain the implementation. Lifetimes
206+
must constrain the implementation if the lifetime is used in an associated type.
207+
208+
Examples of constraining situations:
209+
210+
```rust
211+
# trait Trait{}
212+
# trait GenericTrait<T> {}
213+
# trait HasAssocType { type Ty; }
214+
# struct Struct;
215+
# struct GenericStruct<T>(T);
216+
# struct ConstGenericStruct<const N: usize>([(); N]);
217+
// T constrains by being an argument to GenericTrait.
218+
impl<T> GenericTrait<T> for i32 { /* ... */ }
219+
220+
// T constrains by being an arguement to GenericStruct
221+
impl<T> Trait for GenericStruct<T> { /* ... */ }
222+
223+
// Likewise, N constrains by being an argument to ConstGenericStruct
224+
impl<const N: usize> Trait for ConstGenericStruct<N> { /* ... */ }
225+
226+
// T constrains by being in an associated type in a bound for type `U` which is
227+
// itself a generic parameter constraining the trait.
228+
impl<T, U> GenericTrait<U> for u32 where U: HasAssocType<Ty = T> { /* ... */ }
229+
230+
// Like previous, except the type is `(U, isize)`. `U` appears inside the type
231+
// that includes `T`, and is not the type itself.
232+
impl<T, U> GenericStruct<U> where (U, isize): HasAssocType<Ty = T> { /* ... */ }
233+
```
234+
235+
Examples of non-constraining situations:
236+
237+
```rust,compile_fail
238+
// The rest of these are errors, since they have type or const parameters that
239+
// do not constrain.
240+
241+
// T does not constrain since it does not appear at all.
242+
impl<T> Struct { /* ... */ }
243+
244+
// N does not constrain for the same reason.
245+
impl<const N: usize> Struct { /* ... */ }
246+
247+
// Usage of T inside the implementation does not constrain the impl.
248+
impl<T> Struct {
249+
fn uses_t(t: &T) { /* ... */ }
250+
}
251+
252+
// T is used as an associated type in the bounds for U, but U does not constrain.
253+
impl<T, U> Struct where U: HasAssocType<Ty = T> { /* ... */ }
254+
255+
// T is used in the bounds, but not as an associated type, so it does not constrain.
256+
impl<T, U> GenericTrait<U> for u32 where U: GenericTrait<T> {}
257+
```
258+
259+
Example of an allowed unconstraining lifetime parameter:
260+
261+
```rust
262+
# struct Struct;
263+
impl<'a> Struct {}
264+
```
265+
266+
Example of a disallowed unconstraining lifetime parameter:
267+
268+
```rust,compile_fail
269+
# struct Struct;
270+
# trait HasAssocType { type Ty; }
271+
impl<'a> HasAssocType for Struct {
272+
type Ty = &'a Struct;
273+
}
274+
```
275+
199276
## Attributes on Implementations
200277

201278
Implementations may contain outer [attributes] before the `impl` keyword and
@@ -217,18 +294,19 @@ attributes].
217294
[_Visibility_]: ../visibility-and-privacy.md
218295
[_WhereClause_]: generics.md#where-clauses
219296
[trait]: traits.md
220-
[associated functions]: associated-items.md#associated-functions-and-methods
221297
[associated constants]: associated-items.md#associated-constants
298+
[associated functions]: associated-items.md#associated-functions-and-methods
222299
[associated type]: associated-items.md#associated-types
223300
[attributes]: ../attributes.md
301+
[bounds]: ../trait-bounds.md
224302
[`cfg`]: ../conditional-compilation.md
225303
[`deprecated`]: ../attributes/diagnostics.md#the-deprecated-attribute
226304
[`doc`]: ../../rustdoc/the-doc-attribute.html
305+
[generic parameters]: generics.md
227306
[path]: ../paths.md
228307
[the lint check attributes]: ../attributes/diagnostics.md#lint-check-attributes
229308
[Unsafe traits]: traits.md#unsafe-traits
230309
[local trait]: ../glossary.md#local-trait
231310
[local type]: ../glossary.md#local-type
232311
[fundamental types]: ../glossary.md#fundamental-type-constructors
233312
[uncovered type]: ../glossary.md#uncovered-type
234-
[generic parameters]: generics.md

0 commit comments

Comments
 (0)