Scala Programming Language
  1. Scala Programming Language
  2. SI-3943

Prefix for inner class of generic java classes is incorrect.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: Scala 2.11.0-M3
    • Component/s: Misc Compiler
    • Labels:
      None

      Description

      scalac - classpath javaPart.jar ./test/Child.scala

      scalac.bat : .\test\Child.scala:5: error: class ActualClass needs to be abstract, since method f in class AChild of type (x$$1: test.TopLevelP
      arent[A]#Inner2)Unit is not defined
      class ActualClass[A] extends AnotherChild[A] {
      ^
      .\test\Child.scala:6: error: method f overrides nothing
      override def f(ic: Inner2) = ()
      ^
      two errors found

        Issue Links

          Activity

          Hide
          Adriaan Moors added a comment -

          more poignant test case:

          Outer.java:

          public class Outer<E> {
            abstract class Inner {
              abstract public void foo(E e);
            }
          }
          
          class Child extends Outer<String> {
            // the implicit prefix for Inner is Outer<E> instead of Outer<String>
            public Inner getInner() {
              return new Inner() {
               public void foo(String e) { System.out.println("meh "+e); }
              };
            }
          }
          
          object Test extends Application {
            val x: Child = new Child
            x.getInner.foo("meh")
          //                        ^
          // error: type mismatch;
          //  found   : java.lang.String("meh")
          //  required: E
          }
          
          Show
          Adriaan Moors added a comment - more poignant test case: Outer.java: public class Outer<E> { abstract class Inner { abstract public void foo(E e); } } class Child extends Outer<String> { // the implicit prefix for Inner is Outer<E> instead of Outer<String> public Inner getInner() { return new Inner() { public void foo(String e) { System.out.println("meh "+e); } }; } } object Test extends Application { val x: Child = new Child x.getInner.foo("meh") // ^ // error: type mismatch; // found : java.lang.String("meh") // required: E }
          Hide
          Adriaan Moors added a comment -

          I give up.

          After figuring out the problem and the obvious fix, I've spent more than a day looking for a way that does not cause cyclesr1 during quick.lib.

          The obvious fixr2 is to simply change the two occurrences of `processClassType(processInner(???.tpe))` in `sigToType`
          to `processClassType(processInner(transformedTpe(???)))`, with:

          // SI-3943
          // cls.tpe.prefix is the thisType of the enclosing class of cls's definition
          // later, we'll widen the this-type to the corresponding typeref (with type arguments that blindly refer
          //   to the enclosing class's type parameters)
          // since we're computing sym's signature, cls.tpe needs to be re-interpreted in the context of sym.enclClass.thisType
          // otherwise, cls.tpe.widen may refer to type parameters of its enclosing class, which are not in scope where sym is defined
          lazy val site = if(sym eq null) null else sym.enclClass.thisType
          def transformedTpe(cls: Symbol) = if((site eq null) || cls.isStatic) cls.tpe else site.memberType(cls)
          

          I've tried various approaches with LazyTypes, but the fact that these prefixes may occur in the super class type, method parameter types&result type,... makes it seem like an unlikely solution.

          The only alternative I could think of was something like cooking raw types, but I can only hope there's a better way...

          r1 assertion failed: illegal class file dependency between 'object ListItr' and 'class ListItr'

          69.     assert(!busy.isDefined, {
                    val (s1, s2) = (busy.get, root)
                    if (s1 eq s2) "unsatisfiable cyclic dependency in '%s'".format(s1)
                    else "illegal class file dependency between '%s' and '%s'".format(s1, s2)
                  })
          

          r2 https://github.com/adriaanm/scala/commit/95bcc3f39705e87e2f877a84118cb8cb2b11c076

          Show
          Adriaan Moors added a comment - I give up. After figuring out the problem and the obvious fix, I've spent more than a day looking for a way that does not cause cyclesr1 during quick.lib. The obvious fixr2 is to simply change the two occurrences of `processClassType(processInner(???.tpe))` in `sigToType` to `processClassType(processInner(transformedTpe(???)))`, with: // SI-3943 // cls.tpe.prefix is the thisType of the enclosing class of cls's definition // later, we'll widen the this-type to the corresponding typeref (with type arguments that blindly refer // to the enclosing class's type parameters) // since we're computing sym's signature, cls.tpe needs to be re-interpreted in the context of sym.enclClass.thisType // otherwise, cls.tpe.widen may refer to type parameters of its enclosing class, which are not in scope where sym is defined lazy val site = if(sym eq null) null else sym.enclClass.thisType def transformedTpe(cls: Symbol) = if((site eq null) || cls.isStatic) cls.tpe else site.memberType(cls) I've tried various approaches with LazyTypes, but the fact that these prefixes may occur in the super class type, method parameter types&result type,... makes it seem like an unlikely solution. The only alternative I could think of was something like cooking raw types, but I can only hope there's a better way... r1 assertion failed: illegal class file dependency between 'object ListItr' and 'class ListItr' 69. assert(!busy.isDefined, { val (s1, s2) = (busy.get, root) if (s1 eq s2) "unsatisfiable cyclic dependency in '%s'".format(s1) else "illegal class file dependency between '%s' and '%s'".format(s1, s2) }) r2 https://github.com/adriaanm/scala/commit/95bcc3f39705e87e2f877a84118cb8cb2b11c076
          Hide
          Paul Phillips added a comment -

          This has started working sometime since 2.10.

          Show
          Paul Phillips added a comment - This has started working sometime since 2.10.
          Show
          Jason Zaugg added a comment - SI-6168 / https://github.com/scala/scala/commit/edee27f59f1787 , perchance?
          Hide
          Jason Zaugg added a comment - - edited

          Yep, that was the one.

          ticket/t3943 /code/scala javac -d sandbox test/files/pos/t3943/Outer_1.java && RUNNER=scalac scala-hash edee27f59f1787^ -classpath sandbox test/files/pos/t3943/Client_2.scala
          [info] downloading http://scala-webapps.epfl.ch/artifacts/1187c9896c097e6e591e5655b35f52c06b3c900a/pack.tgz ...done.
          [info] scala revision from 2013-03-23 12:20:41 -0700 downloaded to /Users/jason/usr/scala-v2.11.0-M2-33-g1187c98
          [info] edee27f59f => /Users/jason/usr/scala-v2.11.0-M2-33-g1187c98
          test/files/pos/t3943/Client_2.scala:3: error: type mismatch;
           found   : String("meh")
           required: E
            x.getInner.foo("meh")
                           ^
          one error found
          ticket/t3943 /code/scala javac -d sandbox test/files/pos/t3943/Outer_1.java && RUNNER=scalac scala-hash edee27f59f1787 -classpath sandbox test/files/pos/t3943/Client_2.scala
          [info] edee27f59f => /Users/jason/usr/scala-v2.11.0-M2-34-gedee27f
          

          Test case: https://github.com/scala/scala/pull/2534

          Show
          Jason Zaugg added a comment - - edited Yep, that was the one. ticket/t3943 /code/scala javac -d sandbox test/files/pos/t3943/Outer_1.java && RUNNER=scalac scala-hash edee27f59f1787^ -classpath sandbox test/files/pos/t3943/Client_2.scala [info] downloading http://scala-webapps.epfl.ch/artifacts/1187c9896c097e6e591e5655b35f52c06b3c900a/pack.tgz ...done. [info] scala revision from 2013-03-23 12:20:41 -0700 downloaded to /Users/jason/usr/scala-v2.11.0-M2-33-g1187c98 [info] edee27f59f => /Users/jason/usr/scala-v2.11.0-M2-33-g1187c98 test/files/pos/t3943/Client_2.scala:3: error: type mismatch; found : String("meh") required: E x.getInner.foo("meh") ^ one error found ticket/t3943 /code/scala javac -d sandbox test/files/pos/t3943/Outer_1.java && RUNNER=scalac scala-hash edee27f59f1787 -classpath sandbox test/files/pos/t3943/Client_2.scala [info] edee27f59f => /Users/jason/usr/scala-v2.11.0-M2-34-gedee27f Test case: https://github.com/scala/scala/pull/2534

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Alec Zorab
              TracCC:
              Miles Sabin
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development