Skip to content

Commit

Permalink
Explain with effect system syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jan 23, 2019
1 parent d4637f9 commit 9c715d7
Showing 1 changed file with 31 additions and 3 deletions.
34 changes: 31 additions & 3 deletions const-generic-const-fn-bounds.md
Expand Up @@ -119,8 +119,8 @@ impl const Drop for Foo { fn drop(&mut self) {} } // not allowed

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

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

E.g.

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

allows calling `Foo(String::from("foo")) + Foo(String::from("bar"))` even though that is (at the time
of writing this RFC) most definitely not const, because `String` only has an `impl Add for String`
and not an `impl const Add for String`.
and not an `impl const Add for String`. Expressed in some sort of effect system syntax (neither
effect syntax nor effect semantics are proposed by this RFC, the following is just for demonstration
purposes):

```rust
impl<constness c, T: const(c) Add> const(c) Add for Foo<T> {

This comment was marked as resolved.

Copy link
@RalfJung

RalfJung Jan 23, 2019

Member

Should be c: constness. We don't use "type variable" anywhere in Rust.

const(c) fn add(self, other: Self) -> Self {
Foo(self.0 + other.0)
}
}
```

In this scheme on can see that if the `c` parameter is set to `const`, the `T` parameter requires a
`const Add` bound, and creates a `const Add` impl for `Foo<T>` which then has a `const fn add`
method. On the other hand, if `c` is `?const`, we get a regular impl without any constness anywhere.
Of course for regular impls one can still pass a `T` which has a `const Add` impl, but that won't
cause any constness for `Foo<T>`.

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

Using the same effect syntax from above:

```rust
<constness c> const(c) fn add<T: const(c) Add>(a: T, b: T) -> T {
a + b
}
```

Here the value of `c` decides both whether the `add` function is `const` and whether its parameter
`T` has a `const Add` impl. Since both use the same `constness` variable, `T` is guaranteed to have
a `const Add` iff `add` is `const`.

This feature could have been added in the future in a backwards compatible manner, but without it
the use of `const` impls is very restricted for the generic types of the standard library due to
backwards compatibility.
Expand Down

0 comments on commit 9c715d7

Please sign in to comment.