@@ -6,7 +6,7 @@ A const argument in a [path] specifies the const value to use for that item.
6
6
7
7
r[ const-generics.argument.type]
8
8
The argument must be a [ const expression] of the type ascribed to the const
9
- parameter.
9
+ parameter.
10
10
11
11
r[ items.generics.const.type-ambiguity]
12
12
When there is ambiguity if a generic argument could be resolved as either a
@@ -47,27 +47,106 @@ fn generic<const B: bool>() {
47
47
}
48
48
```
49
49
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
55
62
expressions.
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.
56
75
57
76
``` rust,compile_fail
58
- // Examples where const parameters may not be used.
77
+ // Examples of non-standalone uses of const parameters
59
78
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)>();
65
83
}
66
84
```
67
85
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
71
150
72
151
> [ !NOTE]
73
152
> This syntactic restriction is necessary to avoid requiring infinite lookahead when parsing an expression inside of a type.
@@ -92,4 +171,4 @@ fn example() {
92
171
[ block ] : ../expressions/block-expr.md
93
172
[ const expression ] : ../const_eval.md#constant-expressions
94
173
[ literal ] : ../expressions/literal-expr.md
95
- [ path ] : ../paths.md
174
+ [ path ] : ../paths.md
0 commit comments