-
Notifications
You must be signed in to change notification settings - Fork 54
Description
This happens if a scala trait that doesn't extend a vanilla class declares a method with the same name as something in a vanilla class, then a class mixes this trait with that class, for example:
trait A {
def getWorldObj: World
}
class B extends TileEntity with A
object C {
def foo(p: A) = p.getWorldObj
def bar(p: B) = p.getWorldObj
}
This compiles and works correctly in an unobfuscated environment.
After reobfuscation C.bar gets changed to the obfuscated name as expected
0: aload_1
1: invokevirtual #30 // Method test/B.func_145831_w:()Lnet/minecraft/world/World;
4: areturn
But the interface and C.foo still refers to the unobfuscated name
0: aload_1
1: invokeinterface #20, 1 // InterfaceMethod test/A.getWorldObj:()Lnet/minecraft/world/World;
6: areturn
And a call to C.foo will crash with
java.lang.AbstractMethodError: test.B.getWorldObj()Lnet/minecraft/world/World;
I made a minimal project to demonstrate the issue - it will crash in PreInit when running in an obfuscated environment.
Same thing can also happen in java (though i guess it's less common to do something like that without mixins)
public interface A {
World getWorldObj();
}
public class B extends TileEntity implements A {
}
public class C {
static World foo(A p) {
return p.getWorldObj();
}
static World foo(B p) {
return p.getWorldObj();
}
}
Gives exactly the same result.
I'm not even sure how this can be fixed, creating a synthetic bridge method during reobfuscation? Would that be possible or even be a good idea?