derive_more icon indicating copy to clipboard operation
derive_more copied to clipboard

`AsRef` for `enum`

Open ModProg opened this issue 3 years ago • 3 comments
trafficstars

This would require you to put the correct attributes on each enum variant, same as for the struct derive:

We would maybe need to be able to specify the actual type here, this would be necessary in case of forward when there are two different types that only share a subset of AsRef implementations.

#[derive(AsRef)]
pub enum Enum {
  #[as_ref(forward)
  Tuple(Forward),
  Struct{
    #[as_ref]
    actual: Actual,
    // ...
  },
  // ...
}

ModProg avatar Nov 13 '22 08:11 ModProg

Seems like a useful enhancement. Especially the simple case seems easy to implement where both variants have the same type.

JelteF avatar Dec 19 '23 00:12 JelteF

After I ran into this again, I thought I might as well start working on it.

Will only implement the simple case where everything has the same type for now.

I think it would make sense to allow #[as_ref(forward)] and #[as_ref(<types>)] on item level for enums:

#[derive(AsRef)]
#[as_ref(forward)] // or #[as_ref(Type)]
enum Enum {
    NewType(Type),
    Multiple(#[as_ref] Type, Other),
}

I would probably mirror this to structs while keeping placing this information on the field valid:

// current
#[derive(AsRef)]
struct OnField(#[as_ref(forward)] Field, Other);

// will also be valid
#[derive(AsRef)]
#[as_ref(forward)]
struct OnStruct(#[as_ref] Field, Other);

I could also implement a check disallowing it on structs, but IMO there is little value gained by restricting item attributes to structs.

ModProg avatar Apr 05 '24 20:04 ModProg

I'm gonna write down some more thoughts:

if no types are specified, or forward is used, every field annotated with #[as_ref] would be required to be the same type? The issue here could be fmt::Error vs std::fmt::Error, which, in a naive implementation of the check, would yield an error.

Without the use of forward it's pretty simple, this is the direct more, i.e. &field is returned directly. In this case rust would do the type checking for use. We could just use the type of the first variant, and rust would error that the field in the second variant has a different type correctly.

With forward though, I'm not sure, we could either dissallow forward on enums, or we could do the same, use the first fields type, and just call as_ref on all the other fields. This would mean, when using forward on an enum, the condition is, that all other fields implement AsRef for a superset of types that the first field implements AsRef for.

I'd be fine implementing either. We could also avoid this topic by disallowing forward on enums for now, keeping it open to add at a later point.

ModProg avatar Apr 05 '24 20:04 ModProg