Skip to content

Provide a way for derives to know if they were invoked with #[derive_const] #118304

@jhpratt

Description

@jhpratt
Member

As part of #67792, #[derive_const] is the current way to indicate that a derive should be impl const Trait rather than impl Trait. However, this only works for built-in macros. It should be possible for end-user proc macros to know if they were invoked with #[derive_const], permitting the derive to emit the appropriate code.

In my opinion, this could be an opaque type provided as an additional parameter to the derive implementation. That type would have methods to obtain constness and any other future extension (i.e. effects).

cc @fee1-dead per this Zulip comment.

@rustbot label +A-proc-macros +C-enhancement +F-const-trait-impl +T-libs-api

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Nov 26, 2023
added
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Nov 26, 2023
self-assigned this
on Dec 3, 2023
added
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Dec 4, 2023
fmease

fmease commented on Jul 1, 2024

@fmease
Member

PR #118580 extends support for #[derive_const] to user-defined derive proc-macros as outlined in the issue description. However, #[derive_const] itself is very ad-hoc and non-extensible as petrochenkov criticizes, justifiably so:

Both #[derive_const] itself, and this, are maximally ad hoc tools for addressing the issue.

How macros currently take their input - by a token stream, or two token streams if the macro has two inputs like #[attr(input1)] INPUT2.

This PR adds a third backdoor input tailored for a very specific use case.
The #[derive_const] added a whole new macro just to add one configuration bit to already existing #[derive] macro.

I would suggest keeping the current model and using already existing token-based methods for configuring macro behaviors.

  • Either helper attributes, like many derive macros, including derive_more, already do
  • Or giving derive macros the second input token stream - #[derive(Clone(input1))] INPUT2, that would also improve consistency with attributes.

Then the macros themselves can process the inputs as they want.
E.g. built-in macros could conventionally take a const token to produce a const impl - #[derive(Clone(const))] struct S;, others may accept more configuration.

If #[derive] needs some sugar to pass const to multiple derive macros that it applies at once, then it can grow such sugar itself, instead of delegating to a whole new special-purpose macro.
E.g. #[derive(const: Clone, PartialEq, PartialOrd)] struct S; or anything else, tokens inside the parentheses are an arbitrary token stream, I remind you, so #[derive] can create its own language for its input, like any other attribute macro.

Originally posted by @petrochenkov in #118580 (comment)

On a second thought, there's a third way to pass inputs - the "global data" in struct Rustc.

Proc macro methods without arguments like Span::call_site() take their return values from that global data. I also planned to add some more data there to be available to proc macros, like the kind of brackets used by the macro.

If "derive expansion options" are placed into struct Rustc, then there's no need to add a second parameter to #[proc_macro_derive] functions for passing them.

Originally posted by @petrochenkov in #118580 (comment)

What other similar configuration values we may need in the future?

Will we need to pass them to derive macros only, or for attribute possibly for attribute or fn-like macros too? With derive macros we have an intermediate layer, the #[derive] macro which has access to compiler magic to set such configuration values, but for attribute and fn-like macros we do not.

Originally posted by @petrochenkov in #118580 (comment)

fmease

fmease commented on Jul 1, 2024

@fmease
Member

I will therefore close the aforementioned PR and block this issue on further design work to be done by PG-const-traits Project group: Const traits and likely also WG-macros Working group: Macros .

added
S-blockedStatus: Blocked on something else such as an RFC or other implementation work.
WG-macrosWorking group: Macros
on Jul 1, 2024
illicitonion

illicitonion commented on Jul 17, 2025

@illicitonion
Contributor

It feels like there are three intentions that may be expressible:

  1. I want a const impl
  2. I want a non-const impl
  3. I want whatever impl you can give me - if you can const, great, if not, I'll take non-const

Do we intend to make each of these intentions signal-able? Particularly, will #[derive] imply 2 or 3? And will there be a way to express the other?

oli-obk

oli-obk commented on Jul 17, 2025

@oli-obk
Contributor

I don't think option 3 is doable without resorting to https://crates.io/crates/whichever-compiles (this is a joke, Option 3 is not possible, there is nothing that allows a proc macro to make a decision like that).

You can manually try a const derive, if that doesn't work either change sth to make it work or switch to a normal non-const derive.

illicitonion

illicitonion commented on Jul 17, 2025

@illicitonion
Contributor

I think it's more a question of transition from const traits not existing to them existing - let's imagine I have a proc macro which derives an trait that it can always derive in a const way.

Will callers need to explicitly switch from #[derive] to #[const_derive] in order to get the const version? Should it be an error to #[derive] a const Trait? Is it ok for a proc macro to give a const impl when called with #[derive]?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-trait-systemArea: Trait systemC-enhancementCategory: An issue proposing an enhancement or a PR with one.F-const_trait_impl`#![feature(const_trait_impl)]`PG-const-traitsProject group: Const traitsS-blockedStatus: Blocked on something else such as an RFC or other implementation work.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.WG-macrosWorking group: Macros

Type

No type

Projects

No projects

Milestone

No milestone

Participants

@oli-obk@illicitonion@jhpratt@fmease@fee1-dead

Issue actions

    Provide a way for derives to know if they were invoked with `#[derive_const]` · Issue #118304 · rust-lang/rust