Skip to content

Unable to Use return in Delegate Method: Type Mismatch with RetainedReturnValue #731

@giantpand2000

Description

@giantpand2000

After resolving the previous issue #730 , I encountered a new problem. Based on the guidance, I modified my code and the previous issue was fixed. However, I now find that using an early return in a delegate method causes a type mismatch error.

For example, consider the following code:

unsafe impl NSTableViewDelegate for Delegate {
    #[unsafe(method_id(tableView:viewForTableColumn:row:))]
    unsafe fn table_view_view_for_table_column_row(
        &self,
        table_view: &NSTableView,
        table_column: Option<&NSTableColumn>,
        row: NSInteger,
    ) -> Option<Retained<NSTableCellView>> {
        let identifier = NSUserInterfaceItemIdentifier::from_str("cell");

        let Some(path) = self.ivars().playlist.files.get(row as usize) else {
            return None;
        };

        if let Some(cell_view) = table_view
            .makeViewWithIdentifier_owner(&identifier, Some(self))
            .and_then(|cell| cell.downcast::<NSTableCellView>().ok())
        {
            if let Some(text_field) = cell_view.textField() {
                text_field.setStringValue(&NSString::from_str(path));
            }
            return Some(cell_view);
        }

        None
    }
}

When compiling, I receive an error like:

mismatched types
expected struct `RetainedReturnValue`
     found enum `Option<_>`
rustcClick for full compiler diagnostic
define_class.rs(1292, 14): expected `RetainedReturnValue` because of return type

And upon macro expansion, the generated code looks similar to:

impl Delegate {
    #[allow(clippy::diverging_sub_expression)]
    unsafe extern "C-unwind" fn table_view_view_for_table_column_row(
        &self,
        _: objc2::runtime::Sel,
        table_view: <&NSTableView as objc2::__macro_helpers::ConvertArgument>::__Inner,
        table_column: <Option<&NSTableColumn> as objc2::__macro_helpers::ConvertArgument>::__Inner,
        row: <NSInteger as objc2::__macro_helpers::ConvertArgument>::__Inner,
    ) -> objc2::__macro_helpers::RetainedReturnValue {
        let table_view =
            <&NSTableView as objc2::__macro_helpers::ConvertArgument>::__from_defined_param(
                table_view,
            );
        let table_column =  <Option< &NSTableColumn>as objc2::__macro_helpers::ConvertArgument> ::__from_defined_param(table_column);
        let row = <NSInteger as objc2::__macro_helpers::ConvertArgument>::__from_defined_param(row);
        let __objc2_result = {
            let identifier = NSUserInterfaceItemIdentifier::from_str("cell");
            let Some(path) = self.ivars().playlist.files.get(row as usize) else {
                return None;
            };
            if let Some(cell_view) = table_view
                .makeViewWithIdentifier_owner(&identifier, Some(self))
                .and_then(|cell| cell.downcast::<NSTableCellView>().ok())
            {
                if let Some(text_field) = cell_view.textField() {
                    text_field.setStringValue(&NSString::from_str(path));
                }
                return Some(cell_view);
            }
            None
        };
        #[allow(unreachable_code)]
                        <objc2::__macro_helpers::MethodFamily<{
                            objc2::__macro_helpers::method_family("tableView")
                        }>as objc2::__macro_helpers::MessageReceiveRetained< &Self,Option<Retained<NSTableCellView>> , >>::into_return(__objc2_result)
    }
}

Using an early return (e.g., return Some(cell_view);) within the inner block causes the macro to expect a value of type RetainedReturnValue while it instead encounters an Option<_>. This forces me to rewrite the method without any early return statements. Although I can work around it using alternative coding styles, it is not immediately obvious that this restriction exists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-objc2Affects the `objc2`, `objc2-exception-helper` and/or `objc2-encode` cratesbugSomething isn't working

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions