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

"NoSuchElementException: head of empty list" caused by asInstanceOf with higher kinds #10700

Open
tyukiand opened this issue Jan 25, 2018 · 8 comments

Comments

@tyukiand
Copy link

scala 2.12.4 typechecker crashes when trying to run the following script with "scala script.scala":

import scala.language.higherKinds

class Foo[X]
class Bar[X]
class CrashIt[A[_]] {
  def cast(a: Any): A[Int] = a.asInstanceOf[A[Int]]
}
val c = if (true) new CrashIt[Foo] else new CrashIt[Bar]
val x = c.cast("")

Stack trace:

java.util.NoSuchElementException: head of empty list
	at scala.collection.immutable.Nil$.head(List.scala:428)
	at scala.collection.immutable.Nil$.head(List.scala:425)
	at scala.tools.nsc.typechecker.ContextErrors$InferencerContextErrors$InferErrorGen$.
	  NotWithinBoundsErrorMessage(ContextErrors.scala:1045)
	at scala.tools.nsc.typechecker.ContextErrors$InferencerContextErrors$InferErrorGen$.
	  NotWithinBoundsContextErrors.scala:1052)
	at scala.tools.nsc.typechecker.Infer$Inferencer.issueBoundsError$1(Infer.scala:881)
	at scala.tools.nsc.typechecker.Infer$Inferencer.check$1(Infer.scala:887)
	at scala.tools.nsc.typechecker.Infer$Inferencer.checkBounds(Infer.scala:891)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkBounds(RefChecks.scala:1203)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.checkTypeRef(RefChecks.scala:1384)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transform$4(RefChecks.scala:1668)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transform$4$adapted(RefChecks.scala:1659)
	at scala.reflect.internal.tpe.TypeMaps$ForEachTypeTraverser.traverse(TypeMaps.scala:1102)
	at scala.reflect.internal.Types$Type.foreach(Types.scala:787)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1407)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107)
	at scala.reflect.internal.Trees.$anonfun$itransform$1(Trees.scala:1369)
	at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1368)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1186)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1416)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107)
	at scala.reflect.api.Trees$Transformer.transformTemplate(Trees.scala:2563)
	at scala.reflect.internal.Trees.$anonfun$itransform$4(Trees.scala:1420)
	at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1419)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1198)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1378)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107)
	at scala.reflect.internal.Trees.$anonfun$itransform$2(Trees.scala:1375)
	at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1373)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1198)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1416)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107)
	at scala.reflect.api.Trees$Transformer.transformTemplate(Trees.scala:2563)
	at scala.reflect.internal.Trees.$anonfun$itransform$5(Trees.scala:1425)
	at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1424)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStat(RefChecks.scala:1198)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.$anonfun$transformStats$1(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:1169)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transformStats(RefChecks.scala:107)
	at scala.reflect.internal.Trees.$anonfun$itransform$7(Trees.scala:1438)
	at scala.reflect.api.Trees$Transformer.atOwner(Trees.scala:2600)
	at scala.reflect.internal.Trees.itransform(Trees.scala:1438)
	at scala.reflect.internal.Trees.itransform$(Trees.scala:1348)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:16)
	at scala.reflect.api.Trees$Transformer.transform(Trees.scala:2555)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:1751)
	at scala.tools.nsc.typechecker.RefChecks$RefCheckTransformer.transform(RefChecks.scala:107)
	at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:140)
	at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:30)
	at scala.tools.nsc.Global$GlobalPhase.$anonfun$applyPhase$1(Global.scala:436)
	at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:429)
	at scala.tools.nsc.Global$GlobalPhase.$anonfun$run$1(Global.scala:400)
	at scala.tools.nsc.Global$GlobalPhase.$anonfun$run$1$adapted(Global.scala:400)
	at scala.collection.Iterator.foreach(Iterator.scala:929)
	at scala.collection.Iterator.foreach$(Iterator.scala:929)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1417)
	at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:400)
	at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1452)
	at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1436)
	at scala.tools.nsc.Global$Run.compileSources(Global.scala:1429)
	at scala.tools.nsc.Global$Run.compile(Global.scala:1545)
	at scala.tools.nsc.StandardCompileServer.session(CompileServer.scala:150)
	at scala.tools.util.SocketServer.$anonfun$doSession$2(SocketServer.scala:80)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
	at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
	at scala.Console$.withOut(Console.scala:163)
	at scala.tools.util.SocketServer.$anonfun$doSession$1(SocketServer.scala:80)
	at scala.tools.util.SocketServer.$anonfun$doSession$1$adapted(SocketServer.scala:75)
	at scala.tools.nsc.io.Socket.applyReaderAndWriter(Socket.scala:49)
	at scala.tools.util.SocketServer.doSession(SocketServer.scala:75)
	at scala.tools.util.SocketServer.loop$1(SocketServer.scala:91)
	at scala.tools.util.SocketServer.run(SocketServer.scala:103)
	at scala.tools.nsc.CompileServer$.$anonfun$execute$3(CompileServer.scala:216)
	at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:12)
	at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
	at scala.Console$.withOut(Console.scala:163)
	at scala.tools.nsc.CompileServer$.$anonfun$execute$2(CompileServer.scala:211)
	at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:12)
	at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58)
	at scala.Console$.withErr(Console.scala:192)
	at scala.tools.nsc.CompileServer$.main(CompileServer.scala:211)
	at scala.tools.nsc.CompileServer.main(CompileServer.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at scala.reflect.internal.util.ScalaClassLoader.$anonfun$run$2(ScalaClassLoader.scala:99)
	at scala.reflect.internal.util.ScalaClassLoader.asContext(ScalaClassLoader.scala:34)
	at scala.reflect.internal.util.ScalaClassLoader.asContext$(ScalaClassLoader.scala:30)
	at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:125)
	at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:99)
	at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:91)
	at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:125)
	at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:22)
	at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:21)
	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
	at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:29)
	at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:28)
	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:66)
	at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85)
	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)    

