8
8
9
9
Allow ` const impl ` s for trait impls where all method impls are checked as const fn.
10
10
11
- Make it legal to declare trait bounds on generic parameters of ` const fn ` and allow
12
- the body of the const fn to call methods on these generic parameters.
11
+ Make it legal to declare trait bounds on generic parameters of const functions and allow
12
+ the body of the const fn to call methods on the generic parameters that have a ` const ` modifier
13
+ on their bound.
13
14
14
15
# Motivation
15
16
[ motivation ] : #motivation
@@ -21,26 +22,26 @@ generic parameter type), because they are fully unconstrained.
21
22
# Guide-level explanation
22
23
[ guide-level-explanation ] : #guide-level-explanation
23
24
24
- You can call call methods of generic parameters of ` const fn ` , because they are implicitly assumed to be
25
- ` const fn ` . For example, even though the ` Add ` trait declaration does not contain any mention of ` const ` ,
25
+ You can call 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
26
27
you can use it as a trait bound on your generic parameters:
27
28
28
29
``` rust
29
- const fn triple_add <T : Add >(a : T , b : T , c : T ) -> T {
30
+ const fn triple_add <T : const Add >(a : T , b : T , c : T ) -> T {
30
31
a + b + c
31
32
}
32
33
```
33
34
34
35
The obligation is passed to the caller of your ` triple_add ` function to supply a type whose ` Add ` impl is fully
35
36
` const ` . Since ` Add ` only has ` add ` as a method, in this case one only needs to ensure that the ` add ` method is
36
- ` const fn ` . Instead of adding a ` const ` modifier to all methods of a trait impl, the modifier is added to the entire
37
+ ` const ` . Instead of adding a ` const ` modifier to all methods of a trait impl, the modifier is added to the entire
37
38
` impl ` block:
38
39
39
40
``` rust
40
41
struct MyInt (i8 );
41
42
const impl Add for MyInt {
42
43
fn add (self , other : Self ) -> Self {
43
- MyInt (self . 0 , other . 0 )
44
+ MyInt (self . 0 + other . 0 )
44
45
}
45
46
}
46
47
```
@@ -65,23 +66,17 @@ const impl Hash for MyInt {
65
66
# Reference-level explanation
66
67
[ reference-level-explanation ] : #reference-level-explanation
67
68
68
- This is the technical portion of the RFC. Explain the design in sufficient detail that:
69
-
70
- - Its interaction with other features is clear.
71
- - It is reasonably clear how the feature would be implemented.
72
- - Corner cases are dissected by example.
73
-
74
- The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work.
69
+ The implementation of this RFC is (in contrast to some of its alternatives) mostly
70
+ changes around the syntax of the language (adding ` const ` modifiers in a few places)
71
+ and ensuring that lowering to HIR and MIR keeps track of that.
72
+ The miri engine already fully supports calling methods on generic
73
+ bounds, there's just no way of declaring them.
75
74
76
75
# Drawbacks
77
76
[ drawbacks ] : #drawbacks
78
77
79
- One cannot add trait bounds to ` const fn ` without them automatically
80
- requiring ` const impl ` s for all monomorphizations. Even if one does not
81
- call any method on the generic parameter, the methods are still required to be constant.
82
-
83
78
It is not a fully general design that supports every possible use case,
84
- but only covers the most common cases. See also the alternatives.
79
+ but it covers the most common cases. See also the alternatives.
85
80
86
81
# Rationale and alternatives
87
82
[ rationale-and-alternatives ] : #rationale-and-alternatives
@@ -97,13 +92,17 @@ and this RFC is forward compatible to have its background impl be an effect syst
97
92
One could annotate methods instead of impls, allowing just marking some method impls
98
93
as const fn. This would require some sort of "const bounds" in generic functions that
99
94
can be applied to specific methods. E.g. ` where <T as Add>::add: const ` or something of
100
- the sort.
95
+ the sort. This design is more complex than the current one and we'd probably want the
96
+ current one as sugar anyway
101
97
102
- ## Explicit ` const ` bounds
98
+ ## No explicit ` const ` bounds
103
99
104
- One could require ` T: const Trait ` bounds to differentiate between bounds on which methods
105
- can be called and bounds on which no methods can be called. This can backwards compatibly be
106
- added as an opt-out via ` T: ?const Trait ` if the desire for such differences is strong.
100
+ One could require no ` const ` on the bounds (e.g. ` T: Trait ` ) and assume constness for all
101
+ bounds. An opt-out via ` T: ?const Trait ` would then allow declaring bounds that cannot be
102
+ used for calling methods. This design causes discrepancies with ` const fn ` pointers as
103
+ arguments (where the constness would be needed, as normal function pointers already exist
104
+ as the type of constants). Also it is not forward compatible to allowing ` const ` trait bounds
105
+ on non-const functions
107
106
108
107
## Infer all the things
109
108
@@ -117,7 +116,40 @@ This is strictly the most powerful and generic variant, but is an enormous backw
117
116
hazard as changing a const fn's body to suddenly call a method that it did not before can break
118
117
users of the function.
119
118
119
+ # Future work
120
+
121
+ This design is explicitly forward compatible to all future extensions the author could think
122
+ about. Notable mentions (see also the alternatives section):
123
+
124
+ * an effect system with a "notconst" effect
125
+ * const trait bounds on non-const functions allowing the use of the generic parameter in
126
+ constant expressions in the body of the function or maybe even for array lenghts in the
127
+ signature of the function
128
+ * fine grained bounds for single methods and their bounds
129
+
130
+ It might also be desirable to make the automatic ` Fn* ` impls on function types and pointers ` const ` .
131
+ This change should probably go in hand with allowing ` const fn ` pointers on const functions
132
+ that support being called (in contrast to regular function pointers).
133
+
120
134
# Unresolved questions
121
135
[ unresolved-questions ] : #unresolved-questions
122
136
123
- None
137
+ Should ` const impl ` blocks additionally generate impls that are not const if any generic
138
+ parameters are not const?
139
+
140
+ E.g.
141
+
142
+ ``` rust
143
+ const impl <T : Add > Add for Foo <T > {
144
+ fn add (self , other : Self ) -> Self {
145
+ Foo (self . 0 + other . 0 )
146
+ }
147
+ }
148
+ ```
149
+
150
+ would allow calling ` Foo(String::new()) + Foo(String::new()) ` even though that is (at the time
151
+ of writing this RFC) most definitely not const.
152
+
153
+ This would go in hand with the current scheme for const functions, which may also be called
154
+ at runtime with runtime arguments, but are checked for soundness as if they were called in
155
+ a const context.
0 commit comments