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

Scala compiler reports class file is broken when the class is annotated with a Java annotation having multiple enum values

    Details

      Description

      I discovered this issues while annotating some of scala traits with Jackson type annotations (http://jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/annotate/JsonTypeInfo.html). The issues seems to be that the JsonTypeInfo annotation has two properties that reference inner non-static enumerations. The scala compiler appears to generate valid class files, but cannot load these class to compile other dependent source files.

      I've managed to reproduce the issue outside of Jackson:

      $ javac -version
      javac 1.6.0_26
      $ scalac -version
      Scala compiler version 2.9.2.r25928-b20111102031955 -- Copyright 2002-2011, LAMP/EPFL
      
      $ javac TestAnnotation.java 
      $ scalac TestTrait.scala 
      $ scalac TestObject.scala 
      error: error while loading TestTrait, class file './TestTrait.class' is broken
      (Scala class file does not contain Scala annotation)
      TestObject.scala:2: error: illegal inheritance;
       self-type TestObject.type does not conform to TestTrait's selftype TestTrait
      object TestObject extends TestTrait
                                ^
      TestObject.scala:2: error: illegal inheritance; superclass TestTrait
       is not a subclass of the superclass Object
       of the mixin trait ScalaObject
      object TestObject extends TestTrait
                        ^
      three errors found
      

      The source (also attached):

      TestAnnotation.java
      import java.lang.annotation.*;
      
      @Retention(RetentionPolicy.RUNTIME)
      public @interface TestAnnotation {
        public enum TestEnumOne { A, B }
        public enum TestEnumTwo { C, D }
      
        public TestEnumOne one();
        public TestEnumTwo two();
        public String strVal();
      }
      
      TestTrait.scala
      @TestAnnotation(one=TestAnnotation.TestEnumOne.A, two=TestAnnotation.TestEnumTwo.C, strVal="something")
      trait TestTrait
      
      TestObject.scala
      object TestObject extends TestTrait
      

      Other Observations:

      • Making TestEnumOne and TestEnumTwo static still produces the error
      • Compiling both TestTrait.scala and TestObject.scala together does not produce the error
      • Having only one enum filed in TestAnnotation (i.e. commenting out "public TestEnumTwo two()" in TestAnnotation.java) does not produce the error
      1. test.tbz
        0.4 kB
        Bryan Gahagan

        Issue Links

          Activity

          Hide
          Alex Black added a comment -

          Would love to see a fix for this!

          Show
          Alex Black added a comment - Would love to see a fix for this!
          Hide
          Adriaan Moors added a comment -

          sounds like SI-2764
          please re-open if I missed something

          Show
          Adriaan Moors added a comment - sounds like SI-2764 please re-open if I missed something
          Hide
          Lorrin Nelson added a comment -

          Well, it is a different error message in a slightly different situation (annotated trait rather than annotated method) and slightly different behavior (rather than a direct compile error, the trait compiles fine but then produces invalid class file; SI-2764 occurs with single enum in the annotation but this bug only triggers with two).

          It seems to me that it is likely but unknown whether fixing SI-2764 will fix this. If we close this issue, there's no longer any trigger for someone to notice and confirm whether the issue has been resolved or not. So I'd prefer to leave open.

          Show
          Lorrin Nelson added a comment - Well, it is a different error message in a slightly different situation (annotated trait rather than annotated method) and slightly different behavior (rather than a direct compile error, the trait compiles fine but then produces invalid class file; SI-2764 occurs with single enum in the annotation but this bug only triggers with two). It seems to me that it is likely but unknown whether fixing SI-2764 will fix this. If we close this issue, there's no longer any trigger for someone to notice and confirm whether the issue has been resolved or not. So I'd prefer to leave open.
          Hide
          George added a comment -

          Are there any updates on getting this fixed. Or does anyone have any suggestion for working around it. Im using JsonTypeInfo to assist with some polymorphic jason mappings.

          Show
          George added a comment - Are there any updates on getting this fixed. Or does anyone have any suggestion for working around it. Im using JsonTypeInfo to assist with some polymorphic jason mappings.
          Hide
          George added a comment -

          I found that i could work around this issue by using a java interface instead of a scala trait

          Show
          George added a comment - I found that i could work around this issue by using a java interface instead of a scala trait
          Hide
          Eugene Burmako added a comment -

          In 2.10 `scalac TestTrait.scala` fails to compile because of:

          TestTrait.scala:1: error: annotation argument needs to be a constant; found: TestAnnotation.TestEnumOne.A
          @TestAnnotation(one=TestAnnotation.TestEnumOne.A, two=TestAnnotation.TestEnumTwo.C, strVal="something")
                                                         ^
          TestTrait.scala:1: error: annotation argument needs to be a constant; found: TestAnnotation.TestEnumTwo.C
          @TestAnnotation(one=TestAnnotation.TestEnumOne.A, two=TestAnnotation.TestEnumTwo.C, strVal="something")
                                                                                           ^
          two errors found
          
          Show
          Eugene Burmako added a comment - In 2.10 `scalac TestTrait.scala` fails to compile because of: TestTrait.scala:1: error: annotation argument needs to be a constant; found: TestAnnotation.TestEnumOne.A @TestAnnotation(one=TestAnnotation.TestEnumOne.A, two=TestAnnotation.TestEnumTwo.C, strVal="something") ^ TestTrait.scala:1: error: annotation argument needs to be a constant; found: TestAnnotation.TestEnumTwo.C @TestAnnotation(one=TestAnnotation.TestEnumOne.A, two=TestAnnotation.TestEnumTwo.C, strVal="something") ^ two errors found
          Hide
          Paul Phillips added a comment -

          Noting for the record that I checked in a test case for this thinking it was fixed because eugene's error as given above no longer occurs, it compiles if all source; but the classfile parsing bug remains so this isn't fixed. I'm looking at that now.

          Show
          Paul Phillips added a comment - Noting for the record that I checked in a test case for this thinking it was fixed because eugene's error as given above no longer occurs, it compiles if all source; but the classfile parsing bug remains so this isn't fixed. I'm looking at that now.
          Hide
          Simon Ochsenreither added a comment -

          The problem with the class-parser is probably related to SI-5699.

          Show
          Simon Ochsenreither added a comment - The problem with the class-parser is probably related to SI-5699 .
          Hide
          Raman Gupta added a comment -

          FYI - for anyone running into this issue who is using Jackson annotations – one workaround is to add the annotation to the scala class using a java mixin class. See here: http://wiki.fasterxml.com/JacksonMixInAnnotations.

          Show
          Raman Gupta added a comment - FYI - for anyone running into this issue who is using Jackson annotations – one workaround is to add the annotation to the scala class using a java mixin class. See here: http://wiki.fasterxml.com/JacksonMixInAnnotations .
          Hide
          Adriaan Moors added a comment -

          Compiles with scalac 2.11.0-M8

          Show
          Adriaan Moors added a comment - Compiles with scalac 2.11.0-M8
          Hide
          Jason Zaugg added a comment -

          Paul's test case from source:

          commit 3511e5960d510eafcb67c388ec0b5b60aafdd8f3
          Author: Paul Phillips <paulp@improving.org>
          Date:   Fri May 11 11:06:55 2012 -0700
          
              Test case closes SI-5165.
          
              Also fixed by annotation/enum commit.
          
          commit 807567230852bcadb98a91322bd348aae764801f
          Author: Paul Phillips <paulp@improving.org>
          Date:   Fri May 11 10:25:34 2012 -0700
          
              Recognize java enums as constants from source.
          
              Fixed up one of the mismatches between how java source is modeled
              and how java bytecode is modeled.  We should get the rest of them
              too.  Closes SI-2764.
          

          Looks like this started working in:

          commit dc6a49337f072686516c14f50b847c38cbc6c225
          Author: Miguel Garcia <miguelalfredo.garcia@epfl.ch
          Date:   Fri Jul 6 17:06:57 2012 +0200
          
              GenASM becomes default backend, 1.5 classfiles
          
          % (export V=dc6a493; rm *.class; javac -d . test/files/pos/t5165b/TestAnnotation_1.java && scalac-hash $V test/files/pos/t5165b/TestTrait_2.scala && scalac-hash $V test/files/pos/t5165b/TestObject_3.scala)
          
          % (export V=dc6a493~1; rm *.class; javac -d . test/files/pos/t5165b/TestAnnotation_1.java && scalac-hash $V test/files/pos/t5165b/TestTrait_2.scala && scalac-hash $V test/files/pos/t5165b/TestObject_3.scala 2>&1 | tail -n 8)
           self-type TestObject.type does not conform to TestTrait's selftype TestTrait
          object TestObject extends TestTrait
                                    ^
          test/files/pos/t5165b/TestObject_3.scala:2: error: TestTrait does not have a constructor
          object TestObject extends TestTrait
                            ^
          two warnings found
          5 errors found
          
          % for i in 10.0 10.2 10.3 11.0-M8; do (export V=v2.$i; rm *.class; javac -d . test/files/pos/t5165b/TestAnnotation_1.java && scalac-hash $V test/files/pos/t5165b/TestTrait_2.scala && scalac-hash $V test/files/pos/t5165b/TestObject_3.scala); done
          [warn] v2.11.0-M8 failed, using closest available
          [warn] v2.11.0-M8 failed, using closest available
          

          I've submitted a test case to keep it fixed. This test case used the same compilation order as reported above: https://github.com/scala/scala/pull/3548

          Show
          Jason Zaugg added a comment - Paul's test case from source: commit 3511e5960d510eafcb67c388ec0b5b60aafdd8f3 Author: Paul Phillips <paulp@improving.org> Date: Fri May 11 11:06:55 2012 -0700 Test case closes SI-5165. Also fixed by annotation/enum commit. commit 807567230852bcadb98a91322bd348aae764801f Author: Paul Phillips <paulp@improving.org> Date: Fri May 11 10:25:34 2012 -0700 Recognize java enums as constants from source. Fixed up one of the mismatches between how java source is modeled and how java bytecode is modeled. We should get the rest of them too. Closes SI-2764. Looks like this started working in: commit dc6a49337f072686516c14f50b847c38cbc6c225 Author: Miguel Garcia <miguelalfredo.garcia@epfl.ch Date: Fri Jul 6 17:06:57 2012 +0200 GenASM becomes default backend, 1.5 classfiles % (export V=dc6a493; rm *.class; javac -d . test/files/pos/t5165b/TestAnnotation_1.java && scalac-hash $V test/files/pos/t5165b/TestTrait_2.scala && scalac-hash $V test/files/pos/t5165b/TestObject_3.scala) % (export V=dc6a493~1; rm *.class; javac -d . test/files/pos/t5165b/TestAnnotation_1.java && scalac-hash $V test/files/pos/t5165b/TestTrait_2.scala && scalac-hash $V test/files/pos/t5165b/TestObject_3.scala 2>&1 | tail -n 8) self-type TestObject.type does not conform to TestTrait's selftype TestTrait object TestObject extends TestTrait ^ test/files/pos/t5165b/TestObject_3.scala:2: error: TestTrait does not have a constructor object TestObject extends TestTrait ^ two warnings found 5 errors found % for i in 10.0 10.2 10.3 11.0-M8; do (export V=v2.$i; rm *.class; javac -d . test/files/pos/t5165b/TestAnnotation_1.java && scalac-hash $V test/files/pos/t5165b/TestTrait_2.scala && scalac-hash $V test/files/pos/t5165b/TestObject_3.scala); done [warn] v2.11.0-M8 failed, using closest available [warn] v2.11.0-M8 failed, using closest available I've submitted a test case to keep it fixed. This test case used the same compilation order as reported above: https://github.com/scala/scala/pull/3548

            People

            • Assignee:
              Miguel Garcia
              Reporter:
              Bryan Gahagan
            • Votes:
              7 Vote for this issue
              Watchers:
              17 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development