Skip to content

Commit d695a9a

Browse files
committed
Add "associated item constraints"
This adds a section with rules describing associated item constraints. I'm not 100% certain this is the best chapter layout to place this section. Perhaps it should go somewhere else? I have intentionally used the terminology "associated item constraint" even though it is currently only *types* that are constrained. My intention is that once MCGA is stabilized, it will also include consts.
1 parent a65d48f commit d695a9a

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

src/types/generics/index.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,82 @@ FCW exists for non-value (function) position, see
227227
https://doc.rust-lang.org/nightly/rustc/lints/listing/warn-by-default.html#late-bound-lifetime-arguments
228228
-->
229229
230+
r[generics.associated]
231+
## Associated item constraints
232+
233+
r[generics.associated.intro]
234+
An *associated item constraint* constrains an [associated type] of a trait. There are two kinds of associated item constraints: equality constraints and bound constraints.
235+
236+
r[generics.associated.equality]
237+
An *equality constraint* fixes the associated item to a specific type. It is specified with the [GenericArgsBinding] syntax.
238+
239+
> [!EXAMPLE]
240+
> ```rust
241+
> // The `Item` associated item is specified to be `i32`.
242+
> fn sum_iter(iter: impl Iterator<Item = i32>) -> i32 {
243+
> iter.sum()
244+
> }
245+
> ```
246+
247+
r[generics.associated.bound]
248+
A *bound constraint* requires the associated item to satisfy a [trait bound] without fixing it to a concrete type. It is specified with the [GenericArgsBounds] syntax.
249+
250+
> [!EXAMPLE]
251+
> ```rust
252+
> # use std::fmt::Display;
253+
> #
254+
> // The `Item` associated type is required to implement Display.
255+
> fn print_iter(iter: impl Iterator<Item: Display>) {
256+
> for item in iter {
257+
> println!("{item}");
258+
> }
259+
> }
260+
> ```
261+
262+
r[generics.associated.constraints-position]
263+
Associated item constraints are only permitted when the path refers to a [trait] in a type position. They are permitted in the following positions:
264+
265+
- [Trait bounds], including inline bounds (`T: Trait<Assoc = Type>`) and `where` clauses
266+
- [`impl Trait`][impl trait] argument and return types
267+
- [Trait object] types (`dyn Trait<Assoc = Type>`)
268+
269+
They are not permitted in the following positions:
270+
271+
- On non-trait generic type paths such as structs, enums, or type aliases: `Struct<Assoc = Type>`
272+
- On the trait reference in an `impl` block header: `impl Trait<Assoc = Type> for OtherType`
273+
- On the trait segment of a [qualified path]: `<Type as Trait<Assoc = X>>::AssocItem`
274+
- On an associated item's path segment: `<Type as Trait>::AssocItem<Assoc2 = X>`
275+
- In expression or method call [turbofish]: `Trait::<Assoc = X>::method()` or `value.method::<Assoc = X>()`
276+
277+
> [!EXAMPLE]
278+
> The following are invalid uses of associated item constraints:
279+
>
280+
> ```rust,compile_fail
281+
> // ERROR: constraint on a non-trait generic type (struct).
282+
> struct Container<T>(T);
283+
> fn f1() {
284+
> let _: Container<T = i32>;
285+
> }
286+
>
287+
> // ERROR: constraint on the trait reference in an `impl` block header.
288+
> trait Produce { type Output; }
289+
> struct Widget;
290+
> impl Produce<Output = i32> for Widget {
291+
> type Output = i32;
292+
> }
293+
>
294+
> // ERROR: constraint on the trait segment of a qualified type path.
295+
> trait Source { type Data; }
296+
> fn f3<I: Source>(_: &<I as Source<Data = ()>>::Data) {}
297+
>
298+
> // ERROR: constraint in an expression-position turbofish.
299+
> trait Create { type Item; fn new() -> i32 { 0 } }
300+
> fn f4() { Create::<Item = i32>::new(); }
301+
>
302+
> // ERROR: constraint in a method call turbofish.
303+
> fn f5() { 0u32.clone::<T = u32>(); }
304+
> ```
305+
230306
r[generics.arguments.inference]
231307
### Infer arguments
232308
@@ -471,6 +547,7 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
471547
[generic implementations]: items.impl.generics
472548
[generic parameter scopes]: names.scopes.generic-parameters
473549
[higher-ranked lifetimes]: bound.higher-ranked
550+
[impl trait]: type.impl-trait
474551
[implementations]: items.impl
475552
[inferred const]: generics.const.inferred
476553
[item declarations]: statement.item
@@ -481,10 +558,13 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
481558
[path]: paths
482559
[paths in expressions]: paths.expr
483560
[paths in types]: paths.type
561+
[qualified path]: paths.qualified
484562
[raw pointers]: type.pointer.raw
485563
[references]: type.pointer.reference
486564
[slices]: type.slice
487565
[structs]: items.struct
566+
[trait bound]: bound
567+
[Trait bounds]: bound
488568
[trait object]: type.trait-object
489569
[traits]: items.traits
490570
[tuples]: type.tuple

0 commit comments

Comments
 (0)