Skip to content

Commit c81cd07

Browse files
authored
Merge pull request #901 from lcnr/const-generics
document const generics
2 parents 22c804a + 15ec5a6 commit c81cd07

File tree

4 files changed

+76
-13
lines changed

4 files changed

+76
-13
lines changed

src/SUMMARY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
- [Traits](items/traits.md)
3636
- [Implementations](items/implementations.md)
3737
- [External blocks](items/external-blocks.md)
38-
- [Type and lifetime parameters](items/generics.md)
38+
- [Generic parameters](items/generics.md)
3939
- [Associated Items](items/associated-items.md)
4040
- [Visibility and Privacy](visibility-and-privacy.md)
4141

src/const_eval.md

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ also constant expressions and do not cause any [`Drop::drop`][destructors] calls
2020
to be run.
2121

2222
* [Literals].
23+
* [Const parameters].
2324
* [Paths] to [functions] and [constants].
2425
Recursively defining constants is not allowed.
2526
* Paths to [statics]. These are only allowed within the initializer of a static.
@@ -112,6 +113,7 @@ Conversely, the following are possible in a const function, but not in a const c
112113
[comparison]: expressions/operator-expr.md#comparison-operators
113114
[const functions]: items/functions.md#const-functions
114115
[constants]: items/constant-items.md
116+
[Const parameters]: items/generics.md
115117
[dereference operator]: expressions/operator-expr.md#the-dereference-operator
116118
[destructors]: destructors.md
117119
[enum discriminants]: items/enumerations.md#custom-discriminant-values-for-fieldless-enumerations

src/items/generics.md

+49-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
# Type and Lifetime Parameters
1+
# Generic parameters
22

33
> **<sup>Syntax</sup>**\
44
> _Generics_ :\
55
> &nbsp;&nbsp; `<` _GenericParams_ `>`
66
>
77
> _GenericParams_ :\
88
> &nbsp;&nbsp; &nbsp;&nbsp; _LifetimeParams_\
9-
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> _TypeParams_
9+
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> _TypeParams_\
10+
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> ( _TypeParam_ `,` )<sup>\*</sup> _ConstParams_
1011
>
1112
> _LifetimeParams_ :\
1213
> &nbsp;&nbsp; ( _LifetimeParam_ `,` )<sup>\*</sup> _LifetimeParam_<sup>?</sup>
@@ -18,20 +19,55 @@
1819
> &nbsp;&nbsp; ( _TypeParam_ `,` )<sup>\*</sup> _TypeParam_<sup>?</sup>
1920
>
2021
> _TypeParam_ :\
21-
> &nbsp;&nbsp; [_OuterAttribute_]<sup>?</sup> [IDENTIFIER] ( `:` [_TypeParamBounds_]<sup>?</sup> )<sup>?</sup> ( `=` [_Type_] )<sup>?</sup>
22+
> &nbsp;&nbsp; [_OuterAttribute_]<sup>?</sup> [IDENTIFIER]( `:` [_TypeParamBounds_]<sup>?</sup> )<sup>?</sup> ( `=` [_Type_] )<sup>?</sup>
23+
>
24+
> _ConstParams_:\
25+
> &nbsp;&nbsp; ( _ConstParam_ `,` )<sup>\*</sup> _ConstParam_<sup>?</sup>
26+
>
27+
> _ConstParam_:\
28+
> &nbsp;&nbsp; [_OuterAttribute_]<sup>?</sup> `const` [IDENTIFIER] `:` [_Type_]
2229
2330
Functions, type aliases, structs, enumerations, unions, traits, and
24-
implementations may be *parameterized* by types and lifetimes. These parameters
25-
are listed in angle <span class="parenthetical">brackets (`<...>`)</span>,
31+
implementations may be *parameterized* by types, constants, and lifetimes. These
32+
parameters are listed in angle <span class="parenthetical">brackets (`<...>`)</span>,
2633
usually immediately after the name of the item and before its definition. For
2734
implementations, which don't have a name, they come directly after `impl`.
28-
Lifetime parameters must be declared before type parameters. Some examples of
29-
items with type and lifetime parameters:
35+
The order of generic parameters is restricted to lifetime parameters, then type parameters, and then const parameters.
36+
37+
Some examples of items with type, const, and lifetime parameters:
3038

