nitro icon indicating copy to clipboard operation
nitro copied to clipboard

iOS build error when more than one optional callback

Open wvq opened this issue 9 months ago • 1 comments

What's happening?

when define more than one custom arguments optional callback.

If only one callback using custom arguments, the other callback's arguments are primitive types, it's OK.

Otherwise, build error.

Reproduceable Code

import { type HybridObject } from 'react-native-nitro-modules'

interface User {
  name: string
}

interface Profile {
  name: string
}

// optional callback in difference function
// build error
export interface MyNitroModule1
  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
  getUser(onSuccess?: (user: User) => void): void
  getProfile(onSuccess?: (profile: Profile) => void): void
}

// optional callback in same function
// build error
export interface MyNitroModule2
  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
  getUser(onSuccess?: (user: User) => void, onError?: (profile: Profile) => void): void
}

// optional callback but one using primitive type argument
// build success
export interface MyNitroModule3
  extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
  getUser(id: number, onSuccess?: (user: User) => void, onError?: (profile: number) => void): void
}

Relevant log output

Function type mismatch, declared as '@convention(method) (@in_guaranteed __ObjC.std.__1.optional<function<((_) -> Void)>>) -> @out __ObjC.std.__1.function<((_) -> Void)>' but used as '@convention(method) (@in_guaranteed __ObjC.std.__1.optional<function<((_) -> Void)>>) -> @out __ObjC.std.__1.function<((_) -> Void)>'

Multiple definitions of symbol '$sSo3stdO3__1O0044optionalfunction_Void_wmFAhaDqaBagAiwtiaCegaV7pointeeAD0032function_Void_jEEEdaJjatgIevqvbgVvg'

Device

iPhone 12 ProMax (iOS 16.3)

Nitro Modules Version

0.25.2

Nitrogen Version

0.25.2

Can you reproduce this issue in the Nitro Example app here?

Yes, I can reproduce the same issue in the Example app here

Additional information

wvq avatar Apr 30 '25 07:04 wvq

I'm also facing the same issue

maitrungduc1410 avatar May 24 '25 03:05 maitrungduc1410

This is funny - because your error message;

Function type mismatch, declared as '@convention(method) (@in_guaranteed __ObjC.std.__1.optional<function<((_) -> Void)>>) -> @out __ObjC.std.__1.function<((_) -> Void)>' but used as '@convention(method) (@in_guaranteed __ObjC.std.__1.optional<function<((_) -> Void)>>) -> @out __ObjC.std.__1.function<((_) -> Void)>'

..is literally the same two types;

declared as '@convention(method) (@in_guaranteed __ObjC.std.__1.optional<function<((_) -> Void)>>) -> @out __ObjC.std.__1.function<((_) -> Void)>'
but used as '@convention(method) (@in_guaranteed __ObjC.std.__1.optional<function<((_) -> Void)>>) -> @out __ObjC.std.__1.function<((_) -> Void)>'

lol

mrousavy avatar Aug 06 '25 11:08 mrousavy

Hey - can you try upgrading Nitro and Nitrogen to the latest versions and checking if you still have the same issue?

mrousavy avatar Aug 20 '25 13:08 mrousavy

interface User {
  name: string
}

interface Profile {
  name: string
}

Could it be that the compiler thinks those are the same types? What if you add one property (e.g. dummy: number) to only one of the interfaces? Will it compile then?

mrousavy avatar Aug 20 '25 13:08 mrousavy

I also noticed a similar issue with nitrogen regarding the callback. I’m writing a keyDown handling module for Android TV to register for events as a replacement for DeviceEventEmitter, but it doesn’t work either. On the JS side, I receive an error saying that it’s not a function. When I tried upgrading to version 0.29.1, I encountered an even stranger error

tconns avatar Aug 31 '25 02:08 tconns

@mrousavy no, it's still an build error. I ran a series of tests, multiple optional interfaces will build error, no matter those interfaces struct are same or not.

wvq avatar Sep 04 '25 16:09 wvq

no matter those interfaces struct are same or not.

But we use multiple interfaces here in the tests; https://github.com/mrousavy/nitro/blob/4647a6b6b0208848c561421ea663323db1e56819/packages/react-native-nitro-test/src/specs/TestObject.nitro.ts#L38-L72

... and they are all building & passing fine.

mrousavy avatar Sep 06 '25 12:09 mrousavy

@mrousavy maybe you wanna try fresh new react native project (new arch)

not the example project in your repo

maitrungduc1410 avatar Sep 07 '25 02:09 maitrungduc1410

In #650 I added a test for this.

interface TestObject extends HybridObject {
  // ...
  twoOptionalCallbacks(value: number, first?: (value: number) => void, second?: (value: string) => void): void
}

This builds and runs just fine:

Image

So I'm closing this issue

mrousavy avatar Oct 15 '25 09:10 mrousavy