jcw-gen
should warn about "duplicate" methods
#1215
Labels
callable-wrappers
Issues with Java Callable Wrappers
enhancement
Proposed change to current functionality
Background
(I forget what book I originally read this scenario from circa 30 years ago…)
Consider these two Java interfaces:
if you have an artist who is also a gunslinger, then they better need to do the same thing for
draw()
:This is one of those Don't Do That™ scenarios in Java: if the method implementation can't be the same, then the same type can't implement both interfaces:
C#, meanwhile, supports this scenario via explicit interface implementations:
"The Setup"
Explicit interface implementations thus provide one of the "semantic mismatches" between Java and C# (among many, to be fair!).
So what happens if we use them to implement bound Java interfaces?
Consider the following Java types:
These would be bound (abbreviated) in .NET for Android as:
…and because these are C# interfaces, we can explicitly implement them!
"The Concern"
What happens when we invoke
A.m()
andB.m()
from Java?What happens is
Hmmm.IA.M
is invoked twice:Why?
Because of the Java Callable Wrapper (abbreviated):
There Can Be Only One™ registration for
Hmmm.m()
, and the one we get is forExample.IA.M()
. (Which is order-dependent: if the interface implementation order isIB, IA
instead ofIA, IB
, thenHmmm.IB.M()
will be used.) The call toExample.IB.CallM(B)
doesn't fail (no exception) becauseHmmm
ISAB
, but it callsHmmm.IA.M()
, which might not be at all understandable to C# developers."The Ask"
We should consider updating
jcw-gen
to warn when this scenario is encountered: that is, when a single type implements the same Java-side method more than once.…but what about inheritance?
A related scenario to this already exists in .NET for Android, because many interface re-declare methods from their "base" interfaces, e.g.
java.util.Collection
declaresadd(Object)
, andjava.util.List
also declaresadd(Object)
:Related:
Which means we can explicitly implement
Add()
twice, already:The problems are the same: There Can Be Only One™
add()
method declared, so the marshal method chosen will depend upon the inheritance order (i.e. the marshal method forICollection.Add()
will be used), and the other method is Dead Code. No warning is emitted."The Ask" will also handle this scenario.
Another way to handle this scenario is to prevent it from happening in the first place. This scenario happens because we ignore warning CS0114 in our bindings, which allows
IList
to re-declareAdd()
, hidingICollection.Add()
. This only isn't a problem because explicit interface implementations are rarely used within bindings.If we instead didn't ignore CS0114, we could prevent this scenario by either:
IList.Add()
declaration, orIList
method declarations which have "identical declarations" from base interfaces (22d5687, 73ebad2)"Sanely" handling this scenario will require
generator
support, and may also constitute an ABI break (removingJava.Util.IList.Add()
could break existing code!). This might be something we only want to consider forJava.Base
(#858).The text was updated successfully, but these errors were encountered: