Repository navigation
Closed
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)A-trait-systemArea: Trait systemArea: Trait systemC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFC
Description
This is a tracking issue for trait bounds on const fns. The feature gate for the issue is #![feature(const_fn_trait_bound)]. This is not to be confused with the "trait impl must be const in const contexts" syntax, ~const Trait, which is a part of const_trait_impl and is tracked in #67792.
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
- Implement the feature (couldn't find the implementation PR;
const_fn_trait_boundwas split fromconst_fnin further split up const_fn feature flag #84310) - Adjust documentation (see instructions on rustc-dev-guide) Update const_eval.md for feature stabilization reference#1166
- Stabilization PR (see instructions on rustc-dev-guide) Stabilize const_fn_fn_ptr_basics, const_fn_trait_bound, and const_impl_trait #93827
Unresolved Questions
Implementation history
- #????? - Implementation
- further split up const_fn feature flag #84310 - Split
const_fn_trait_boundinto its own feature gate
@rustbot modify labels +A-const-fn +A-traits
Reacted by Gustav Trede, Vladas Zakrevskis and Aurelia Molzer
Reacted by Artur Sinila and Hudson Ayers
Metadata
Metadata
Assignees
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)A-trait-systemArea: Trait systemArea: Trait systemC-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFC
Activity
Rollup merge of rust-lang#93682 - PatchMixolydic:where-in-the-world-i…
Rollup merge of rust-lang#93682 - PatchMixolydic:where-in-the-world-i…
Rollup merge of rust-lang#93682 - PatchMixolydic:where-in-the-world-i…
Rollup merge of rust-lang#93682 - PatchMixolydic:where-in-the-world-i…
Rollup merge of rust-lang#93682 - PatchMixolydic:where-in-the-world-i…
fee1-dead commentedon Feb 7, 2022
cc @rust-lang/wg-const-eval: Should we remove this feature because of #90912?
oli-obk commentedon Feb 7, 2022
Yes, together with function pointers and trait objects. We just need a stabilization PR and a summary for the lang team
eholk commentedon Feb 11, 2022
I have a stabilization PR at #93827 and a documentation PR now at rust-lang/reference#1166.
Rollup merge of rust-lang#93827 - eholk:stabilize-const_fn-features, …
jplatte commentedon Mar 22, 2022
This has been stabilized in #93827, I'd really prefer if we could take a step back, revert that stabilization and consider an edition-based flow for getting
?constinstead of~constafterall:The few currently allowed bounds in
const fncould be transitioned to?constvia deprecation (plus more?constbounds allowed) in this edition, then the next edition can change the meaning of trait bounds without?constinconst fnand we can have the thing we originally wanted.I've voiced this idea on the tracking issue for the
impl const TraitRFC earlier: #67792 (comment)jhpratt commentedon Mar 22, 2022
What's wrong with having the stabilization that's already landed and switching to
?constin a future edition?RalfJung commentedon Mar 22, 2022
It's not just the bounds, it's also function pointers and trait objects that already made me advocate for this change long before the bounds stabilization hole was discovered.
A
T: Traitbound should be symmetric with&dyn Trait, so if the former implicitly gainsconstness so should the latter. However, this is stable since forever:jplatte commentedon Mar 22, 2022
Then you'd be stabilizing something just to deprecate it short after. But I guess it would be fine.
I think I've seen this argument before but forgot about it. To me personally, with how different and magic
dynalready is, I'm not convinced by this argument but I can see where you're coming from.RalfJung commentedon Mar 22, 2022
To add to the argument, consider the syntactic parallel between
implanddyn:The last two are the same by definition; the first two IMO should be the same as everything else would be really confusing.
If you consider
dyntoo much magic, let me note that this also affectsconst fn foo(x: fn()), but the syntactic symmetry is more striking withdyn. These (traits bounds,dyn,fn) are all just different ways to "abstract over code", and IMO their interaction withconstshould be consistent across the board.fee1-dead commentedon Mar 22, 2022
consider this:
If we go with the ~const approach, all of these will not impose additional requirements for the callers.
If we do ?const, some of them will be inconsistent, even if we made it consistent for the next edition it is going to be a pain to migrate, because all types (including fn pointers) now needs ?const to have the same behavior as before.
When you are arguing for ?const you are arguing for the fact that all of const trait bounds, const dyn traits, const impl traits, const fn pointers are used more frequently than their non-const versions in const contexts.
RalfJung commentedon Mar 22, 2022
Well, we could make all of them require
?const, but that is super backwards incompatible.(In
const fn,fnanddynare unstable -- or just have recently been stabilized together with the trait bounds. However, inconst/staticthey are stable and having the same type mean something different inconstvsconst fnsounds like a Bad Idea.)jplatte commentedon Mar 29, 2022
I thought about this for a while, and I am not convinced for two reasons:
First, I don't see why you would ever use
dyn Traitin aconst fnbut second and more importantly, I can now articulate this "dyn Traitis just inherently different" feeling I had before. Take the case of auto traits:It's not something people think about a lot, but once you do it's actually intuitive (IMHO): Because of the type erasure, you can't propagate auto traits.
Additionally, and this has been stated before but I think it's important to bring it up again: Requiring a
const implin a const context is simply the way more useful default, and it's a backwards-compatible change to add?const. People don't need to learn about all of this concept of "needs to be const impl if called in const context" until they actually need itm or come across an API that uses?const.Finally, and this isn't really a strong argument for either side I think, but I feel like I should point out that there are conceptually three cases for trait bounds in generic
const fn. This could probably be seen two ways, let me try to explain with a table:const implT: const Trait(?)T: const Trait(?)const implinconstcontextT: ~const TraitT: TraitimplT: TraitT: ?const TraitRalfJung commentedon Mar 30, 2022
For the same reasons you would use
dyn Traitin a regularfn.Yeah, return-type
impl Traitis semi-transparent, and in particular is transparent for auto traits. That's an odd quirk, but nothing fundamental and not conceptually very relevant in my eyes.I agree! IMO that also applies to
dyn Traitandfntypes.But I don't agree strong enough to be willing to sacrifice consistency for this.
Yes, I agree.
The "less weird" column however is inconsistent with how
?syntax is used elsewhere -- with?Sized, we have that writing nothing is equivalent to having aSizedbound. So I would expect that with?const, this indicates opting out of a defaultconst, so explicitly writingconstshould be the same as writing nothing.What this goes to show is that the situation is fundamentally different from
?Sized.jplatte commentedon Mar 30, 2022
Oh, I think I see. Theoretically we could have this behavior even for non-generic
const fn, there's no technical reasons preventing it. I didn't really consider that.Heh, so I guess this gives rise to yet another possible (but to me very unlikely) option:
const implT: const Trait(?)const implin const contextT: TraitorT: ~const TraitT: ?~const Traitoli-obk commentedon May 13, 2022
This has been stabilized in #93827