Question

Following on from How is ScalaRunTime.stringOf(x) not failing when x.toString fails?, how is

x.toString

different from

(x: Any).toString

Also, how about

"" + x

Example REPL session:

> scala -cp joda-time-2.3.jar
Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val dt = new org.joda.time.DateTime
warning: Class org.joda.convert.FromString not found - continuing with a stub.
warning: Class org.joda.convert.ToString not found - continuing with a stub.
warning: Class org.joda.convert.FromString not found - continuing with a stub.
warning: Class org.joda.convert.ToString not found - continuing with a stub.
dt: org.joda.time.DateTime = 2014-05-15T09:27:17.929+01:00

scala> (dt: Any).toString
res0: String = 2014-05-15T09:27:17.929+01:00

scala> "" + dt
res1: String = 2014-05-15T09:27:17.929+01:00

scala> dt.toString
java.lang.AssertionError: assertion failed: org.joda.convert.ToString
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1410)
at scala.reflect.internal.Symbols$TypeSymbol.isNonBottomSubClass(Symbols.scala:3040)
at scala.reflect.internal.AnnotationInfos$AnnotationInfo.matches(AnnotationInfos.scala:305)
at scala.reflect.internal.AnnotationInfos$Annotatable$class.dropOtherAnnotations(AnnotationInfos.scala:68)
at scala.reflect.internal.AnnotationInfos$Annotatable$class.hasAnnotation(AnnotationInfos.scala:53)
at scala.reflect.internal.Symbols$Symbol.hasAnnotation(Symbols.scala:174)
at scala.tools.nsc.typechecker.Infer$class.improves$1(Infer.scala:61)
at scala.tools.nsc.typechecker.Infer$$anonfun$4.apply(Infer.scala:65)
at scala.tools.nsc.typechecker.Infer$$anonfun$4.apply(Infer.scala:65)
Was it helpful?

Solution

The answer to your other question clearly describes the problem, I'll give it another shot and describe in more detail what is going on.

When you call dt.toString you actually call the toString method of the DateTime class, which also contains an overloaded version of this method. This leads to a compilation error, not a runtime error, what actually is a bug in the compiler (but it seems to be fixed in a more recent Scala version as the other answer mentions)

In the case of (dt: Any).toString or "" + dt you are not directly calling one of the overloaded toString methods in DateTime but the one defined in Any (which is in fact java.lang.Object#toString). The compiler doesn't even see the overloaded toString method of the DateTime subclass - hence the corresponding bug doesn't make any problems.

At runtime, because of dynamic dispatch not the implementation of Any.toString is called but DateTime.toString. This dispatch is not done by scalac at compile time but by the JVM at runtime. The latter doesn't have the overloading bug - hence no error occurs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top