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

Can't summon an ArrayTag for a type alias of an Array type #5769

Closed
scabug opened this issue May 7, 2012 · 23 comments
Closed

Can't summon an ArrayTag for a type alias of an Array type #5769

scabug opened this issue May 7, 2012 · 23 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented May 7, 2012

 ~/code/scala ./build/quick/bin/scala Welcome to Scala version 2.10.0-20120505-103711-7cac6334d4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).

scala> arrayTag[Array[Int]]
res4: ArrayTag[Array[Int]] = ClassTag[class [I]

scala> type AI=Array[Int]; arrayTag[AI]
<console>:9: error: No ArrayTag available for AI
        arrayTag[AI]
                ^

Original report:

http://stackoverflow.com/questions/10488007/toarray-in-scala-2-10-milestone

By contrast, this works:

scala> type I=Int; arrayTag[I]
defined type alias I
res6: ArrayTag[I] = ClassTag[int]
@scabug
Copy link
Author

scabug commented May 7, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5769?orig=1
Reporter: @retronym
Affected Versions: 2.10.0

@scabug
Copy link
Author

scabug commented May 7, 2012

@retronym said:
Is this sufficient?

https://github.com/retronym/scala/compare/ticket/5769

@scabug
Copy link
Author

scabug commented May 7, 2012

@scabug
Copy link
Author

scabug commented May 7, 2012

@retronym said:
Sounds legit. Rebased: https://github.com/retronym/scala/compare/ticket/5769

@scabug
Copy link
Author

scabug commented May 7, 2012

@xeno-by said:
Not to be picky, but why not typeSymbol.dealias? To be honest I'm pretty scared of referring to raw info.

@scabug
Copy link
Author

scabug commented May 8, 2012

@retronym said:
This is a learning exercise for me; any help to illuminate such pitfalls would be much appreciated.

@scabug
Copy link
Author

scabug commented May 8, 2012

@retronym said:
To be clear, is this what you suggested?

https://github.com/retronym/scala/compare/ticket/5769

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
Are you really getting different answers for tpe.dealias.typeSymbol and tpe.typeSymbol? How? Calling typeSymbol normalizes!

Just to throw some cold water on this: you should not be inspecting typeSymbols directly, that's what leads to all these aliasing bugs; you should definitely be scared to call rawInfo; and when did dealias turn up on Symbol...

@scabug
Copy link
Author

scabug commented May 8, 2012

@retronym said:
You're right; I was running the wrong set of tests.

Would tpe.baseType(ArrayClass) != NoType the better check in that place? (Not that it's necessarily the right place to fix this bug...)

@scabug
Copy link
Author

scabug commented May 8, 2012

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
That dealias method seems like nothing but trouble to me. Chasing from one symbol to another and disregarding the info completely means you better not be using the result for much. For instance in this case you end up with Array's type constructor instead of Array[Int] if you call ai.dealias.

Here are some things about type aliases.

scala> class Foo { type AI = Array[Int] }
defined class Foo

scala> val ai = typeMember(intp.types("Foo"), "AI")
ai: $r.intp.global.Symbol = type AI

scala> ai.info
res0: $r.intp.global.Type = Array[Int]

scala> ai.tpe
res1: $r.intp.global.Type = Foo.this.AI

scala> ai.tpe.typeSymbol
res2: $r.intp.global.Symbol = class Array

scala> ai.tpe.typeSymbolDirect
res3: $r.intp.global.Symbol = type AI

scala> ai.info.typeSymbol
res4: $r.intp.global.Symbol = class Array

scala> ai.info.typeSymbolDirect
res5: $r.intp.global.Symbol = class Array

scala> ai.dealias
res7: $r.intp.global.Symbol = class Array

scala> ai.typeParams
res8: List[$r.intp.global.Symbol] = List()

scala> res7.typeParams
res9: List[$r.intp.global.Symbol] = List(type T)

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
As you can see in the transcript, "tpe.typeSymbol == ArrayClass" will recognize Arrays whether or not tpe is an alias. So whatever the issue is, it's not that.

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
Here's the bug, and this is what I meant about not inspecting typeSymbol directly:

        if (tpe.typeSymbol == ArrayClass) {
          val componentTpe = tpe.typeArguments(0)

typeSymbol normalizes, but typeArguments doesn't. So it seems to be an Array, but then you take the type arguments from the type alias, and there aren't any.

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
If you're casting your gaze toward the compiler I guess I have about three days left before you know it better than I do, so I better enjoy until friday. See 8e88e5b214 for how to deal safely with potential aliases.

@scabug
Copy link
Author

scabug commented May 8, 2012

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
"Shipping untested fixes since 2008."

@scabug scabug closed this as completed May 8, 2012
@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
"val sym = sym0.dealias"

So if you have

type AI = Array[Int]

and you call reify with the typeSymbol for AI, then it reifies Array's type constructor.

I can't see how that can be right.

@scabug
Copy link
Author

scabug commented May 8, 2012

@xeno-by said:
(consistency argument) In a lot of places in the compiler, aliases are silently converted to their underlying types.

(correctness argument) If an underlying type contains spliceable stuff, we need to ensure that we reify spliced version of that type, not just an alias.

@scabug
Copy link
Author

scabug commented May 8, 2012

@xeno-by said:
Hmm wait

@scabug
Copy link
Author

scabug commented May 8, 2012

@xeno-by said:
Yeah, I see the point:

scala> import scala.reflect.mirror._
import scala.reflect.mirror._

scala> type AI = Array[Int]
defined type alias AI

scala> reify{ val x: AI = null }
res0: reflect.mirror.Expr[Unit] =
Expr[Unit]({
  val x: Array = null;
  ()
})

scala> reify { val x: Array[Int] = null }
res1: reflect.mirror.Expr[Unit] =
Expr[Unit]({
  val x: Array[Int] = null;
  ()
})

@scabug
Copy link
Author

scabug commented May 8, 2012

@xeno-by said:
#5771

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
"In a lot of places in the compiler, aliases are silently converted to their underlying types."

Types are converted to underlying types. That doesn't mean you can do it with bare symbols.

@scabug
Copy link
Author

scabug commented May 8, 2012

@paulp said:
When exactly to dealias is very tricky stuff; too eagerly will be wrong, too lazily will be wrong.

@scabug scabug added this to the 2.10.0 milestone Apr 7, 2017
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

2 participants