@@ -6,7 +6,7 @@ A const argument in a [path] specifies the const value to use for that item.
66
77r[ const-generics.argument.type]
88The argument must be a [ const expression] of the type ascribed to the const
9- parameter.
9+ parameter.
1010
1111r[ items.generics.const.type-ambiguity]
1212When there is ambiguity if a generic argument could be resolved as either a
@@ -47,27 +47,106 @@ fn generic<const B: bool>() {
4747}
4848```
4949
50- r[ items.generics.const.standalone]
51- As a further restriction, const parameters may only appear as a standalone
52- argument inside of a [ type] or [ array repeat expression] . In those contexts,
53- they may only be used as a single segment [ path expression] , possibly inside a
54- [ block] (such as ` N ` or ` {N} ` ). That is, they cannot be combined with other
50+ r[ const-generics.kinds]
51+ There are three kinds of arguments to a const parameter:
52+ 1 . Standalone const parameters
53+ 2 . Inferred consts
54+ 3 . Arbitrary concrete expressions
55+
56+ r[ const-generics.standalone]
57+ ## Standalone const parameters
58+
59+ A const parameter can only be used in a const argument if it is a standalone usage.
60+ The argument must be * only* a usage of a const parameter and can be wrapped
61+ in at most one level of braces. That is, they cannot be combined with other
5562expressions.
63+ ``` rust
64+ // Examples of standalone uses of const parameters
65+
66+ fn foo <const N : usize >() {
67+ let a : [u8 ; N ] = [10 ; N ];
68+ let b : [u8 ; { N }] = a ;
69+ foo :: <N >();
70+ foo :: <{ N }>();
71+ }
72+ ```
73+
74+ Here ` a ` has type ` [u8; N] ` , an array with a length of ` N ` , referring to ` foo ` 's const parameter.
5675
5776``` rust,compile_fail
58- // Examples where const parameters may not be used.
77+ // Examples of non-standalone uses of const parameters
5978
60- // Not allowed to combine in other expressions in types, such as the
61- // arithmetic expression in the return type here.
62- fn bad_function<const N: usize>() -> [u8; {N + 1}] {
63- // Similarly not allowed for array repeat expressions.
64- [1; {N + 1}]
79+ fn foo<const N: usize>() {
80+ let a: [u8; {{ N }}] = [10; (N)];
81+ foo::<{{ N }}>();
82+ foo::<(N)>();
6583}
6684```
6785
68- The const expression must be a [ block expression] [ block ]
69- (surrounded with braces) unless it is a single path segment (an [ IDENTIFIER] )
70- or a [ literal] (with a possibly leading ` - ` token).
86+ r[ const-generics.inferred]
87+ ## Inferred consts
88+
89+ r[ const-generics.inferred.syntax]
90+ ``` grammar,types
91+ @root InferredConst -> `_`
92+ ```
93+
94+ The inferred const asks the compiler to infer the const if possible based on
95+ the surrounding information available.
96+
97+ It cannot be used in item signatures.
98+
99+ It is often used in repeat expressions:
100+ ``` rust
101+ fn make_array () -> [u32 ; 2 ] {
102+ [Default :: default (); _ ]
103+ }
104+ ```
105+
106+ r[ const-generics.concrete-expr]
107+ ## Concrete expressions
108+
109+ Most const expressions are allowed as const arguments:
110+ ``` rust
111+ // Example of a concrete expressions as an argument
112+
113+ fn make_array () -> [u8 ; 1 + 10 / 2 ] {
114+ [1 ; 6 ]
115+ }
116+ ```
117+
118+ r[ const-generics.concrete-expr.limitations]
119+ There are a few limitations about what expressions are allowed:
120+ 1 . Generic parameters may not be used
121+ 2 . In-scope where clauses may not be used
122+ 3 . Must be wrapped in braces in some cases
123+
124+ ``` rust,compile_fail
125+ // Examples where expressions may not be used as they use generic parameters.
126+
127+ // Not allowed in the const argument for an arrays length
128+ fn bad_function<const N: usize>() -> [u8; N + 1] {
129+ // Similarly not allowed for array repeat expressions' count argument.
130+ [1; N + 1]
131+ }
132+
133+ // Using type parameters is also disallowed
134+ fn type_parameters_disallowed<T>(_: [u8; size_of::<T>()]) {}
135+ ```
136+
137+ ``` rust,compile_fail
138+ // Example where an expression may not be used as it depends on an in-scope
139+ // where clause
140+
141+ fn bad_function(_: [u8; { let a: [u8]; 1 }])
142+ where
143+ for<'a> [u8]: Sized, {}
144+ ```
145+
146+ The const expression must be a [ block expression] [ block ] (surrounded with braces) unless it's:
147+ - a single path segment (an [ IDENTIFIER] )
148+ - a [ literal] (with a possibly leading ` - ` token)
149+ - an array length or repeat expression count
71150
72151> [ !NOTE]
73152> This syntactic restriction is necessary to avoid requiring infinite lookahead when parsing an expression inside of a type.
@@ -92,4 +171,4 @@ fn example() {
92171[ block ] : ../expressions/block-expr.md
93172[ const expression ] : ../const_eval.md#constant-expressions
94173[ literal ] : ../expressions/literal-expr.md
95- [ path ] : ../paths.md
174+ [ path ] : ../paths.md
0 commit comments