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

Scala reflection doesn't understand Java enumerations

    Details

      Description

      enum SimpleEnumeration {
        FOO,
        BAR
      }
      
      import scala.reflect.runtime.universe._
      
      object Test extends App {
        println(typeOf[SimpleEnumeration].declarations)
      }
      
      scala.reflect.internal.Symbols$CyclicReference: illegal cyclic reference involving type E
      	at scala.reflect.internal.Symbols$Symbol$$anonfun$info$3.apply(Symbols.scala:1188)
      	at scala.reflect.internal.Symbols$Symbol$$anonfun$info$3.apply(Symbols.scala:1186)
      	at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
      	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
      	at scala.reflect.internal.Symbols$Symbol.lock(Symbols.scala:468)
      	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1186)
      	at scala.reflect.internal.Types$$anonfun$40.apply(Types.scala:4316)
      	at scala.reflect.internal.Types$$anonfun$40.apply(Types.scala:4315)
      	at scala.reflect.internal.util.Collections$class.mapWithIndex(Collections.scala:122)
      	at scala.reflect.internal.SymbolTable.mapWithIndex(SymbolTable.scala:12)
      	at scala.reflect.internal.Types$class.typeParamsToExistentials(Types.scala:4315)
      	at scala.reflect.internal.SymbolTable.typeParamsToExistentials(SymbolTable.scala:12)
      	at scala.reflect.internal.Types$class.typeParamsToExistentials(Types.scala:4321)
      	at scala.reflect.internal.SymbolTable.typeParamsToExistentials(SymbolTable.scala:12)
      	at scala.reflect.internal.Types$$anon$11.apply(Types.scala:4352)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1004)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1007)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror$TypeParamCompleter$$anonfun$complete$1.apply(JavaMirrors.scala:567)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror$TypeParamCompleter$$anonfun$complete$1.apply(JavaMirrors.scala:567)
      	at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
      	at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
      	at scala.collection.immutable.List.foreach(List.scala:309)
      	at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
      	at scala.collection.AbstractTraversable.map(Traversable.scala:105)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror$TypeParamCompleter.complete(JavaMirrors.scala:567)
      	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1198)
      	at scala.reflect.internal.Types$$anonfun$40.apply(Types.scala:4316)
      	at scala.reflect.internal.Types$$anonfun$40.apply(Types.scala:4315)
      	at scala.reflect.internal.util.Collections$class.mapWithIndex(Collections.scala:122)
      	at scala.reflect.internal.SymbolTable.mapWithIndex(SymbolTable.scala:12)
      	at scala.reflect.internal.Types$class.typeParamsToExistentials(Types.scala:4315)
      	at scala.reflect.internal.SymbolTable.typeParamsToExistentials(SymbolTable.scala:12)
      	at scala.reflect.internal.Types$class.typeParamsToExistentials(Types.scala:4321)
      	at scala.reflect.internal.SymbolTable.typeParamsToExistentials(SymbolTable.scala:12)
      	at scala.reflect.internal.Types$$anon$11.apply(Types.scala:4352)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1004)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror.typeToScala(JavaMirrors.scala:1007)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.completeRest(JavaMirrors.scala:653)
      	at scala.reflect.runtime.JavaMirrors$JavaMirror$FromJavaClassCompleter.complete(JavaMirrors.scala:644)
      	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1198)
      	at scala.reflect.internal.Types$TypeRef.decls(Types.scala:2421)
      	at scala.reflect.internal.Types$TypeApiImpl.declarations(Types.scala:298)
      	at scala.reflect.internal.Types$TypeApiImpl.declarations(Types.scala:295)
      	at Test$delayedInit$body.apply(Test.scala:4)
      	at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
      	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
      	at scala.App$$anonfun$main$1.apply(App.scala:61)
      	at scala.App$$anonfun$main$1.apply(App.scala:61)
      	at scala.collection.immutable.List.foreach(List.scala:309)
      	at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
      	at scala.collection.mutable.ListBuffer.foreach(ListBuffer.scala:45)
      	at scala.App$class.main(App.scala:61)
      	at Test$.main(Test.scala:3)
      	at Test.main(Test.scala)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71)
      	at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
      	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:139)
      	at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:71)
      	at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:139)
      	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28)
      	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45)
      	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35)
      	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45)
      	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74)
      	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
      	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105)
      	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
      

        Activity

        Hide
        Eugene Burmako added a comment - - edited

        Here's the deal:

        1) SimpleEnumeration is being completed. Completion triggers typeToScala(superclazz), which is Enum<SimpleEnumeration>
        =======
        2) typeToScala(Enum<SimpleEnumeration>) recurs into typeToScala(Enum)
        3) typeToScala(Enum) = rawToExistential(typeRef(clazz.owner.thisType, clazz, List()))
        4) rawToExistential = existentialAbstraction(mapOver(typeParamsToExistentials(sym)), typeRef(apply(pre), sym, mapOver(typeParamsToExistentials(sym)) map (_.tpe)))
        5) typeParamsToExistentials = clazz.newExistential(newTypeName("?"+i), clazz.pos) setInfo tparam.info.bounds
        6) tparam.info = TypeParamCompleter.complete
        7) TypeParamCompleter.complete = sym setInfo TypeBounds.upper(glb(jtvar.getBounds.toList map typeToScala map objToAny))
        8) Since Enum is defined as Enum<E extends Enum<E>>, jtvar.getBounds map typeToScala recurs back into Step 2, with the argument being not Enum<SimpleEnumeration>, but Enum<E>, which eventually leads to a cyclic reference

        I can't immediately see how to evade the error. Could anyone chime in?

        Show
        Eugene Burmako added a comment - - edited Here's the deal: 1) SimpleEnumeration is being completed. Completion triggers typeToScala(superclazz), which is Enum<SimpleEnumeration> ======= 2) typeToScala(Enum<SimpleEnumeration>) recurs into typeToScala(Enum) 3) typeToScala(Enum) = rawToExistential(typeRef(clazz.owner.thisType, clazz, List())) 4) rawToExistential = existentialAbstraction(mapOver(typeParamsToExistentials(sym)), typeRef(apply(pre), sym, mapOver(typeParamsToExistentials(sym)) map (_.tpe))) 5) typeParamsToExistentials = clazz.newExistential(newTypeName("?"+i), clazz.pos) setInfo tparam.info.bounds 6) tparam.info = TypeParamCompleter.complete 7) TypeParamCompleter.complete = sym setInfo TypeBounds.upper(glb(jtvar.getBounds.toList map typeToScala map objToAny)) 8) Since Enum is defined as Enum<E extends Enum<E>>, jtvar.getBounds map typeToScala recurs back into Step 2, with the argument being not Enum<SimpleEnumeration>, but Enum<E>, which eventually leads to a cyclic reference I can't immediately see how to evade the error. Could anyone chime in?
        Show
        Eugene Burmako added a comment - https://github.com/scala/scala/pull/1324
        Hide
        Grzegorz Kossakowski added a comment -
        Show
        Grzegorz Kossakowski added a comment - Closed in https://github.com/scala/scala/pull/1324

          People

          • Assignee:
            Eugene Burmako
            Reporter:
            Eugene Burmako
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development