Skip to content
This repository has been archived by the owner on Sep 11, 2023. It is now read-only.

Use Generic Associated Types for Enum trait #35

Closed
wants to merge 2 commits into from
Closed

Conversation

KamilaBorowska
Copy link
Owner

No description provided.

@KamilaBorowska
Copy link
Owner Author

KamilaBorowska commented Jan 17, 2023

The biggest issue is the length calculation:

#[doc(hidden)]
pub const fn enum_len<E: Enum>() -> usize {
    E::Array::<()>::LENGTH
}

Can we ensure that lengths match for all generic types, and if it doesn't then can we ensure it won't cause unsafety.

@DCNick3
Copy link

DCNick3 commented Jan 17, 2023

Do you mean that for given E value E::Array::<V>::LENGTH should be the same for all V?

I don't think this can be enforced with rust type system, so probably make it a precondition of some unsafe trait (Enum in this case?)

Though I am not sure it is actually possible to write such code so it would be different w/o implementing the unsafe Array trait, hmm

@DCNick3
Copy link

DCNick3 commented Jan 19, 2023

As far as I understand:

  • if no unsafe impl's for Array trait are present, the only types implementing them are the array types [T; N]
  • The only way to refer to an array type generic over T is [T; N]
  • N must be some constant expression
  • You can't depend on generic parameter T in constant expression (example), so it's required to evaluate to the same constant no matter the T

As such, the array size can't change based on T.

Though, allowing the user to implement the Array trait complicates stuff... Is there any reason to allow it?

@KamilaBorowska
Copy link
Owner Author

KamilaBorowska commented Jan 20, 2023

Though, allowing the user to implement the Array trait complicates stuff... Is there any reason to allow it?

Array is sealed. internal is not a public module, and Array is intentionally not exported. Unless that doesn't work for effectively sealing traits? Even assuming it doesn't work, the trait is marked as unsafe, so implementations need to match its requirements.

@DCNick3
Copy link

DCNick3 commented Jan 20, 2023

Unless that doesn't work for effectively sealing traits?

It does. The usual way to seal a trait is to make it require another non-public one. Making the whole trait non-public should work too

Even assuming it doesn't work, the trait is marked as unsafe, so implementations need to match its requirements.

Fair, it's just not clear to me what the requirements would be (because it's kinda dependent on Enum implementations too..). w/o user impls it's easier to reason about, so it probably should be kept this way.

@DCNick3
Copy link

DCNick3 commented Feb 2, 2023

Have been trying out this feature. One kinda unfortunate thing with current implementation is how EnumMap generic over the key interacts with trait bounds like Clone.

I have a generic structure that looks like this:

pub struct ActionMap<A: Enum> {
    action_map: EnumMap<A, PetitSet<UserInput, 8>>,
}

Then, in the code, I want to use .clone on the action map. PetitSet implements Clone and, ideally, this should be the only thing that matters. Unfortunately, this does not work because Clone implementation for EnumMap requires A::Array: Clone. Logically, only Clone on the key should be there.

With the clone this can be hacked, for example, like this (based on impl of .map):

impl<K: Enum, V> Clone for EnumMap<K, V>
where
    V: Clone,
{
    #[inline]
    fn clone(&self) -> Self {
        let mut position = 0;
        enum_map! {
            _k => {
                let value = &self.as_slice()[position];
                position += 1;
                value.clone()
            }
        }
    }
}

Unfortunately, this doesn't work with Copy, as it is based on compiler magic and actually needs the A::Array: Copy bound.

DCNick3 added a commit to DCNick3/shin that referenced this pull request Jun 17, 2023
- enum-map to a newer version of the GAT PR (KamilaBorowska/enum-map#35)
- mp4 to the rebased Hdlr PR (alfg/mp4-rust#95)
enum-map reserves __EnumMapInternalV for this purpose. This
is not a part of stable API, and it's only necessary due
to not having stable def_site hygiene.
@DCNick3
Copy link

DCNick3 commented Sep 11, 2023

With this PR being closed, are there any plans to bring the GATs in some other form?

@KamilaBorowska
Copy link
Owner Author

@DCNick3 Right, I forgot to archive the repo. GitHub recommends to close pull requests before archiving, and the project is now migrated to Codeberg where the pull request is still open: https://codeberg.org/xfix/enum-map.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants