Skip to content

Commit 290d7fe

Browse files
committed
Add per-method annotations alternative
1 parent 545099b commit 290d7fe

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

text/0000-const-trait-impls.md

+41-1
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,45 @@ With the opt-out scheme that would still compile, but suddenly require callers t
641641
The safe default (and the one folks are used to for a few years now), is that trait bounds just work, you just
642642
can't call methods on them. To get more capabilities, you add more syntax. Thus the opt-out approach was not taken.
643643

644+
## Per-method constness instead of per-trait
645+
646+
We could require trait authors to declare which methods can be const:
647+
648+
```rust
649+
trait Default {
650+
const fn default() -> Self;
651+
}
652+
```
653+
654+
This has two major advantages:
655+
656+
* you can now have const and non-const methods in your trait without requiring an opt-out
657+
* you can add new methods with default bodies and don't have to worry about new kinds of breaking changes
658+
659+
The specific syntax given here may be confusing though, as it looks like the function is always const, but
660+
implementations can use non-const impls and thus make the impl not usable for `T: ~const Trait` bounds.
661+
662+
Though this means that changing a non-const fn in the trait to a const fn is a breaking change, as the user may
663+
have that previous-non-const fn as a non-const fn in the impl, causing the entire impl now to not be usable for
664+
`T: ~const Trait` anymore.
665+
666+
See also: out of scope RTN notation in [Unresolved questions](#unresolved-questions)
667+
668+
## Per-method and per-trait constness together:
669+
670+
To get the advantages of the per-method constness alternative above, while avoiding the new kind of breaking change, we can require per-method and per-trait constness:
671+
672+
A mixed version of the above could be
673+
674+
```rust
675+
const trait Foo {
676+
const fn foo();
677+
fn bar();
678+
}
679+
```
680+
681+
where you still need to annotate the trait, but also annotate the const methods.
682+
644683
# Prior art
645684
[prior-art]: #prior-art
646685

@@ -669,9 +708,10 @@ can't call methods on them. To get more capabilities, you add more syntax. Thus
669708
* `T: Iterator<Item = U>` and don't require `where T: Iterator, <T as Iterator>::Item = U`.
670709
* `T: Iterator<Item: Debug>` and don't require `where T: Iterator, <T as Iterator>::Item: Debug`.
671710
* RTN for per-method bounds: `T: Trait<some_fn(..): ~const Fn(A, B) -> C>` could supplement this feature in the future.
711+
* Alternatively `where <T as Trait>::some_fn(..): ~const` or `where <T as Trait>::some_fn \ {const}`.
672712
* Very verbose (need to specify arguments and return type).
673713
* Want short hand sugar anyway to make it trivial to change a normal function to a const function by just adding some minor annotations.
674-
* Significantly would delay const trait stabilization.
714+
* Significantly would delay const trait stabilization (by years).
675715
* Usually requires editing the trait anyway, so there's no "can constify impls without trait author opt in" silver bullet.
676716
* New RTN-like per-method bounds: `T: Trait<some_fn(_): ~const>`.
677717
* Unclear if soundly possible.

0 commit comments

Comments
 (0)