Skip to content

Commit 9c715d7

Browse files
committed
Explain with effect system syntax
1 parent d4637f9 commit 9c715d7

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

const-generic-const-fn-bounds.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ impl const Drop for Foo { fn drop(&mut self) {} } // not allowed
119119

120120
## Runtime uses don't have `const` restrictions
121121

122-
`impl const` blocks additionally generate impls that are not const if any generic
123-
parameters are not const.
122+
`impl const` blocks are treated as if the constness is a generic parameter
123+
(see also effect systems in the alternatives).
124124

125125
E.g.
126126

@@ -134,7 +134,23 @@ impl<T: Add> const Add for Foo<T> {
134134

135135
allows calling `Foo(String::from("foo")) + Foo(String::from("bar"))` even though that is (at the time
136136
of writing this RFC) most definitely not const, because `String` only has an `impl Add for String`
137-
and not an `impl const Add for String`.
137+
and not an `impl const Add for String`. Expressed in some sort of effect system syntax (neither
138+
effect syntax nor effect semantics are proposed by this RFC, the following is just for demonstration
139+
purposes):
140+
141+
```rust
142+
impl<constness c, T: const(c) Add> const(c) Add for Foo<T> {
143+
const(c) fn add(self, other: Self) -> Self {
144+
Foo(self.0 + other.0)
145+
}
146+
}
147+
```
148+
149+
In this scheme on can see that if the `c` parameter is set to `const`, the `T` parameter requires a
150+
`const Add` bound, and creates a `const Add` impl for `Foo<T>` which then has a `const fn add`
151+
method. On the other hand, if `c` is `?const`, we get a regular impl without any constness anywhere.
152+
Of course for regular impls one can still pass a `T` which has a `const Add` impl, but that won't
153+
cause any constness for `Foo<T>`.
138154

139155
This goes in hand with the current scheme for const functions, which may also be called
140156
at runtime with runtime arguments, but are checked for soundness as if they were called in
@@ -147,6 +163,18 @@ const fn add<T: Add>(a: T, b: T) -> T {
147163
}
148164
```
149165

166+
Using the same effect syntax from above:
167+
168+
```rust
169+
<constness c> const(c) fn add<T: const(c) Add>(a: T, b: T) -> T {
170+
a + b
171+
}
172+
```
173+
174+
Here the value of `c` decides both whether the `add` function is `const` and whether its parameter
175+
`T` has a `const Add` impl. Since both use the same `constness` variable, `T` is guaranteed to have
176+
a `const Add` iff `add` is `const`.
177+
150178
This feature could have been added in the future in a backwards compatible manner, but without it
151179
the use of `const` impls is very restricted for the generic types of the standard library due to
152180
backwards compatibility.

0 commit comments

Comments
 (0)