1717> _ ConstParam_ :\
1818>   ;  ; ` const ` [ IDENTIFIER] ` : ` [ _ Type_ ]
1919
20- Functions, type aliases, structs, enumerations, unions, traits, and
21- implementations may be * parameterized* by types, constants, and lifetimes. These
20+ [ Functions] , [ type aliases] , [ structs] , [ enumerations] , [ unions] , [ traits] , and
21+ [ implementations] may be * parameterized* by types, constants, and lifetimes. These
2222parameters are listed in angle <span class =" parenthetical " >brackets (` <...> ` )</span >,
2323usually immediately after the name of the item and before its definition. For
2424implementations, which don't have a name, they come directly after ` impl ` .
@@ -33,18 +33,137 @@ struct Ref<'a, T> where T: 'a { r: &'a T }
3333struct InnerArray <T , const N : usize >([T ; N ]);
3434```
3535
36+ The generic parameters are in scope within the item definition where they are
37+ declared.
38+
39+ [ References] , [ raw pointers] , [ arrays] , [ slices] [ arrays ] , [ tuples] , and
40+ [ function pointers] have lifetime or type parameters as well, but are not
41+ referred to with path syntax.
42+
43+ ### Const generics
44+
45+ Const generic parameters allow items to be generic over constant values. The
46+ const identifier introduces a name for the constant parameter, and all
47+ instances of the item must be instantiated with a value of the given type.
48+
49+ <!-- TODO: update above to say "introduces a name in the [value namespace]"
50+ once namespaces are added. -->
51+
3652The only allowed types of const parameters are ` u8 ` , ` u16 ` , ` u32 ` , ` u64 ` , ` u128 ` , ` usize `
3753` i8 ` , ` i16 ` , ` i32 ` , ` i64 ` , ` i128 ` , ` isize ` , ` char ` and ` bool ` .
3854
39- Const parameters may only be be used as standalone arguments inside
40- of [ types] and [ repeat expressions] but may be freely used elsewhere:
55+ Const parameters can generally be used anywhere a [ const item] can be used,
56+ with the exception of the definition of any [ item] within the body of a
57+ function, and can only be used as standalone expressions in [ types] and
58+ [ array repeat expressions] (described below). That is, they are allowed in the
59+ following places:
60+
61+ 1 . As an applied const to any type which forms a part of the signature of the
62+ item in question.
63+ 2 . As part of a const expression used to define an [ associated const] , or as a
64+ parameter to an [ associated type] .
65+ 3 . As a value in any runtime expression in the body of any functions in the
66+ item.
67+ 4 . As a parameter to any type used in the body of any functions in the item.
68+ 5 . 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.
74+ fn 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.
82+ struct Foo <const N : usize >([i32 ; N ]);
83+
84+ impl <const N : usize > Foo <N > {
85+ // Used as an associated constant.
86+ const CONST : usize = N * 4 ;
87+ }
88+
89+ trait Trait {
90+ type Output ;
91+ }
92+
93+ impl <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.
101+ fn 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+
113+ As a further restriction, const parameters may only appear as a standalone
114+ argument inside of [ types] and [ array repeat expressions] . In those contexts,
115+ they 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
117+ expressions.
41118
42119``` rust,compile_fail
43- // ok: standalone argument
44- fn foo<const N: usize>() -> [u8; N] { todo!() }
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.
124+ fn bad_function<const N: usize>() -> [u8; {N + 1}] {
125+ // Similarly not allowed for array repeat expressions.
126+ [1; {N + 1}]
127+ }
128+ ```
129+
130+ A const argument in a [ path] specifies the const value to use for that item.
131+ The argument must be a [ const expression] of the type ascribed to the const
132+ parameter. The const expression must be a [ block expression] [ block ]
133+ (surrounded with braces) unless it is a single path segment (an [ IDENTIFIER] )
134+ or a [ literal] (with a possibly leading ` - ` token). This syntactic restriction
135+ is necessary to avoid requiring infinite lookahead when parsing an expression
136+ inside of a type.
137+
138+ ``` rust
139+ fn double <const N : i32 >() {
140+ println! (" doubled: {}" , N * 2 );
141+ }
45142
46- // ERROR: generic const operation
47- fn bar<const N: usize>() -> [u8; N + 1] { todo!() }
143+ const SOME_CONST : i32 = 12 ;
144+
145+ fn example () {
146+ // Example usage of a const argument.
147+ double :: <9 >();
148+ double :: <- 123 >();
149+ double :: <{7 + 8 }>();
150+ double :: <SOME_CONST >();
151+ double :: <{ SOME_CONST + 5 }>();
152+ }
153+ ```
154+
155+ When there is ambiguity if a generic argument could be resolved as either a
156+ type or const argument, it is always resolved as a type. Placing the argument
157+ in a block expression can force it to be interpreted as a const argument.
158+
159+ ``` rust,compile_fail
160+ type N = u32;
161+ struct Foo<const N: usize>;
162+ // The following is an error, because `N` is interpreted as the type alias `N`.
163+ fn foo<const N: usize>() -> Foo<N> { todo!() } // ERROR
164+ // Can be fixed by wrapping in braces to force it to be interprted as the `N`
165+ // const parameter:
166+ fn bar<const N: usize>() -> Foo<{ N }> { todo!() } // ok
48167```
49168
50169Unlike type and lifetime parameters, const parameters of types can be used without
@@ -60,10 +179,6 @@ struct Baz<T>;
60179struct Biz<'a>;
61180```
62181
63- [ References] , [ raw pointers] , [ arrays] , [ slices] [ arrays ] , [ tuples] , and
64- [ function pointers] have lifetime or type parameters as well, but are not
65- referred to with path syntax.
66-
67182## Where clauses
68183
69184> ** <sup >Syntax</sup >** \
@@ -90,7 +205,7 @@ parameters.
90205The ` for ` keyword can be used to introduce [ higher-ranked lifetimes] . It only
91206allows [ _ LifetimeParam_ ] parameters.
92207
93- Bounds that don't use the item's parameters or higher-ranked lifetimes are
208+ Bounds that don't use the item's parameters or [ higher-ranked lifetimes] are
94209checked when the item is defined. It is an error for such a bound to be false.
95210
96211[ ` Copy ` ] , [ ` Clone ` ] , and [ ` Sized ` ] bounds are also checked for certain generic
@@ -141,17 +256,33 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
141256[ _Type_ ] : ../types.md#type-expressions
142257[ _TypeParamBounds_ ] : ../trait-bounds.md
143258
259+ [ array repeat expressions ] : ../expressions/array-expr.md
144260[ arrays ] : ../types/array.md
261+ [ associated const ] : associated-items.md#associated-constants
262+ [ associated type ] : associated-items.md#associated-types
263+ [ block ] : ../expressions/block-expr.md
145264[ const contexts ] : ../const_eval.md#const-context
265+ [ const expression ] : ../const_eval.md#constant-expressions
266+ [ const item ] : constant-items.md
267+ [ enumerations ] : enumerations.md
268+ [ functions ] : functions.md
146269[ function pointers ] : ../types/function-pointer.md
147270[ higher-ranked lifetimes ] : ../trait-bounds.md#higher-ranked-trait-bounds
271+ [ implementations ] : implementations.md
272+ [ item ] : ../items.md
273+ [ literal ] : ../expressions/literal-expr.md
274+ [ path ] : ../paths.md
275+ [ path expression ] : ../expressions/path-expr.md
148276[ raw pointers ] : ../types/pointer.md#raw-pointers-const-and-mut
149277[ references ] : ../types/pointer.md#shared-references-
150- [ repeat expressions ] : ../expressions/array-expr.md
151278[ `Clone` ] : ../special-types-and-traits.md#clone
152279[ `Copy` ] : ../special-types-and-traits.md#copy
153280[ `Sized` ] : ../special-types-and-traits.md#sized
281+ [ structs ] : structs.md
154282[ tuples ] : ../types/tuple.md
155283[ trait object ] : ../types/trait-object.md
284+ [ traits ] : traits.md
285+ [ type aliases ] : type-aliases.md
156286[ types ] : ../types.md
287+ [ unions ] : unions.md
157288[ attributes ] : ../attributes.md
0 commit comments