New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: const
functions in traits
#3490
base: master
Are you sure you want to change the base?
Conversation
@rustbot label +T-lang |
cc @rust-lang/wg-const-eval |
EDIT: In hindsight, I realise that I made this while tired and not fully understanding what this RFC is suggesting. Going to effectively retract my comments here, but will leave it for posterity. Going to be rather blunt: have you been following the development of const-fn-in-trait at all? Because, this is a planned goal, but one of the reasons why keyword generics exist in the first place is to solve this problem. This RFC strikes me as being written by someone who hasn't followed that development, and just wants const trait support sooner. The problem is that we really can't offer it much sooner than finishing up the existing proposals. Sure, we could tag some functions as |
I am not familiar with anything specifically called
It is true that this RFC is encompassed by the effects goals. But effects are still very much in the experimentation stage and have a much larger and more complex scope (I have to assume we are still many months away from RFCs), so it did not seem there would be any harm in proposing a minor and fairly unobjectionable subset at this time. I also did some due diligence to ensure this wouldn't conflict 1 2. I also have to disagree that this isn't useful on its own, I come across uses quite frequently in projects that use a lot of statics (e.g. modular C+Rust projects). |
I know I definitely will use this, currently I have to make-do with a bunch of My motivating use-case is compile-time checking of properties of a domain-specific language embedded in Rust. |
This is allowed in [`rust-lang/rust`](https://github.com/rust-lang/rust/blob/62d9034a0d571b78e518727d6cb4b090569e5238/triagebot.toml#L12). Others have also expected it to work here: - rust-lang#3490 (comment) - rust-lang#3485 (comment) @rustbot label not-rfc
While some form of optional const-ness is needed in traits, regardless of how that is done, always const functions are something that you should be able to do. Since a trait is a contract and so its natural to be able to add const-ness to that contract, and this is exactly what has been done for async, you can add async to the contract to force a function to always be async so extending that to const is only natural. Plus I would definitely use this if it existed. |
Would refinining a trait method by adding |
I don't intend to cover allowing Thanks for bringing it up, I added that under future possibilities. |
I'd like to share a concrete usecase for this feature. In the RFC: Introduce the Store API for great good the If this RFC were to be accepted, the Store API could be simplified to a single |
Workarounds typically involve a combination of wrapper functions, macros, and | ||
associated consts. This RFC will eliminate the need for such workarounds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel it may be useful to note some of these workarounds?
Essentially, I'm searching for an illustration of what is possible (although maybe hugely inconvenient and ugly) in current Rust, and what new possibilities would be enabled by this proposal, if any?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean that you are looking for a sample of what a solution might look like today? Or just a more in depth explanation from the list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just a better explanation of each workaround or the use cases would be best, current examples are usually pretty large and vary a lot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, mostly I fear that there may be a lot of edge-cases that have not yet been considered in the proposal?
And then I think that if I saw a few instances of "this thing can already be done today, just not as cleanly", then it'd assuage my worries on that front.
text/0000-const-fn-in-trait.md
Outdated
/// Add a named item to our global state register | ||
const fn register_state<T: GlobalState>(name: &'static str, item: T) { | ||
// ... | ||
STATES[0] = (name, item.build()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should provide some base_value
to the build
method
Just a small question: how would this work with trait objects? Will For instance: trait Foo {
const fn foo();
}
fn run_any_foo(trait_object: &dyn Foo) {
trait_object.foo();
}
const fn run_any_foo(trait_object: &dyn Foo) {
trait_object.foo();
} If a I don't have any specific ideas for changes to the RFC, I'm just making sure trait objects aren't forgotten. :) |
Co-authored-by: Mads Marquart <mads@marquart.dk>
Co-authored-by: Mads Marquart <mads@marquart.dk>
That is a great question! At runtime, I think maybe it is best to leave thta under unresolved questions or future possibilities for now, since more information will probably become apparent at implementation time. I'll update the RFC soon |
I think that can be left for when we get function pointers with const in the type, which is presumably what the methods will essentially be: pub const fn call_it(f: const fn() -> i32) -> i32 {
f()
} |
Responding after re-reading the RFC, understanding for real what's actually going on. I've marked my previous comment to clarify that I really wasn't responding properly to this RFC, although I don't like deleting things since it makes discussions confusing to read. I agree that having The reason why I had such a knee-jerk reaction to the RFC is because, well… there's the issue of potentially abusing this feature until keyword generics are released, where people start offering const and non-const versions of traits. This will just make migrating back into keyword generics a headache, although I agree that simply not having functionality in the meantime is a bad solution. Overall it's just really confusing to reason about |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the main issue with this is that of technical debt. If we ever wanted traits like Iterator
s to be const and usable in const contexts, then we need to introduce constness to those traits in a backwards-compatible way. This RFC cannot help with eventually making Iterator
const, since adding const
to a trait function would be a breaking change. This means that a future RFC that proposes "const traits", like the experimental feature we currently have under const_trait_impl
and effects
will eventually need to be proposed.
But, if we allow the ability to have const functions in traits, we are suggesting traits like ConstAdd
or ConstIterator
so that someone can use those traits in const functions with generic parameters. Perhaps this works fine when someone is implementing something like a generic factorial function and all the types they are handling can have subtraction and multiplication done in compile time, but this potentially creates fragmentation where non-const functions are unable to call generic const
functions due to the strict trait impl requirements. If we are pushing to stabilize this faster than const traits, then this would be concerning.
Also, cc @rust-lang/wg-const-eval since I didn't get notified for the first ping it seems
|
||
Adding this feature approaches the goal of "Rust working like one would expect | ||
it to work". That is, functions in traits generally act similar to functions | ||
outside of traits, and this feature serves to bridge one of the final gaps |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like you didn't finish this sentence here
This feature requires tracking more information related to trait definition and | ||
usage, but this should be a relatively maintenance burden. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
relatively low?
standard `const` functions when needed at CTFE. This additional metadata can be | ||
stripped in all other cases and the function will act the same as a non-const | ||
function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that is what we do with const functions? IIRC marking a function has const can change inliner behavior, but I might just be misremembering.
- Reducing code duplication in const contexts | ||
- Providing a constructor for generic static object, e.g. C-style plugin | ||
registration | ||
- Subtraits that want to provide defaults based on supertraits |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what this use case is and why it relates to const functions in traits, could you specify?
const<C> trait SometimesConstFoo { | ||
const <C> fn sometimes_const_foo(&self) -> u32 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not equivalent to const functions in traits, because there is no parameterization based on constness on the trait. Under effects, const functions in traits will become generic over constness itself, but not the traits (but we still treat it as a non-generic in different parts of rustc, something like foo<'a>
)
I would prefer to postpone this RFC until we have a good implementation of const traits. Landing this RFC would suggest that we'd also work on it, and I don't think we can do that until const the const traits work settles down, as it's already hard enough to keep one major |
Thanks for taking a look! With the potential conflicting work in mind, I don't see this going anywhere anytime soon. I'll leave it around for now though as a draft just to continue collecting any feedback |
Indeed, it cannot, but I do not see this as a problem. We can today have inherent I already mentioned the usecase of the The clearly better API is for the In the end, we need the flexibility of both
I'm ambivalent on this. I understand the motivation, however it may also be worth accepting such an RFC to signal that |
We don't even have an accepted const trait RFC 😅 |
Rendered
This RFC allows marking methods in traits as
const
.