-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Duplicate method name&signature in class file (lambda on AnyVal subclass argument) #6260
Comments
Imported From: https://issues.scala-lang.org/browse/SI-6260?orig=1 |
@paulp said: final class Boxy(val x: Object) extends AnyVal { }
object Test {
def crash(f: () => Boxy) = ()
def main(args: Array[String]): Unit = crash(() => new Boxy(""))
} The value classes want to generate bridge methods; so does Function0. They collide with the same signature in the closure. |
@odersky said: |
@odersky said: |
@paulp said: class X(val value: Object) extends AnyVal { def or(alt: => X): X = this }
class Y { def f = new X("") or new X("") }
// ./a.scala:2: error: bridge generated for member method apply: ()X in anonymous class $anonfun
// which overrides method apply: ()R in trait Function0
// clashes with definition of the member itself;
// both have erased type ()Object
// class Y { def f = new X("") or new X("") }
// ^
// one error found
|
@paulp said: final class Option[+A](val value: A) extends AnyVal
abstract class Foo[A] { def f(): Option[A] }
class Bar[A] extends Foo[A] { def f(): Option[A] = ??? }
|
@paulp said: |
Andrzej Giniewicz (giniu) said: class Wrapper(val value: Int) extends AnyVal
abstract class Test { def check(the: Wrapper): Boolean }
new Test { def check(the: Wrapper) = true } error: bridge generated for member method check: (the: Wrapper)Boolean in anonymous class $anon
which overrides method check: (the: Wrapper)Boolean in class Test
clashes with definition of the member itself;
both have erased type (the: Int)Boolean
new Test { def check(the: Wrapper) = true }
^ |
@paulp said: |
@gkossakowski said: trait Function1[T,U]
class Foo(val x: AnyRef) extends AnyVal
object FooUnwrap extends Function1[Foo, AnyRef] {
def apply(f: Foo): AnyRef = f.x
} Now, let's consider a code that uses those classes and objects: val fooStr = new Foo("str") // erases to val fooStr: String = "str"
val f: Function1[Foo, AnyRef] = FooUnwrap // erases to val f: Function1[AnyRef, AnyRef] = FooUnwrap
f.apply(fooStr) // erases to f.apply(new Foo(fooStr)) must dispatch to apply(AnyRef)AnyRef method
FooUnwrap.apply(fooStr) // erases to FooUnwrap.apply(fooStr) must dispatch to apply(AnyRef)AnyRef method I've put erasure of each line in a comment. You can see that we have two calls to an apply where in one case we should unwrap the argument and in another one we shouldn't but the target (erased) signature is the same. Am I missing something? |
@retronym said (edited on Oct 25, 2013 1:13:41 PM UTC): final class Option[+A](val value: A) extends AnyVal
abstract class Foo[A] { def f(): Option[A] }
class Bar[A] extends Foo[A] { def f(): Option[A] = ??? } These signatures were considered different wrt bridging because: !(ErasedValueClass(Option[A(in Foo)]) =:= ErasedValueClass(Option[A(in Bar)]]) In my branch, I fix this in a slightly hacky way with a type map from final class Option[+A](val value: A) extends AnyVal
abstract class Foo1[A] { def f(): A }
class Bar1[A] extends Foo1[Option[A]] { def f(): Option[A] = ??? } I have a hunch we can move that into the normal erasure type map, rather than leaving it to posterasure. |
@retronym said (edited on Oct 25, 2013 1:12:51 PM UTC): Incidentally, I was motivated to fix this problem because I'm extending bridging to Mixin to try to fix #3452, and that got tripped up when mixing DeprectedPredef.any2ArrowAssoc into Predef. def any2ArrowAssoc[A](x: A): ArrowAssoc[A] |
@paulp said: Since you're poking at value class erasures, you might want to consider this one just for fun. It was brought up at PNW Scala that it would be a lot better if both these methods were specialized. But specialization is about as hip to the value class scene as is erasure. class Meter(val m: Double) extends AnyVal
object Test {
def fn1(f: Meter => Double)(x: Meter): Double = f(x)
// 0: aload_1
// 1: new #16 // class Meter
// 4: dup
// 5: dload_2
// 6: invokespecial #19 // Method Meter."<init>":(D)V
// 9: invokeinterface #25, 2 // InterfaceMethod scala/Function1.apply:(Ljava/lang/Object;)Ljava/lang/Object;
// 14: invokestatic #31 // Method scala/runtime/BoxesRunTime.unboxToDouble:(Ljava/lang/Object;)D
// 17: dreturn
def fn2(f: Double => Double)(x: Double): Double = f(x)
// 0: aload_1
// 1: dload_2
// 2: invokeinterface #41, 3 // InterfaceMethod scala/Function1.apply$mcDD$sp:(D)D
// 7: dreturn
} |
@paulp said: |
@retronym said: |
@retronym said: |
@retronym said: https://github.com/retronym/java-8-function1/blob/master/README.md What if we only created the generic signature for anoynmous functions, rather than a more specific signature in the subclass that will always be accessed via a bridge? |
@retronym said: |
@retronym said: |
@gkossakowski said: object MyLambda extends (ValueClass => ValueClass) However, in majority of cases people care about lambdas so I'd mark this as fixed. Jason, WDYT? |
@retronym said: |
Lambdas with AnyVal extension arguments, where the single val is erased to Object, seem to produce invalid classes, which is only indicated when trying to load those classes. This is a simplified example.
The text was updated successfully, but these errors were encountered: