Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

more non-determinism in reflection #6826

Open
scabug opened this issue Dec 18, 2012 · 3 comments
Open

more non-determinism in reflection #6826

scabug opened this issue Dec 18, 2012 · 3 comments
Milestone

Comments

@scabug
Copy link

scabug commented Dec 18, 2012

This is really confusing behavior.

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeOf[List[_]].typeSymbol.asType.toType
res0: reflect.runtime.universe.Type = List

scala> typeOf[List[_]].typeSymbol.asType.toType
res1: reflect.runtime.universe.Type = List[A]

scala> typeOf[Function1[_,_]].typeSymbol.asType.toType
res2: reflect.runtime.universe.Type = Function1

scala> typeOf[Function1[_,_]].typeSymbol.asType.toType
res3: reflect.runtime.universe.Type = T1 => R
@scabug
Copy link
Author

scabug commented Dec 18, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6826?orig=1
Reporter: @paulp
Affected Versions: 2.11.0

@scabug
Copy link
Author

scabug commented May 4, 2013

@ghik said (edited on May 4, 2013 8:25:12 PM UTC):
I was hit by this bug in 2.10.1 and did a little debugging (used this as an opportunity to delve a bit into compiler internals).

Below is what I found. I don't know if this is of any relevance or tells anything that isn't already obvious to you, Scala compiler guys, but I post this in case I save someone a little debugging time.

In general, this seems to be a problem with lazy resolution of type associated with a Symbol.

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeOf[List[_]].typeSymbol.asType.toType.getClass
res0: Class[_ <: reflect.runtime.universe.Type] = class scala.reflect.internal.Types$TypeRef$$anon$6

TypeRef$$anon$6 is a subclass of NoArgsTypeRef, this is a wrong type!
At this point, infos.info of the symbol is an instance of scala.reflect.runtime.SymbolLoaders$TopClassCompleter (retrieved using Java reflection on private fields so it didn't cause any lazy evaluation)

This happened as a result of following call chain:

	at scala.reflect.internal.Types$Type.typeParams(Types.scala:554)
	at scala.reflect.internal.Symbols$Symbol.unsafeTypeParams(Symbols.scala:1468)
	at scala.reflect.internal.Symbols$TypeSymbol.tpe(Symbols.scala:2768)
	at scala.reflect.internal.Symbols$SymbolContextApiImpl.toType(Symbols.scala:101)
	at scala.reflect.internal.Symbols$TypeSymbol.toType(Symbols.scala:2689)

The innermost call (Type.typeParams) returned empty list because it was called on rawInfo which at this point was a lazy type, scala.reflect.runtime.SymbolLoaders$TopClassCompleter. I guess this is something that shouldn't have happened. Based on empty parameter list returned from TopClassCompleter, a NoArgsTypeRef type was associated with the symbol.

OK, let's see what happens next:

scala> typeOf[List[_]].typeSymbol.asType.toType.getClass
res1: Class[_ <: reflect.runtime.universe.Type] = class scala.reflect.internal.Types$TypeRef$$anon$6

Still the same...

scala> typeOf[List[_]].typeSymbol.asType.toType
res2: reflect.runtime.universe.Type = List

Wrong result, that's a string representation of NoArgsTypeRef from before.
At this point however, infos.info of the symbol is an instance of scala.reflect.internal.Types$PolyType. It seems that
something was reinitialized during toString() call on the type.

scala> typeOf[List[_]].typeSymbol.asType.toType.getClass
res3: Class[_ <: reflect.runtime.universe.Type] = class scala.reflect.internal.Types$TypeRef$$anon$5

Now the type seems to be correct. TypeRef$$anon$5 is a subclass of ArgsTypeRef.

scala> typeOf[List[_]].typeSymbol.asType.toType
res4: reflect.runtime.universe.Type = List[A]

Now that the symbol has correct type, everything's fine.

@scabug
Copy link
Author

scabug commented May 4, 2013

@paulp said:
"I guess this is something that shouldn't have happened."

Right, that's why it's called "unsafeTypeParams".

Calling toString sometimes leads to normalize being called (that is a bug, which I might have fixed in master, can't remember) which can force the info.

It's a big, complicated thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant