error: the `#[default]` attribute may only be used on unit enum variants
--> src/main.rs:6:5
|
6 | FirstVar(FirstVariant),
| ^^^^^^^^
|
= help: consider a manual implementation of `Default`
My request is for someone to enable Default derive attribute on DefaultingEnum to use the default value of FirstVariant inside the FirstVar variant instead of saying that it can't be done.
Yeah, it was requested that it be removed due to the lack of consensus on what the generated bounds be. If that can be resolved, there is zero reason it couldn't be added.
would it be possible to add Default non-unit variants for one category of scenarios at a time? For example you might start by allowing Default non-unit variants in the case where the non-unit variant's inner value has a primitive type as its default (i.e. explicitly written out value, which shouldn't cause cyclic dependency), or if it's a tree of defaults then allowing the non-unit default at the root if all the leaves of the tree are primitive types.
so you can then expand the macro before the type is resolved, and then you can resolve the type and perform the compile-time analysis to let the Default macro know that the enum variant's inner value is a primitive type?
Not just that – seems like we could allow #[default] on any variant that does not refer to any generic parameter of the enum, without having to resolve any questions about how to decide bounds.
I was about to say not quite — it could be a valid choice to emit the "imperfect" bounds that are generated for generic struct when deriving for generic enum — but checking, we do already allow #[default] for unit variants of generic enum without creating any additional impl bounds.
Due to that, I agree that extending #[default] to support non-unit variants that do not use any generic captures is straightforward. (Unfortunately, this includes not using generic lifetimes (or the semi-implicit capture that is the Self type), since impls can be lifetime-dependent, which could still be surprising.)
I think the only option ruled out is to emit "imperfect" bounds whenever #[default] is used on a non-unit variant, whether it captures generics or not. Given we don't emit bounds when on unit variants, I think this is a bad "spooky action" option that we should be okay with ruling out.
I don't think that's possible for a proc macro to detect. The variant can use an associated type -- perhaps even via TAIT tricks somehow -- without naming the type parameter's token, I think.
Really? It does sound like the general [category of hazard of interacting features] that one needs to consider, but how would the compiler ever know you meant an associated type of that type parameter, rather than of some other type (parameter or otherwise) that met the same bounds, without you writing the token?
Note that Scott is mentioning TAIT here — type alias impl trait. You can't easily have TAIT implicitly capture generics like RPIT does, but it might be possible behind some tricks. Forbidding any mention of the generic names (including Self) before type normalization (i.e. syntactically) should in theory be sufficient.
The most obvious other potential "hole" is that despite being a semi-inert attribute, derives are expanded before a non-inert proc macro attribute which is "inside" it, seeing the attribute itself in its token stream. This means that a proc macro transformation after the derive could change the definition of the variant. However, I don't think that's an issue per say, rather just how derives work.
EDIT: whoops this post got buffered for an hour and got ninja'd