Skip to content

Allow #[method_id] in declare_class! #282

@madsmtm

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.

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