3139
```rust
3240
fn foo<'a, T>() {}
3341
trait A<U> {}
3442
struct Ref<'a, T> where T: 'a { r: &'a T }
43+
struct InnerArray<T, const N: usize>([T; N]);
44+
```
45+
46+
The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize`
47+
`i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char` and `bool`.
48+
49+
Const parameters may only be be used as standalone arguments inside
50+
of [types] and [repeat expressions] but may be freely used elsewhere:
51+
52+
```rust,compile_fail
53+
// ok: standalone argument
54+
fn foo<const N: usize>() -> [u8; N] { todo!() }
55+
56+
// ERROR: generic const operation
57+
fn bar<const N: usize>() -> [u8; N + 1] { todo!() }
58+
```
59+
60+
Unlike type and lifetime parameters, const parameters of types can be used without
61+
being mentioned inside of a parameterized type:
62+
63+
```rust,compile_fail
64+
// ok
65+
struct Foo<const N: usize>;
66+
enum Bar<const M: usize> { A, B }
67+
68+
// ERROR: unused parameter
69+
struct Baz<T>;
70+
struct Biz<'a>;
3571
```
3672

3773
[References], [raw pointers], [arrays], [slices][arrays], [tuples], and
@@ -55,7 +91,7 @@ referred to with path syntax.
5591
> &nbsp;&nbsp; _ForLifetimes_<sup>?</sup> [_Type_] `:` [_TypeParamBounds_]<sup>?</sup>
5692
>
5793
> _ForLifetimes_ :\
58-
> &nbsp;&nbsp; `for` `<` [_LifetimeParams_](#type-and-lifetime-parameters) `>`
94+
> &nbsp;&nbsp; `for` `<` [_LifetimeParams_](#generic-parameters) `>`
5995
6096
*Where clauses* provide another way to specify bounds on type and lifetime
6197
parameters as well as a way to specify bounds on types that aren't type
@@ -65,7 +101,7 @@ Bounds that don't use the item's parameters or higher-ranked lifetimes are
65101
checked when the item is defined. It is an error for such a bound to be false.
66102

67103
[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic
68-
types when defining the item. It is an error to have `Copy` or `Clone`as a
104+
types when defining the item. It is an error to have `Copy` or `Clone` as a
69105
bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a
70106
bound on a trait object or slice.
71107

@@ -112,12 +148,15 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
112148
[_TypeParamBounds_]: ../trait-bounds.md
113149

114150
[arrays]: ../types/array.md
151+
[const contexts]: ../const_eval.md#const-context
115152
[function pointers]: ../types/function-pointer.md
116-
[references]: ../types/pointer.md#shared-references-
117153
[raw pointers]: ../types/pointer.md#raw-pointers-const-and-mut
154+
[references]: ../types/pointer.md#shared-references-
155+
[repeat expressions]: ../expressions/array-expr.md
118156
[`Clone`]: ../special-types-and-traits.md#clone
119157
[`Copy`]: ../special-types-and-traits.md#copy
120158
[`Sized`]: ../special-types-and-traits.md#sized
121159
[tuples]: ../types/tuple.md
122160
[trait object]: ../types/trait-object.md
161+
[types]: ../types.md
123162
[attributes]: ../attributes.md

src/paths.md

+24-2
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,32 @@ mod m {
5252
> &nbsp;&nbsp; &nbsp;&nbsp; `<` `>`\
5353
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,`<sup>?</sup> `>`\
5454
> &nbsp;&nbsp; | `<` _GenericArgsTypes_ `,`<sup>?</sup> `>`\
55+
> &nbsp;&nbsp; | `<` _GenericArgsConsts_ `,`<sup>?</sup> `>`\
5556
> &nbsp;&nbsp; | `<` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
56-
> &nbsp;&nbsp; | `<` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
5757
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,`<sup>?</sup> `>`\
58+
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsConsts_ `,`<sup>?</sup> `>`\
5859
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
59-
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`
60+
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,`<sup>?</sup> `>`\
61+
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
62+
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
63+
> &nbsp;&nbsp; | `<` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`\
64+
> &nbsp;&nbsp; | `<` _GenericArgsLifetimes_ `,` _GenericArgsTypes_ `,` _GenericArgsConsts_ `,` _GenericArgsBindings_ `,`<sup>?</sup> `>`
6065
>
6166
> _GenericArgsLifetimes_ :\
6267
> &nbsp;&nbsp; [_Lifetime_] (`,` [_Lifetime_])<sup>\*</sup>
6368
>
6469
> _GenericArgsTypes_ :\
6570
> &nbsp;&nbsp; [_Type_] (`,` [_Type_])<sup>\*</sup>
6671
>
72+
> _GenericArgsConsts_ :\
73+
> &nbsp;&nbsp; _GenericArgsConst_ (`,` _GenericArgsConst_)<sup>\*</sup>
74+
>
75+
> _GenericArgsConst_ :\
76+
> &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
77+
> &nbsp;&nbsp; | [_LiteralExpression_]\
78+
> &nbsp;&nbsp; | `-` [_LiteralExpression_]\
79+
> &nbsp;&nbsp; | [_SimplePathSegment_]
80+
>
6781
> _GenericArgsBindings_ :\
6882
> &nbsp;&nbsp; _GenericArgsBinding_ (`,` _GenericArgsBinding_)<sup>\*</sup>
6983
>
@@ -81,6 +95,9 @@ ambiguity with the less-than operator. This is colloquially known as "turbofish"
8195
Vec::<u8>::with_capacity(1024);
8296
```
8397

98+
Const arguments must be surrounded by braces unless they are a
99+
[literal] or a single segment path.
100+
84101
## Qualified paths
85102

86103
> **<sup>Syntax</sup>**\
@@ -364,9 +381,14 @@ mod without { // ::without
364381
# fn main() {}
365382
```
366383

384+
[_BlockExpression_]: expressions/block-expr.md
385+
[_Expression_]: expressions.md
367386
[_GenericArgs_]: #paths-in-expressions
368387
[_Lifetime_]: trait-bounds.md
388+
[_LiteralExpression_]: expressions/literal-expr.md
389+
[_SimplePathSegment_]: #simple-paths
369390
[_Type_]: types.md#type-expressions
391+
[literal]: expressions/literal-expr.md
370392
[item]: items.md
371393
[variable]: variables.md
372394
[implementations]: items/implementations.md

0 commit comments

Comments
 (0)