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

Reflection: == on equal types returns false

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: Scala 2.10.0-M4
    • Fix Version/s: Scala 2.10.0-M4
    • Component/s: Reflection
    • Labels:
      None
    • Environment:

      Welcome to Scala version 2.10.0-20120621-122142-953898fa32

      Description

      I access the result type of a method ({{

      {Int}

      }}) and compiare it with {{

      {typeOf[Int]}

      }}, but that returns {{

      {false}

      }}. I expected to see {{

      {true}

      }}.

      class X {
         def methodIntIntInt(x: Int, y: Int) = x+y
      }
      
      import scala.reflect.runtime.universe._
      import scala.reflect.runtime.{ currentMirror => cm }
      val im: InstanceMirror = cm.reflect(new X)
      val cs: ClassSymbol = im.symbol
      val ts: Type = cs.typeSignature
      val ms: MethodSymbol = ts.declaration(newTermName("methodIntIntInt")).asMethodSymbol
      val MethodType( _, t1 ) = ms.typeSignature
      val t2 = typeOf[scala.Int]
      

      and now the output from the REPL:

      scala> t1
      res0: reflect.runtime.universe.Type = scala.Int
      
      scala> t2
      res1: reflect.runtime.universe.Type = Int
      
      scala> showRaw(t1)
      res2: String = TypeRef(ThisType(scala), scala.Int, List())
      
      scala> showRaw(t2)
      res3: String = TypeRef(ThisType(scala), scala.Int, List())
      
      scala> t1==t2
      res4: Boolean = false
      
      scala> t1.normalize == t2.normalize
      res5: Boolean = false
      
      

        Activity

        Hide
        Dominik Gruntz added a comment -

        the type symbols of t1 and t2 are equivalent:

        scala> t1.typeSymbol
        res29: reflect.runtime.universe.Symbol = class Int
        
        scala> t2.typeSymbol
        res30: reflect.runtime.universe.Symbol = class Int
        
        scala> t1.typeSymbol == t2.typeSymbol
        res32: Boolean = true
        
        Show
        Dominik Gruntz added a comment - the type symbols of t1 and t2 are equivalent: scala> t1.typeSymbol res29: reflect.runtime.universe.Symbol = class Int scala> t2.typeSymbol res30: reflect.runtime.universe.Symbol = class Int scala> t1.typeSymbol == t2.typeSymbol res32: Boolean = true
        Hide
        Adriaan Moors added a comment -

        and what about their prefixes?
        if those are equal, hashconsing might be broken – in principle it should hold that `t1 eq t2`

        Show
        Adriaan Moors added a comment - and what about their prefixes? if those are equal, hashconsing might be broken – in principle it should hold that `t1 eq t2`
        Hide
        Dominik Gruntz added a comment -

        how can I access the prefix on a type of type reflect.runtime.universe.Type?

        Show
        Dominik Gruntz added a comment - how can I access the prefix on a type of type reflect.runtime.universe.Type ?
        Hide
        Adriaan Moors added a comment -

        seems like hashconsing is broken:

        scala> TypeRef.unapply(t1.asInstanceOf[TypeRef])
        res2: Option[(reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type])] = Some((scala.type,class Int,List()))
        
        scala> TypeRef.unapply(t2.asInstanceOf[TypeRef])
        res3: Option[(reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type])] = Some((scala.type,class Int,List()))
        
        scala> TypeRef.unapply(t1.asInstanceOf[TypeRef]).get._1 == TypeRef.unapply(t2.asInstanceOf[TypeRef]).get._1
        res9: Boolean = false
        
        scala> System.identityHashCode(t1)
        res10: Int = 598346035
        
        scala> System.identityHashCode(t2)
        res11: Int = 1622300681
        
        Show
        Adriaan Moors added a comment - seems like hashconsing is broken: scala> TypeRef.unapply(t1.asInstanceOf[TypeRef]) res2: Option[(reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type])] = Some((scala.type,class Int,List())) scala> TypeRef.unapply(t2.asInstanceOf[TypeRef]) res3: Option[(reflect.runtime.universe.Type, reflect.runtime.universe.Symbol, List[reflect.runtime.universe.Type])] = Some((scala.type,class Int,List())) scala> TypeRef.unapply(t1.asInstanceOf[TypeRef]).get._1 == TypeRef.unapply(t2.asInstanceOf[TypeRef]).get._1 res9: Boolean = false scala> System.identityHashCode(t1) res10: Int = 598346035 scala> System.identityHashCode(t2) res11: Int = 1622300681
        Hide
        Eugene Burmako added a comment - - edited

        The sky is not falling. It's just that <package scala> symbols have been loaded by different mirrors.

        scala> mirrorThatLoaded(pre1.typeSymbol)
        res2 @ 6547bc27: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain
        $TranslatingClassLoader@4069b25f of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoa
        der with classpath <unknown>
        
        scala> mirrorThatLoaded(pre2.typeSymbol)
        res3 @ 4b59df6c: reflect.runtime.universe.Mirror = JavaMirror with sun.misc.Launcher$AppClassLoader@
        546b97fd of type class sun.misc.Launcher$AppClassLoader with classpath [file:/C:/Projects/Kepler/tes
        t/files/codelib/code.jar,file:/C:/Projects/Kepler/lib/jline.jar,file:/C:/Projects/Kepler/lib/fjbg.ja
        r,file:/C:/Projects/Kepler/build/locker/classes/compiler/,file:/C:/Projects/Kepler/build/locker/clas
        ses/reflect/,file:/C:/Projects/Kepler/build/locker/classes/library/]
        

        Very well. It seems that we need to disable symbol sharing altogether.

        Show
        Eugene Burmako added a comment - - edited The sky is not falling. It's just that <package scala> symbols have been loaded by different mirrors. scala> mirrorThatLoaded(pre1.typeSymbol) res2 @ 6547bc27: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain $TranslatingClassLoader@4069b25f of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoa der with classpath <unknown> scala> mirrorThatLoaded(pre2.typeSymbol) res3 @ 4b59df6c: reflect.runtime.universe.Mirror = JavaMirror with sun.misc.Launcher$AppClassLoader@ 546b97fd of type class sun.misc.Launcher$AppClassLoader with classpath [file:/C:/Projects/Kepler/tes t/files/codelib/code.jar,file:/C:/Projects/Kepler/lib/jline.jar,file:/C:/Projects/Kepler/lib/fjbg.ja r,file:/C:/Projects/Kepler/build/locker/classes/compiler/,file:/C:/Projects/Kepler/build/locker/clas ses/reflect/,file:/C:/Projects/Kepler/build/locker/classes/library/] Very well. It seems that we need to disable symbol sharing altogether.
        Hide
        Eugene Burmako added a comment -

        Good news is that this works outside REPL.

        Show
        Eugene Burmako added a comment - Good news is that this works outside REPL.
        Show
        Eugene Burmako added a comment - Fixed in https://github.com/scala/scala/commit/0529dd502a45e29aa617986ff9ab29e145d62582

          People

          • Assignee:
            Eugene Burmako
            Reporter:
            Dominik Gruntz
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development