Information about the used compiler and environment:

scala -version
Scala code runner version 2.12.4

java -version
openjdk version "1.8.0_144"
OpenJDK Runtime Environment (build 1.8.0_144-b01)
OpenJDK 64-Bit Server VM (build 25.144-b01, mixed mode)

uname -a
Linux myHostname 4.14.13-1-ARCH #1 SMP PREEMPT Wed Jan 10 11:14:50 UTC 2018 x86_64 GNU/Linux

Some observations:

  • This does not happen with ordinary non-higher-kinded type parameters
  • This does not happen if the invocation of c.cast("") is removed
@Jasper-M
Copy link
Member

Just for fun, eliminating the asInstanceOf:

import scala.language.higherKinds

class Foo[X]
class Bar[X]
class CrashIt[A[_] >: Null] {
  def cast(a: Any): A[Int] = null
}
val c = if (true) new CrashIt[Foo] else new CrashIt[Bar]
val x = c.cast("")

@tyukiand
Copy link
Author

Even shorter: without >: Null and without returning any instances at all:

import scala.language.higherKinds

class Foo[X]
class Bar[X]
class CrashIt[A[_]] {
  def cast(a: Any): A[Int] = ???
}
val c = if (true) new CrashIt[Foo] else new CrashIt[Bar]
val x = c.cast("")

(That's not purely code-golfing, this has fewer syntactic elements, and it has the advantage of a somewhat shorter stack trace of the error.)

@joroKr21
Copy link
Member

Ugh, just this line kills the REPL:

class CrashIt[A[_]]
if (true) new CrashIt[Option] else new CrashIt[List]

@Jasper-M
Copy link
Member

Jasper-M commented Jan 25, 2018

Ugh, just this line kills the REPL

Yes, but it "works" outside of the REPL though...
This is a very dangerous corner of the compiler :-p

@hrhino hrhino changed the title Compiler crash 2.12.4: "NoSuchElementException: head of empty list" caused by asInstanceOf with higher kinds "NoSuchElementException: head of empty list" caused by asInstanceOf with higher kinds Jan 25, 2018
@hrhino
Copy link
Member

hrhino commented Jan 25, 2018

This goes way farther back (before 2.11, even).

@smarter smarter added the typer label Feb 6, 2018
@joroKr21
Copy link
Member

Uh-oh, note the ill-kinded type inference:

scala> List(new CrashIt[Option], new CrashIt[List])
<console>:39: error: type mismatch;
 found   : CrashIt[Option]
 required: CrashIt[_ >: List with Option <: Product with Serializable]
       List(new CrashIt[Option], new CrashIt[List])
            ^
<console>:39: error: type mismatch;
 found   : CrashIt[List]
 required: CrashIt[_ >: List with Option <: Product with Serializable]
       List(new CrashIt[Option], new CrashIt[List])
                                 ^

Also, I don't understand why:

can't existentially abstract over parameterized type

https://github.com/scala/scala/blob/8ad55a4ed8424aa6da372d3b6e41750f3d098523/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala#L722-L723

joroKr21 added a commit to joroKr21/scala that referenced this issue Mar 14, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types. Improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
joroKr21 added a commit to joroKr21/scala that referenced this issue Apr 24, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types. Improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
joroKr21 added a commit to joroKr21/scala that referenced this issue Apr 25, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types. Improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
joroKr21 added a commit to joroKr21/scala that referenced this issue Apr 25, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types. Improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
joroKr21 added a commit to joroKr21/scala that referenced this issue Apr 25, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types. Improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
joroKr21 added a commit to joroKr21/scala that referenced this issue May 26, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types. Improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
adriaanm pushed a commit to joroKr21/scala that referenced this issue Aug 3, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types when merging type constructor arguments
that are supplied for a type constructor parameter.

This improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
adriaanm pushed a commit to scala/scala that referenced this issue Aug 3, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types when merging type constructor arguments
that are supplied for a type constructor parameter.

This improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
adriaanm pushed a commit to joroKr21/scala that referenced this issue Aug 6, 2018
When computing the `lub/glb` of HKTs take care to produce
well-kinded types when merging type constructor arguments
that are supplied for a type constructor parameter.

This improves type inference.

A few tests with `-Xstrict-inference` were changed.
Other tests reveal a limitation of higher-kinded existentials.

Fixes scala/bug#8882 and promotes scala/bug#10700 to an error.
@SethTisue
Copy link
Member

scala/scala#6352 promotes this to an error for 2.13

@som-snytt
Copy link

My PR is just not to crash when constructing a string.

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

7 participants