]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/items/generics.md
New upstream version 1.51.0+dfsg1
[rustc.git] / src / doc / reference / src / items / generics.md
CommitLineData
5869c6ff 1# Generic parameters
94b46f34 2
8faf50e0 3> **<sup>Syntax</sup>**\
8faf50e0 4> _GenericParams_ :\
5869c6ff
XL
5> &nbsp;&nbsp; &nbsp;&nbsp; `<` `>`\
6> &nbsp;&nbsp; | `<` (_GenericParam_ `,`)<sup>\*</sup> _GenericParam_ `,`<sup>?</sup> `>`
8faf50e0 7>
5869c6ff
XL
8> _GenericParam_ :\
9> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> ( _LifetimeParam_ | _TypeParam_ | _ConstParam_ )
8faf50e0
XL
10>
11> _LifetimeParam_ :\
5869c6ff 12> &nbsp;&nbsp; [LIFETIME_OR_LABEL]&nbsp;( `:` [_LifetimeBounds_] )<sup>?</sup>
8faf50e0
XL
13>
14> _TypeParam_ :\
5869c6ff
XL
15> &nbsp;&nbsp; [IDENTIFIER]( `:` [_TypeParamBounds_]<sup>?</sup> )<sup>?</sup> ( `=` [_Type_] )<sup>?</sup>
16>
17> _ConstParam_:\
18> &nbsp;&nbsp; `const` [IDENTIFIER] `:` [_Type_]
94b46f34 19
5869c6ff
XL
20[Functions], [type aliases], [structs], [enumerations], [unions], [traits], and
21[implementations] may be *parameterized* by types, constants, and lifetimes. These
22parameters are listed in angle <span class="parenthetical">brackets (`<...>`)</span>,
532ac7d7 23usually immediately after the name of the item and before its definition. For
94b46f34 24implementations, which don't have a name, they come directly after `impl`.
5869c6ff
XL
25The order of generic parameters is restricted to lifetime parameters, then type parameters, and then const parameters.
26
27Some examples of items with type, const, and lifetime parameters:
94b46f34
XL
28
29```rust
30fn foo<'a, T>() {}
31trait A<U> {}
32struct Ref<'a, T> where T: 'a { r: &'a T }
5869c6ff 33struct InnerArray<T, const N: usize>([T; N]);
94b46f34
XL
34```
35
5869c6ff
XL
36Generic parameters are in scope within the item definition where they are
37declared. They are not in scope for items declared within the body of a
38function as described in [item declarations].
39
e1599b0c 40[References], [raw pointers], [arrays], [slices][arrays], [tuples], and
94b46f34
XL
41[function pointers] have lifetime or type parameters as well, but are not
42referred to with path syntax.
43
5869c6ff
XL
44### Const generics
45
46*Const generic parameters* allow items to be generic over constant values. The
47const identifier introduces a name for the constant parameter, and all
48instances of the item must be instantiated with a value of the given type.
49
50<!-- TODO: update above to say "introduces a name in the [value namespace]"
51 once namespaces are added. -->
52
53The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize`
54`i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char` and `bool`.
55
56Const parameters can be used anywhere a [const item] can be used, with the
57exception that when used in a [type] or [array repeat expression], it must be
58standalone (as described below). That is, they are allowed in the following
59places:
60
611. As an applied const to any type which forms a part of the signature of the
62 item in question.
632. As part of a const expression used to define an [associated const], or as a
64 parameter to an [associated type].
653. As a value in any runtime expression in the body of any functions in the
66 item.
674. As a parameter to any type used in the body of any functions in the item.
685. As a part of the type of any fields in the item.
69
70```rust
71// Examples where const generic parameters can be used.
72
73// Used in the signature of the item itself.
74fn foo<const N: usize>(arr: [i32; N]) {
75 // Used as a type within a function body.
76 let x: [i32; N];
77 // Used as an expression.
78 println!("{}", N * 2);
79}
80
81// Used as a field of a struct.
82struct Foo<const N: usize>([i32; N]);
83
84impl<const N: usize> Foo<N> {
85 // Used as an associated constant.
86 const CONST: usize = N * 4;
87}
88
89trait Trait {
90 type Output;
91}
92
93impl<const N: usize> Trait for Foo<N> {
94 // Used as an associated type.
95 type Output = [i32; N];
96}
97```
98
99```rust,compile_fail
100// Examples where const generic parameters cannot be used.
101fn foo<const N: usize>() {
102 // Cannot use in item definitions within a function body.
103 const BAD_CONST: [usize; N] = [1; N];
104 static BAD_STATIC: [usize; N] = [1; N];
105 fn inner(bad_arg: [usize; N]) {
106 let bad_value = N * 2;
107 }
108 type BadAlias = [usize; N];
109 struct BadStruct([usize; N]);
110}
111```
112
113As a further restriction, const parameters may only appear as a standalone
114argument inside of a [type] or [array repeat expression]. In those contexts,
115they may only be used as a single segment [path expression], possibly inside a
116[block] (such as `N` or `{N}`). That is, they cannot be combined with other
117expressions.
118
119```rust,compile_fail
120// Examples where const parameters may not be used.
121
122// Not allowed to combine in other expressions in types, such as the
123// arithmetic expression in the return type here.
124fn bad_function<const N: usize>() -> [u8; {N + 1}] {
125 // Similarly not allowed for array repeat expressions.
126 [1; {N + 1}]
127}
128```
129
130A const argument in a [path] specifies the const value to use for that item.
131The argument must be a [const expression] of the type ascribed to the const
132parameter. The const expression must be a [block expression][block]
133(surrounded with braces) unless it is a single path segment (an [IDENTIFIER])
134or a [literal] (with a possibly leading `-` token).
135
136> **Note**: This syntactic restriction is necessary to avoid requiring
137> infinite lookahead when parsing an expression inside of a type.
138
139```rust
140fn double<const N: i32>() {
141 println!("doubled: {}", N * 2);
142}
143
144const SOME_CONST: i32 = 12;
145
146fn example() {
147 // Example usage of a const argument.
148 double::<9>();
149 double::<-123>();
150 double::<{7 + 8}>();
151 double::<SOME_CONST>();
152 double::<{ SOME_CONST + 5 }>();
153}
154```
155
156When there is ambiguity if a generic argument could be resolved as either a
157type or const argument, it is always resolved as a type. Placing the argument
158in a block expression can force it to be interpreted as a const argument.
159
160<!-- TODO: Rewrite the paragraph above to be in terms of namespaces, once
161 namespaces are introduced, and it is clear which namespace each parameter
162 lives in. -->
163
164```rust,compile_fail
165type N = u32;
166struct Foo<const N: usize>;
167// The following is an error, because `N` is interpreted as the type alias `N`.
168fn foo<const N: usize>() -> Foo<N> { todo!() } // ERROR
169// Can be fixed by wrapping in braces to force it to be interprted as the `N`
170// const parameter:
171fn bar<const N: usize>() -> Foo<{ N }> { todo!() } // ok
172```
173
174Unlike type and lifetime parameters, const parameters can be declared without
175being used inside of a parameterized item, with the exception of
176implementations as described in [generic implementations]:
177
178```rust,compile_fail
179// ok
180struct Foo<const N: usize>;
181enum Bar<const M: usize> { A, B }
182
183// ERROR: unused parameter
184struct Baz<T>;
185struct Biz<'a>;
186struct Unconstrained;
187impl<const N: usize> Unconstrained {}
188```
189
190When resolving a trait bound obligation, the exhaustiveness of all
191implementations of const parameters is not considered when determining if the
192bound is satisfied. For example, in the following, even though all possible
193const values for the `bool` type are implemented, it is still an error that
194the trait bound is not satisfied:
195
196```rust,compile_fail
197struct Foo<const B: bool>;
198trait Bar {}
199impl Bar for Foo<true> {}
200impl Bar for Foo<false> {}
201
202fn needs_bar(_: impl Bar) {}
203fn generic<const B: bool>() {
204 let v = Foo::<B>;
205 needs_bar(v); // ERROR: trait bound `Foo<B>: Bar` is not satisfied
206}
207```
208
209
94b46f34
XL
210## Where clauses
211
8faf50e0
XL
212> **<sup>Syntax</sup>**\
213> _WhereClause_ :\
214> &nbsp;&nbsp; `where` ( _WhereClauseItem_ `,` )<sup>\*</sup> _WhereClauseItem_ <sup>?</sup>
215>
216> _WhereClauseItem_ :\
217> &nbsp;&nbsp; &nbsp;&nbsp; _LifetimeWhereClauseItem_\
218> &nbsp;&nbsp; | _TypeBoundWhereClauseItem_
219>
220> _LifetimeWhereClauseItem_ :\
221> &nbsp;&nbsp; [_Lifetime_] `:` [_LifetimeBounds_]
222>
223> _TypeBoundWhereClauseItem_ :\
224> &nbsp;&nbsp; _ForLifetimes_<sup>?</sup> [_Type_] `:` [_TypeParamBounds_]<sup>?</sup>
225>
226> _ForLifetimes_ :\
5869c6ff 227> &nbsp;&nbsp; `for` [_GenericParams_](#generic-parameters)
94b46f34 228
532ac7d7 229*Where clauses* provide another way to specify bounds on type and lifetime
94b46f34
XL
230parameters as well as a way to specify bounds on types that aren't type
231parameters.
232
5869c6ff
XL
233The `for` keyword can be used to introduce [higher-ranked lifetimes]. It only
234allows [_LifetimeParam_] parameters.
235
236Bounds that don't use the item's parameters or [higher-ranked lifetimes] are
94b46f34
XL
237checked when the item is defined. It is an error for such a bound to be false.
238
e1599b0c 239[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic
5869c6ff 240types when defining the item. It is an error to have `Copy` or `Clone` as a
94b46f34
XL
241bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a
242bound on a trait object or slice.
243
60c5eb7d 244```rust,compile_fail
94b46f34
XL
245struct A<T>
246where
247 T: Iterator, // Could use A<T: Iterator> instead
248 T::Item: Copy,
249 String: PartialEq<T>,
250 i32: Default, // Allowed, but not useful
251 i32: Iterator, // Error: the trait bound is not satisfied
252 [T]: Copy, // Error: the trait bound is not satisfied
253{
254 f: T,
255}
256```
257
258## Attributes
259
260Generic lifetime and type parameters allow [attributes] on them. There are no
261built-in attributes that do anything in this position, although custom derive
262attributes may give meaning to it.
263
264This example shows using a custom derive attribute to modify the meaning of a
265generic parameter.
266
60c5eb7d 267<!-- ignore: requires proc macro derive -->
e74abb32 268```rust,ignore
94b46f34
XL
269// Assume that the derive for MyFlexibleClone declared `my_flexible_clone` as
270// an attribute it understands.
e74abb32
XL
271#[derive(MyFlexibleClone)]
272struct Foo<#[my_flexible_clone(unbounded)] H> {
94b46f34
XL
273 a: *const H
274}
275```
276
416331ca
XL
277[IDENTIFIER]: ../identifiers.md
278[LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels
279
5869c6ff 280[_LifetimeParam_]: #generic-parameters
416331ca
XL
281[_LifetimeBounds_]: ../trait-bounds.md
282[_Lifetime_]: ../trait-bounds.md
283[_OuterAttribute_]: ../attributes.md
284[_Type_]: ../types.md#type-expressions
285[_TypeParamBounds_]: ../trait-bounds.md
286
5869c6ff 287[array repeat expression]: ../expressions/array-expr.md
416331ca 288[arrays]: ../types/array.md
5869c6ff
XL
289[associated const]: associated-items.md#associated-constants
290[associated type]: associated-items.md#associated-types
291[block]: ../expressions/block-expr.md
292[const contexts]: ../const_eval.md#const-context
293[const expression]: ../const_eval.md#constant-expressions
294[const item]: constant-items.md
295[enumerations]: enumerations.md
296[functions]: functions.md
416331ca 297[function pointers]: ../types/function-pointer.md
5869c6ff
XL
298[generic implementations]: implementations.md#generic-implementations
299[higher-ranked lifetimes]: ../trait-bounds.md#higher-ranked-trait-bounds
300[implementations]: implementations.md
301[item declarations]: ../statements.md#item-declarations
302[item]: ../items.md
303[literal]: ../expressions/literal-expr.md
304[path]: ../paths.md
305[path expression]: ../expressions/path-expr.md
416331ca 306[raw pointers]: ../types/pointer.md#raw-pointers-const-and-mut
5869c6ff 307[references]: ../types/pointer.md#shared-references-
416331ca
XL
308[`Clone`]: ../special-types-and-traits.md#clone
309[`Copy`]: ../special-types-and-traits.md#copy
310[`Sized`]: ../special-types-and-traits.md#sized
5869c6ff 311[structs]: structs.md
416331ca
XL
312[tuples]: ../types/tuple.md
313[trait object]: ../types/trait-object.md
5869c6ff
XL
314[traits]: traits.md
315[type aliases]: type-aliases.md
316[type]: ../types.md
317[unions]: unions.md
416331ca 318[attributes]: ../attributes.md