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

Bad super class declared in a signature for interface corresponding to generic trait extending generic class

    Details

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

      Description

      Consider following Scala code:

      package test.generic
      
      class C1[A] {
        def m1(): Unit = System.out.println("m1")
      }
      
      trait T1[A] extends C1[A]
      
      class C2[A] extends T1[A] //defined for connivence 
      

      Once compiled, this will produce a broken signature in interface corresponding to T1:

      Compiled from "test-generic.scala"
      public interface test.generic.T1
        SourceFile: "test-generic.scala"
        ScalaSig: length = 0x3
         05 00 00 
        Signature: length = 0x2
         00 04 
        RuntimeVisibleAnnotations: length = 0xB
         00 01 00 06 00 01 00 07 73 00 08 
        minor version: 0
        major version: 49
        Constant pool:
      const #1 = Asciz	SourceFile;
      const #2 = Asciz	test-generic.scala;
      const #3 = Asciz	ScalaSig;
      const #4 = Asciz	<A:Ljava/lang/Object;>Ltest/generic/C1<TA;>;; //!!! interface extends a class, not very nice
      const #5 = Asciz	Signature;
      const #6 = Asciz	Lscala/reflect/ScalaSignature;;
      const #7 = Asciz	bytes;
      const #9 = Asciz	RuntimeVisibleAnnotations;
      const #10 = Asciz	test/generic/T1;
      const #11 = class	#10;	//  test/generic/T1
      const #12 = Asciz	java/lang/Object;
      const #13 = class	#12;	//  java/lang/Object
      
      {
      }
      

      As a bonus, define Java code:

      
      import test.generic.*;
      
      public class Foo {
        
        public static <A> void foo(T1<A> x) {
          x.m1();
        }
        
        public static void main(String[] args) {
          T1<Object> x = new C2<Object>();
          foo(x);
        }
        
      }
      

      and compile it using javac. Once you run, you get:

      Exception in thread "main" java.lang.NoSuchMethodError: test.generic.T1.m1()V
      	at Foo.foo(Foo.java:6)
      	at Foo.main(Foo.java:11)
      

      Which means that javac got completely confused by broken signature and created a broken class file itself. Not very good.

      The solution would be to skip classes from list of extended things. We should only list traits (if there are any) so we get signature for interface that refers to interfaces only. This solution has been discussed with Martin and he is ok with it.

        Activity

        Hide
        Grzegorz Kossakowski added a comment -

        Also, it's worth mentioning that signatures for interfaces should always list java.lang.Object as a super class. Thus our signature would become:
        <A:Ljava/lang/Object;>Ljava/lang/Object;

        Show
        Grzegorz Kossakowski added a comment - Also, it's worth mentioning that signatures for interfaces should always list java.lang.Object as a super class. Thus our signature would become: <A:Ljava/lang/Object;>Ljava/lang/Object;
        Hide
        Commit Message Bot added a comment -

        (extempore in r25468) Fix java signature generation for traits: no classes as parents.
        Closes SI-4891, review by grek.

        Show
        Commit Message Bot added a comment - (extempore in r25468 ) Fix java signature generation for traits: no classes as parents. Closes SI-4891 , review by grek.

          People

          • Assignee:
            Paul Phillips
            Reporter:
            Grzegorz Kossakowski
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development