Let's call this test.kt:
interface WidthHeight1 {
val height: Float
val width: Float
}
interface WidthHeight2 {
val height: Double
val width: Double
}
~/.konan/kotlin-native-macos-1.3.1/bin/konanc test.kt -o test -p framework yields the following Obj-C protocols:
__attribute__((swift_name("WidthHeight1")))
@protocol TestWidthHeight1
@required
@property (readonly) float height __attribute__((swift_name("height")));
@property (readonly) float width __attribute__((swift_name("width")));
@end;
__attribute__((swift_name("WidthHeight2")))
@protocol TestWidthHeight2
@required
@property (readonly) double height_ __attribute__((swift_name("height_")));
@property (readonly) double width_ __attribute__((swift_name("width_")));
@end;
I'd expect neither to have underscore suffixes. IMO, it's on the programmer to figure out how a design like this should lead to valid code in the end. In other words, resolving this in Kotlin would be hard (having a class implement both interfaces), so it seems weird to fix the naming conflicts in Obj-C. Does this make sense?
Consider a Kotlin class implementing both interfaces.
If height property has the same Objective-C name for both of resulting protocols, then the class method table should have two functions with different binary types (one returning float, other returning double) for the same selector. How would you do that?
Right I don't think you can do that in Kotlin, so it seems weird that we would add namespacing to allow you to do it in Obj-C? Basically, you've designed yourself into a hole, so I think you (me the designer) needs to design yourself out of it. Do you see what I mean?
to allow you to do it in Obj-C
This is basically not the reason, please read by answer above.
I don't think you can do that in Kotlin
I bet I can:
private class WidthHeightImpl : WidthHeight1, WidthHeight2 {
override val height: Nothing
get() = TODO()
override val width: Nothing
get() = TODO()
}
Do you see what I mean?
I don't think so. Could you clarify?
Interesting. Is that the only way you can satisfy the interfaces in this scenario? If so, doesn't that seem impractical?
Consider a Kotlin class implementing both interfaces.
I would understand the namespacing if that were the case, but in this case, them merely existing together causes the namespacing to happen. That's the frustrating part: now we have to consider the global namespace for property names (and associated types) as common as width and height.
Is that the only way you can satisfy the interfaces in this scenario?
What do you mean by "this"?
If so, doesn't that seem impractical?
The compiler can't decide that some valid source code "seem impractical" and generate incorrect machine code for it. That's not what compilers do.
I would understand the namespacing if that were the case, but in this case, them merely existing together causes the namespacing to happen.
What do propose instead? How would you generate correct Objective-C method table in this case without mangling?
Sorry what I mean is that in my scenario, those interfaces exist in the same header, but they're never used/implemented together. If they were implemented by the same kotlin class and that class was exposed, I would understand that yes you need the suffixing. In my case, no single kotlin class is implementing them, so it doesn't matter that they have properties with the same name. Does that clarify?
If they were implemented by the same kotlin class and that class was exposed
The thing is: every Kotlin class potentially requires Objective-C class generated even if it is not exposed, since the instance of this Kotlin class may leak to Objective-C world.
So making translation conditional here would make it vary depending on private implementation too, which would lead to a translation strategy even more global and unpredictable than we have now.
Ah I see. Yep okay I understand now. Thanks for your patience!
Thank you for the report!
We completely understand limitations of current approach and have some considerations on improving the situation, but the problem is complicated enough, so it would take some time.
@SvyatoslavScherbina are the name mangling PRs that I see cropping up aimed at possibly addressing this?
I don't think so.
@SvyatoslavScherbina as discussed, I think the key issue here is that it's unexpected. Can something be added so that the compiler emits a log or other warning when it has to disambiguate in the Obj-C header?
This way, we can look for that during our build and manually fail the build ourselves and ask that engineers improve their method names.
Now that I've thought about this some more, it might be better to just add a compiler mode, similar to the new API mode, that emits a warning for each collision for interops where a collision had to be resolved this way, when enabled via a flag.