Skip to content
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

Improving mapping of generic types #316

Closed
madsmtm opened this issue Dec 27, 2022 · 1 comment · Fixed by #419
Closed

Improving mapping of generic types #316

madsmtm opened this issue Dec 27, 2022 · 1 comment · Fixed by #419
Labels
A-framework Affects the framework crates and the translator for them enhancement New feature or request
Milestone

Comments

@madsmtm
Copy link
Owner

madsmtm commented Dec 27, 2022

Currently, we're mapping generic types roughly as:

extern_class!(
    #[derive(PartialEq, Eq, Hash)]
    pub struct NSArray<T: Message = Object, O: Ownership = Shared> {
        p: PhantomData<Id<T, O>>,
    }

    unsafe impl<T: Message, O: Ownership> ClassType for NSArray<T, O> {
        type Super = NSObject;
    }
);

impl<T: Message, O: Ownership> NSArray<T, O> {
    fn get(&self, index: usize) -> Option<&T>;
}

impl<T: Message> NSArray<T, Owned> {
    fn get_mut(&mut self, index: usize) -> Option<&mut T>;
}

But this can be a bit limiting, since there's no easy way to carry any lifetime information in the type. Also, it is IMO a bit confusing to see Id<NSArray<NSObject, Shared>, Shared>, and this only gets worse on types with multiple generics (like NSDictionary).

So perhaps we could instead introduce a helper trait and do it like this:

trait Foo: Sealed {
    type Item: Message;
    type Ownership: Ownership;
}

impl<T: Message> Foo for &T {
    type Item = T;
    type Ownership = Shared;
}
impl<T: Message> Foo for &mut T {
    type Item = T;
    type Ownership = Owned;
}
impl<T: Message, O: Ownership> Foo for Id<T, Owned> {
    type Item = T;
    type Ownership = O;
}

// Usage

extern_class!(
    #[derive(PartialEq, Eq, Hash)]
    pub struct NSArray<T: Foo> {
        p: PhantomData<T>,
    }

    unsafe impl<T: Foo> ClassType for NSArray<T> {
        type Super = NSObject;
    }
);

impl<T: Foo> NSArray<T> {
    fn get(&self, index: usize) -> Option<&T>;
}

impl<T: Foo<Owneship = Owned>> NSArray<T> {
    fn get_mut(&mut self, index: usize) -> Option<&mut T>;
}

Where usage would then be Id<NSArray<&NSObject>, Shared> or Id<NSArray<Id<NSObject, Shared>>, Shared>.

This will also help with #304, since -[NSEnumerator nextObject] by itself could now be safe by default (though -[NSArray objectEnumerator] would still be unsafe).

@madsmtm madsmtm added enhancement New feature or request A-framework Affects the framework crates and the translator for them labels Dec 27, 2022
@madsmtm madsmtm added this to the icrate v0.2.0 milestone Jan 27, 2023
@madsmtm madsmtm modified the milestones: icrate v0.2.0, objc2 v0.3 Feb 2, 2023
@madsmtm
Copy link
Owner Author

madsmtm commented Apr 15, 2023

I'll be choosing the even simpler option in #419, which is just removing the Ownership parameter, and assuming that generic types hold an Id<T> internally. This is a tiny bit more restrictive than technically necessary, but I suspect it will be good enough for most of the common cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-framework Affects the framework crates and the translator for them enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant