Skip to content

Allow #[method_id] in declare_class! #282

Description

@madsmtm

To make declare_class! and extern_class! closer in functionality (and make using declare_class! much safer in general)!

It'll probably make sense to start supporting super in msg_send_id! as well, see #173.

Example usage (where all of these could also return an Option<Id<_, _>>):

declare_class!(
    struct MyCustomObject;

    unsafe impl ClassType for MyCustomObject {
        type Super = NSObject;
    }

    unsafe impl MyCustomObject {
        #[method_id(newOnClass)]
        fn new() -> Id<Object, Shared> {
            todo!()
        }

        #[method_id(newOnInstance)]
        fn newOnInstance(&self) -> Id<Object, Shared> {
            todo!()
        }

        // Disallowed, since it requires a lot on the user to do correctly
        // #[method_id(alloc)]

        // Always requires `this: Allocated<Self>`
        // Class method `init` that returns an `Id` is disallowed
        #[method_id(init)]
        fn init(this: Allocated<Self>) -> Id<Self, Owned> {
            todo!()
        }

        #[method_id(copyOnClass)]
        fn copyOnClass() -> Id<Object, Shared> {
            todo!()
        }

        #[method_id(copyOnInstance)]
        fn copyOnInstance(&self) -> Id<Object, Shared> {
            todo!()
        }

        #[method_id(otherOnClass)]
        fn otherOnClass() -> Id<Object, Shared> {
            todo!()
        }

        #[method_id(otherOnInstance1)]
        fn otherOnInstance1(&self) -> Id<Object, Shared> {
            todo!()
        }

        #[method_id(otherOnInstance2)]
        fn otherOnInstance2(this: &Self) -> Id<Object, Shared> {
            todo!()
        }
    }
);

And what we should generate:

unsafe impl MyCustomObject {
    fn new(_cls: &Class, _cmd: Sel) -> *mut Object {
        <RT as DeclareClassId>::return_id::<Id<Object, Shared>>({
            todo!()
        }) // Manuallydrop
    }

    fn newOnInstance(&self, _cmd: Sel) -> *mut Object {
        <RT as DeclareClassId>::return_id::<Id<Object, Shared>>(
            todo!()
        }) // Manuallydrop
    }

    fn init(this: *mut Self, _cmd: Sel) -> *mut Self {
        let this = <RT as DeclareClassId>::convert_receiver(this);
        <RT as DeclareClassId>::return_id_this_checked::<Id<Self, Shared>>({
            todo!()
        }) // Manuallydrop
    }

    fn copyOnClass(_cls: &Class, _cmd: Sel) -> *mut Object {
        <RT as DeclareClassId>::return_id::<Id<Object, Shared>>({
            todo!()
        }) // Manuallydrop
    }

    fn copyOnInstance(&self, _cmd: Sel) -> *mut Object {
        <RT as DeclareClassId>::return_id::<Id<Object, Shared>>({
            todo!()
        }) // Manuallydrop
    }

    fn otherOnClass(_cls: &Class, _cmd: Sel) -> *mut Object {
        <RT as DeclareClassId>::return_id::<Id<Object, Shared>>({
            todo!()
        }) // Autorelease
    }

    fn otherOnInstance1(&self, _cmd: Sel) -> *mut Object {
        <RT as DeclareClassId>::return_id::<Id<Object, Shared>>({
            todo!()
        }) // Autorelease
    }

    fn otherOnInstance2(this: &Self, _cmd: Sel) -> *mut Object {
        let this = <RT as DeclareClassId>::convert_receiver(this);
        <RT as DeclareClassId>::return_id_this_checked::<Id<Self, Shared>>({
            todo!()
        }) // Autorelease
    }
}

I'm unsure if we should restrict class method new to always return Id<Self>? Probably not.

No activity

Activity on this issue will appear here.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-objc2Affects the `objc2`, `objc2-exception-helper` and/or `objc2-encode` cratesenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions