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

Artifacts from AnyVal getClass appear in signatures #4846

Closed
scabug opened this issue Jul 27, 2011 · 11 comments
Closed

Artifacts from AnyVal getClass appear in signatures #4846

scabug opened this issue Jul 27, 2011 · 11 comments
Assignees

Comments

@scabug
Copy link

scabug commented Jul 27, 2011

In 2.9.0.1:

scala> List(1) ++ List('a')
res0: List[AnyVal] = List(1, a)

In 2.9.1RC1/2.10-trunk:

scala> List(1) ++ List('a')
res0: List[AnyVal{def getClass(): java.lang.Class[_ >: Int with Char <: AnyVal]}] = List(1, a)

I'm not sure if this is a bug or an enhancement.

Imho the type signature is exposing some implementation detail of getCLass for AnyVals (probably related to #864) and shouldn't appear anywhere.

I really don't want to explain that type signature to a beginner ...

@scabug
Copy link
Author

scabug commented Jul 27, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4846?orig=1
Reporter: @soc
See #864, #3749

@scabug
Copy link
Author

scabug commented Jul 28, 2011

@paulp said:
The inferred type is correct, so this is a scaladoc issue if anything.

@scabug
Copy link
Author

scabug commented Jul 28, 2011

@soc said:
The weird thing is that it disappears again if another List is concatenated:

scala> val list = List(1) ++ List('a') ++ List(1L)
list: List[AnyVal] = List(1, a, 1)

Considering that getClass is already special-cased for AnyVals, would it be possible to at least clean up the REPL output?

@scabug
Copy link
Author

scabug commented Jul 28, 2011

@ijuma said (edited on Jul 28, 2011 9:14:11 AM UTC):
If a List with another AnyVal is concatenated, it disappears, but it remains for e.g.:

scala> List(1L) ++ List(1) ++ List(1L)
res4: List[AnyVal{def getClass(): java.lang.Class[_ >: Long with Int <: AnyVal]}] = List(1, 1, 1)

Personally, I find this a bit odd. If you then call getClass on it, you get:

scala> res4.getClass
res5: java.lang.Class[_ <: List[AnyVal{def getClass(): java.lang.Class[_ >: Long with Int <: AnyVal]}]] = class scala.collection.immutable.$colon$colon

Personally, I think this should just return Class[_ <: List[AnyVal]], but I see what the compiler is doing.

@scabug
Copy link
Author

scabug commented Jul 28, 2011

@SethTisue said:
Simon, the stuff about Scaladoc is irrelevant to the meat of this ticket, so I removed it from the description. I'd suggest adding it as a comment on the pull request instead (with a reference to this ticket).

And with the Scaladoc stuff removed, having the ticket assigned to "Scaladoc Team" no longer makes sense, so I'm changing the status of the ticket to "Invalid", since Paul said "The inferred type is correct."

The inferred type may be "correct" in some sense, but it certainly doesn't seem like the best type to be inferred here. Is this really how it must be? If it stays this way I think this is going to get noticed pretty frequently — especially by beginners.

I'll take it up on the mailing list.

@scabug
Copy link
Author

scabug commented Jul 28, 2011

@SethTisue said:
The issue isn't particular to getClass. The change that was made to getClass merely exposes something about the least-upper-bound algorithm that hasn't changed in many years. 2.9, 2.8, and 2.7 all show:

scala> abstract class A { def f: Class[_] }
defined class A

scala> class A1 extends A { override def f = classOf[Int] }
defined class A1

scala> class A2 extends A { override def f = classOf[Char] }
defined class A2

scala> List(new A1) ++ List(new A2)
res2: List[A{def f: java.lang.Class[_ >: Int with Char <: AnyVal]}] = List(A1@52ac5024, A2@2ec195e3)

@scabug
Copy link
Author

scabug commented Jul 31, 2011

@paulp said:
There has been worse stuff than this for a long time and we've survived this long.

Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).

scala> List(1L: java.lang.Long) ++ List(1: java.lang.Integer)
res0: List[java.lang.Number with java.lang.Comparable[_ >: java.lang.Long with java.lang.Integer <: java.lang.Number with java.lang.Comparable[_ >: java.lang.Long with java.lang.Integer <: java.lang.Number with java.lang.Comparable[_ >: java.lang.Long with java.lang.Integer <: java.lang.Number]]]] = List(1, 1)

@scabug
Copy link
Author

scabug commented Aug 2, 2011

@SethTisue said:
Martin writes: "Since refinements are legal Scala types they may appear as lubs. That fact is used in a lot of Scala code. One way out of this particular pickle would be to teach the typechecker that the glb of Char and Int is Nothing, and likewise for the other value types. I think that would fix the problem." from https://groups.google.com/d/msg/scala-language/mThYtcdajfc/9b3wJa2VOwAJ

So, reopening the ticket but reclassifying it as an enhancement. Martin's suggestion wouldn't help the java.lang.Long/Integer case Paul noticed, but oh well.

@scabug
Copy link
Author

scabug commented Aug 8, 2011

@SethTisue said:
Martin withdraws that fix and suggests three possible alternatives at https://groups.google.com/d/msg/scala-language/mThYtcdajfc/D_LX44WtmeoJ

@scabug scabug closed this as completed Nov 13, 2011
@scabug
Copy link
Author

scabug commented Nov 13, 2011

Commit Message Bot (anonymous) said:
(extempore in r26001) Sin some more.

"Fiddle with lubs and glbs by never considering getClass as a member in
a refinement generated from them. In a sense we have justification for
this by saying we already treated getClass in an ad-hoc way, so we might
as well go all the way." -- m. odersky

Closes #4846.

@scabug
Copy link
Author

scabug commented Nov 13, 2011

@SethTisue said:
hooray!

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