@@ -23,11 +23,11 @@ generic parameter type), because they are fully unconstrained.
23
23
[ guide-level-explanation ] : #guide-level-explanation
24
24
25
25
You can call methods of generic parameters of a const function, because they are implicitly assumed to be
26
- ` const fn ` . For example, the ` Add ` trait declaration has an additional ` const ` before the trait name, so
27
- you can use it as a trait bound on your generic parameters:
26
+ ` const fn ` . For example, the ` Add ` trait bound can be used to call ` Add::add ` or ` + ` on the arguments
27
+ with that bound.
28
28
29
29
``` rust
30
- const fn triple_add <T : const Add >(a : T , b : T , c : T ) -> T {
30
+ const fn triple_add <T : Add >(a : T , b : T , c : T ) -> T {
31
31
a + b + c
32
32
}
33
33
```
@@ -46,26 +46,23 @@ impl const Add for MyInt {
46
46
}
47
47
```
48
48
49
- The const requirement is required on all bounds of the impl and its methods,
49
+ The const requirement is inferred on all bounds of the impl and its methods,
50
50
so in the following ` H ` is required to have a const impl of ` Hasher ` , so that
51
51
methods on ` state ` are callable.
52
52
53
53
``` rust
54
54
impl const Hash for MyInt {
55
- const fn hash <H >(
55
+ fn hash <H >(
56
56
& self ,
57
57
state : & mut H ,
58
58
)
59
- where H : const Hasher
59
+ where H : Hasher
60
60
{
61
61
state . write (& [self . 0 as u8 ]);
62
62
}
63
63
}
64
64
```
65
65
66
- While these ` const ` keywords could be inferred (after all, they are required), requiring them is
67
- forward compatible to schemes in the future that allow more fine grained control.
68
-
69
66
## Drop
70
67
71
68
A notable use case of ` impl const ` is defining ` Drop ` impls. If you write
@@ -101,7 +98,7 @@ parameters are not const.
101
98
E.g.
102
99
103
100
``` rust
104
- impl <T : const Add > const Add for Foo <T > {
101
+ impl <T : Add > const Add for Foo <T > {
105
102
fn add (self , other : Self ) -> Self {
106
103
Foo (self . 0 + other . 0 )
107
104
}
@@ -118,7 +115,7 @@ a const context. E.g. the following function may be called as
118
115
` add(String::from("foo"), String::from("bar")) ` at runtime.
119
116
120
117
``` rust
121
- const fn add <T : const Add >(a : T , b : T ) -> T {
118
+ const fn add <T : Add >(a : T , b : T ) -> T {
122
119
a + b
123
120
}
124
121
```
@@ -129,6 +126,28 @@ backwards compatibility.
129
126
Changing an impl to only allow generic types which have a ` const ` impl for their bounds would break
130
127
situations like the one described above.
131
128
129
+ ## ` ?const ` opt out
130
+
131
+ There is often desire to add bounds to a ` const ` function's generic arguments, without wanting to
132
+ call any of the methods on those generic bounds. Prominent examples are ` new ` methods:
133
+
134
+ ``` rust
135
+ struct Foo <T : Trait >(T );
136
+ const fn new <T : Trait >(t : T ) -> Foo <T > {
137
+ Foo (t )
138
+ }
139
+ ```
140
+
141
+ Unfortunately, with the given syntax in this RFC, one can now only call the ` new ` method if ` T ` has
142
+ an ` impl const Trait for T { ... } ` . Thus an opt-out similar to ` ?Sized ` can be used:
143
+
144
+ ``` rust
145
+ struct Foo <T : Trait >(T );
146
+ const fn new <T : ? const Trait >(t : T ) -> Foo <T > {
147
+ Foo (t )
148
+ }
149
+ ```
150
+
132
151
# Reference-level explanation
133
152
[ reference-level-explanation ] : #reference-level-explanation
134
153
@@ -142,13 +161,12 @@ of `impl const` items.
142
161
143
162
## Implementation instructions
144
163
145
- 1 . Add an ` is_const ` field to the AST's ` TraitRef `
146
- 2 . Adjust the Parser to support ` const ` modifiers before trait bounds
147
- 3 . Add an ` is_const ` field to the HIR's ` TraitRef `
148
- 4 . Adjust lowering to pass through the ` is_const ` field from AST to HIR
149
- 5 . Add a a check to ` librustc_typeck/check/wfcheck.rs ` ensuring that all generic bounds
150
- in an ` impl const ` block have the ` in_const ` flag set and all methods' ` constness ` field is
151
- ` Const ` .
164
+ 1 . Add an ` maybe_const ` field to the AST's ` TraitRef `
165
+ 2 . Adjust the Parser to support ` ?const ` modifiers before trait bounds
166
+ 3 . Add an ` maybe_const ` field to the HIR's ` TraitRef `
167
+ 4 . Adjust lowering to pass through the ` maybe_const ` field from AST to HIR
168
+ 5 . Add a a check to ` librustc_typeck/check/wfcheck.rs ` ensuring that no generic bounds
169
+ in an ` impl const ` block have the ` maybe_const ` flag set
152
170
6 . Feature gate instead of ban ` Predicate::Trait ` other than ` Sized ` in
153
171
` librustc_mir/transform/qualify_min_const_fn.rs `
154
172
7 . Remove the call in https://github.com/rust-lang/rust/blob/f8caa321c7c7214a6c5415e4b3694e65b4ff73a7/src/librustc_passes/ast_validation.rs#L306
@@ -189,14 +207,18 @@ can be applied to specific methods. E.g. `where <T as Add>::add: const` or somet
189
207
the sort. This design is more complex than the current one and we'd probably want the
190
208
current one as sugar anyway
191
209
192
- ## No explicit ` const ` bounds
210
+ ## Require ` const ` bounds everywhere
193
211
194
- One could require no ` const ` on the bounds (e.g. ` T: Trait ` ) and assume constness for all
195
- bounds. An opt-out via ` T: ?const Trait ` would then allow declaring bounds that cannot be
196
- used for calling methods. This design causes discrepancies with ` const fn ` pointers as
197
- arguments (where the constness would be needed, as normal function pointers already exist
198
- as the type of constants). Also it is not forward compatible to allowing ` const ` trait bounds
199
- on non-const functions
212
+ One could require ` const ` on the bounds (e.g. ` T: const Trait ` ) instead of assuming constness for all
213
+ bounds. That design would not be forward compatible to allowing ` const ` trait bounds
214
+ on non-const functions, e.g. in
215
+
216
+ ``` rust
217
+ fn foo <T : const Bar >() -> i32 {
218
+ const FOO : i32 = T :: bar ();
219
+ FOO
220
+ }
221
+ ```
200
222
201
223
## Infer all the things
202
224
@@ -283,6 +305,93 @@ Impl specialization is still unstable. There should be a separate RFC for declar
283
305
const impl blocks and specialization interact. For now one may not have both ` default `
284
306
and ` const ` modifiers on ` impl ` blocks.
285
307
308
+ ## ` const ` trait methods
309
+
310
+ This RFC does not touch ` trait ` methods at all, all traits are defined as they would be defined
311
+ without ` const ` functions existing. A future extension could allow
312
+
313
+ ``` rust
314
+ trait Foo {
315
+ const fn a () -> i32 ;
316
+ fn b () -> i32 ;
317
+ }
318
+ ```
319
+
320
+ Where all trait impls * must* provide a ` const ` function for ` a ` , allowing
321
+
322
+ ``` rust
323
+ const fn foo <T : ? const Foo >() -> i32 {
324
+ T :: a ()
325
+ }
326
+ ```
327
+
328
+ even though the ` ?const ` modifier explicitly opts out of constness.
329
+
330
+ ## ` ?const ` modifiers in trait methods
331
+
332
+ This RFC does not touch ` trait ` methods at all, all traits are defined as they would be defined
333
+ without ` const ` functions existing. A future extension could allow
334
+
335
+ ``` rust
336
+ trait Foo {
337
+ fn a <T : ? const Bar >() -> i32 ;
338
+ }
339
+ ```
340
+
341
+ which does not force ` impl const Foo for Type ` to now require passing a ` T ` with an ` impl const Bar `
342
+ to the ` a ` method.
343
+
344
+ ## ` const ` function pointers
345
+
346
+ ``` rust
347
+ const fn foo (f : fn () -> i32 ) -> i32 {
348
+ f ()
349
+ }
350
+ ```
351
+
352
+ is currently illegal. While we can change the language to allow this feature, two questions make
353
+ themselves known:
354
+
355
+ 1 . fn pointers in constants
356
+
357
+ ``` rust
358
+ const F : fn () -> i32 = ... ;
359
+ ```
360
+
361
+ is already legal in Rust today , even though the `F ` doesn 't need to be a `const ` function .
362
+
363
+ 2 . Opt out bounds are ugly
364
+
365
+ I don 't think it 's either intuitive nor readable to write the following
366
+
367
+ ```rust
368
+ const fn foo (f : ? const fn () -> i32 ) -> i32 {
369
+ // not allowed to call `f` here, because we can't guarantee that it points to a `const fn`
370
+ }
371
+ ```
372
+
373
+ Thus it seems useful to prefix function pointers to `const ` functions with `const `:
374
+
375
+ ```rust
376
+ const fn foo (f : const fn () -> i32 ) -> i32 {
377
+ f ()
378
+ }
379
+ const fn bar (f : fn () -> i32 ) -> i32 {
380
+ f () // ERROR
381
+ }
382
+ ```
383
+
384
+ This opens up the curious situation of ` const ` function pointers in non-const functions:
385
+
386
+ ``` rust
387
+ fn foo (f : const fn () -> i32 ) -> i32 {
388
+ f ()
389
+ }
390
+ ```
391
+
392
+ Which is useless except for ensuring some sense of "purity" of the function pointer ensuring that
393
+ subsequent calls will only modify global state if passed in via arguments.
394
+
286
395
# Unresolved questions
287
396
[ unresolved-questions ] : #unresolved-questions
288
397
0 commit comments