-
Notifications
You must be signed in to change notification settings - Fork 61
Description
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.