Skip to content

Evaluation of invalid Function crashes Scala #21952

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

Closed
ghost opened this issue Nov 14, 2024 · 2 comments · Fixed by #21970
Closed

Evaluation of invalid Function crashes Scala #21952

ghost opened this issue Nov 14, 2024 · 2 comments · Fixed by #21970
Labels
area:transform itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Milestone

Comments

@ghost
Copy link

ghost commented Nov 14, 2024

Compiler version

3.5.2

Minimized code

When running in scala-cli, the following crashes:

(new Function[(Int, Int), Int] {def apply(a: Int, b: Int): Int = a * b})(2, 3)

Of course, the above code is invalid, there should be a single tuple argument to apply. The unexpected result is that Scala crashes altogether instead of just throwing an exception.

It should be replaced with any of the following, which both work:

(new Function[(Int, Int), Int] {def apply(a: (Int, Int)): Int = a._1 * a._2})(2, 3)
(new Function2[Int, Int, Int] {def apply(a: Int, b: Int): Int = a * b})(2, 3)

Output (click arrow to expand)

  unhandled exception while running MegaPhase{crossVersionChecks, firstTransform, checkReentrant, elimPackagePrefixes, cookComments, checkLoopingImplicits, betaReduce, inlineVals, expandSAMs, elimRepeated, refchecks} on rs$line$1

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/scala/scala3/issues/new/choose
  For non-enriched exceptions, compile with -Xno-enrich-error-messages.

     while compiling: rs$line$1
        during phase: MegaPhase{crossVersionChecks, firstTransform, checkReentrant, elimPackagePrefixes, cookComments, checkLoopingImplicits, betaReduce, inlineVals, expandSAMs, elimRepeated, refchecks}
                mode: Mode(ImplicitsEnabled,ReadPositions,Interactive)
     library version: version 2.13.14
    compiler version: version 3.5.2
            settings: -Xcook-docs true -Xread-docs true -classpath /home/beaver/.my/java/scala3/maven2/org/scala-lang/scala3-library_3/3.5.2/scala3-library_3-3.5.2.jar:/home/beaver/.my/java/scala3/maven2/org/scala-lang/scala-library/2.13.14/scala-library-2.13.14.jar -d <REPL compilation output>

Exception in thread "main" java.lang.UnsupportedOperationException: tail of empty list
        at scala.collection.immutable.Nil$.tail(List.scala:665)
        at scala.collection.immutable.Nil$.tail(List.scala:662)
        at dotty.tools.dotc.core.Substituters$.substSym(Substituters.scala:87)
        at dotty.tools.dotc.core.Types$Type.substSym(Types.scala:1942)
        at dotty.tools.dotc.ast.TreeTypeMap$$anon$2.apply(TreeTypeMap.scala:75)
        at dotty.tools.dotc.ast.TreeTypeMap.mapType(TreeTypeMap.scala:76)
        at dotty.tools.dotc.ast.TreeTypeMap.transform(TreeTypeMap.scala:110)
        at dotty.tools.dotc.transform.BetaReduce$.reduceApplication(BetaReduce.scala:151)
        at dotty.tools.dotc.transform.BetaReduce$.recur$1(BetaReduce.scala:82)
        at dotty.tools.dotc.transform.BetaReduce$.apply(BetaReduce.scala:95)
        at dotty.tools.dotc.transform.BetaReduce.transformApply(BetaReduce.scala:44)
        at dotty.tools.dotc.transform.MegaPhase.goApply(MegaPhase.scala:681)
        at dotty.tools.dotc.transform.MegaPhase.goApply(MegaPhase.scala:682)
        at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:297)
        at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454)
        at dotty.tools.dotc.transform.MegaPhase.mapValDef$1(MegaPhase.scala:251)
        at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:256)
        at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452)
        at dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465)
        at dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465)
        at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:376)
        at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454)
        at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:272)
        at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452)
        at dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465)
        at dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465)
        at dotty.tools.dotc.transform.MegaPhase.mapPackage$1(MegaPhase.scala:396)
        at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:399)
        at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454)
        at dotty.tools.dotc.transform.MegaPhase.transformUnit(MegaPhase.scala:481)
        at dotty.tools.dotc.transform.MegaPhase.run(MegaPhase.scala:493)
        at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:380)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.immutable.List.foreach(List.scala:334)
        at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:373)
        at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:343)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
        at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
        at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
        at dotty.tools.dotc.Run.runPhases$1(Run.scala:336)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:384)
        at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:396)
        at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:396)
        at dotty.tools.dotc.Run.compileUnits(Run.scala:288)
        at dotty.tools.repl.ReplCompiler.compile(ReplCompiler.scala:88)
        at dotty.tools.repl.ReplDriver.compile(ReplDriver.scala:321)
        at dotty.tools.repl.ReplDriver.interpret(ReplDriver.scala:283)
        at dotty.tools.repl.ReplDriver.loop$1(ReplDriver.scala:196)
        at dotty.tools.repl.ReplDriver.runUntilQuit$$anonfun$1(ReplDriver.scala:199)
        at dotty.tools.repl.ReplDriver.withRedirectedOutput(ReplDriver.scala:238)
        at dotty.tools.repl.ReplDriver.runBody$$anonfun$1(ReplDriver.scala:212)
        at dotty.tools.runner.ScalaClassLoader$.asContext(ScalaClassLoader.scala:80)
        at dotty.tools.repl.ReplDriver.runBody(ReplDriver.scala:212)
        at dotty.tools.repl.ReplDriver.runUntilQuit(ReplDriver.scala:199)
        at dotty.tools.repl.ReplDriver.tryRunning(ReplDriver.scala:136)
        at dotty.tools.repl.Main$.main(Main.scala:7)
        at dotty.tools.repl.Main.main(Main.scala)

Note

Note also that simply creating the function only throws an exception, without crashing:

new Function[(Int, Int), Int] {def apply(a: Int, b: Int): Int = a * b}

Output:

-- Error: ----------------------------------------------------------------------------------------------------------------------------------
1 |new Function[(Int, Int), Int] {def apply(a: Int, b: Int): Int = a * b}
  |^
  |object creation impossible, since def apply(v1: T1): R in trait Function1 in package scala is not defined 
1 error found
@ghost ghost added itype:bug itype:crash stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 14, 2024
@Gedochao Gedochao added area:transform and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Nov 15, 2024
@Gedochao
Copy link
Contributor

scala-cli compile --script-snippet '(new Function[(Int, Int), Int] {def apply(a: Int, b: Int): Int = a * b})(2, 3)'

Here's the output when compiled outside of the REPL:

-- Error: /var/folders/5n/_ggj7kk93czdt_n0jzrk8s780000gn/T/14507058402592798626/.scala-build/14507058402592798626_22f9a8571a-571f19b3f1/src_generated/main/snippet.scala:7:1 
7 |(new Function[(Int, Int), Int] {def apply(a: Int, b: Int): Int = a * b})(2, 3)
  | ^
  |object creation impossible, since def apply(v1: T1): R in trait Function1 in package scala is not defined 

  unhandled exception while running MegaPhase{crossVersionChecks, firstTransform, checkReentrant, elimPackagePrefixes, cookComments, checkLoopingImplicits, betaReduce, inlineVals, expandSAMs, elimRepeated, refchecks} on /var/folders/5n/_ggj7kk93czdt_n0jzrk8s780000gn/T/14507058402592798626/.scala-build/14507058402592798626_22f9a8571a-571f19b3f1/src_generated/main/snippet.scala

  An unhandled exception was thrown in the compiler.
  Please file a crash report here:
  https://github.com/scala/scala3/issues/new/choose
  For non-enriched exceptions, compile with -Xno-enrich-error-messages.

     while compiling: /var/folders/5n/_ggj7kk93czdt_n0jzrk8s780000gn/T/14507058402592798626/.scala-build/14507058402592798626_22f9a8571a-571f19b3f1/src_generated/main/snippet.scala
        during phase: MegaPhase{crossVersionChecks, firstTransform, checkReentrant, elimPackagePrefixes, cookComments, checkLoopingImplicits, betaReduce, inlineVals, expandSAMs, elimRepeated, refchecks}
                mode: Mode(ImplicitsEnabled)
     library version: version 2.13.14
    compiler version: version 3.5.1
            settings: -classpath /Users/pchabelski/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.5.1/scala3-library_3-3.5.1.jar:/Users/pchabelski/Library/Caches/Coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.14/scala-library-2.13.14.jar -d /var/folders/5n/_ggj7kk93czdt_n0jzrk8s780000gn/T/14507058402592798626/.scala-build/14507058402592798626_22f9a8571a-571f19b3f1/classes/main -explain true -sourceroot /var/folders/5n/_ggj7kk93czdt_n0jzrk8s780000gn/T/14507058402592798626

Exception in thread "main" java.lang.UnsupportedOperationException: tail of empty list
	at scala.collection.immutable.Nil$.tail(List.scala:665)
	at scala.collection.immutable.Nil$.tail(List.scala:662)
	at dotty.tools.dotc.core.Substituters$.substSym(Substituters.scala:87)
	at dotty.tools.dotc.core.Types$Type.substSym(Types.scala:1941)
	at dotty.tools.dotc.ast.TreeTypeMap$$anon$2.apply(TreeTypeMap.scala:75)
	at dotty.tools.dotc.ast.TreeTypeMap.mapType(TreeTypeMap.scala:76)
	at dotty.tools.dotc.ast.TreeTypeMap.transform(TreeTypeMap.scala:110)
	at dotty.tools.dotc.transform.BetaReduce$.reduceApplication(BetaReduce.scala:151)
	at dotty.tools.dotc.transform.BetaReduce$.recur$1(BetaReduce.scala:82)
	at dotty.tools.dotc.transform.BetaReduce$.apply(BetaReduce.scala:95)
	at dotty.tools.dotc.transform.BetaReduce.transformApply(BetaReduce.scala:44)
	at dotty.tools.dotc.transform.MegaPhase.goApply(MegaPhase.scala:681)
	at dotty.tools.dotc.transform.MegaPhase.goApply(MegaPhase.scala:682)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:297)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454)
	at dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465)
	at dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:376)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454)
	at dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:272)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452)
	at dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465)
	at dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465)
	at dotty.tools.dotc.transform.MegaPhase.mapPackage$1(MegaPhase.scala:396)
	at dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:399)
	at dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454)
	at dotty.tools.dotc.transform.MegaPhase.transformUnit(MegaPhase.scala:481)
	at dotty.tools.dotc.transform.MegaPhase.run(MegaPhase.scala:493)
	at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:380)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:334)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:373)
	at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:343)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:336)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:384)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:396)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:396)
	at dotty.tools.dotc.Run.compileSources(Run.scala:282)
	at dotty.tools.dotc.Run.compile(Run.scala:267)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:37)
	at dotty.tools.dotc.Driver.process(Driver.scala:201)
	at dotty.tools.dotc.Driver.process(Driver.scala:169)
	at dotty.tools.dotc.Driver.process(Driver.scala:181)
	at dotty.tools.dotc.Driver.main(Driver.scala:211)
	at dotty.tools.dotc.Main.main(Main.scala)

@Gedochao Gedochao added the regression This worked in a previous version but doesn't anymore label Nov 15, 2024
@Gedochao
Copy link
Contributor

Labelling as a regression, as it seems this used to not crash pre-3.3.1.

Last good stable version: 3.3.0
First bad stable version: 3.3.1

odersky added a commit that referenced this issue Nov 19, 2024
…pe (#21970)


It's possible to define Functions with wrong apply methods by hand which
will give an error but pass on a function that does fails beta
reduction.

Fixes #21952
KacperFKorban pushed a commit to dotty-staging/dotty that referenced this issue Nov 20, 2024
… shape

It's possible to define Functions with wrong apply methods by hand which will
give an error but pass on a function that does fails beta reduction.

Fixes scala#21952
@WojciechMazur WojciechMazur added this to the 3.6.3 milestone Nov 25, 2024
KacperFKorban pushed a commit to dotty-staging/dotty that referenced this issue Nov 29, 2024
… shape

It's possible to define Functions with wrong apply methods by hand which will
give an error but pass on a function that does fails beta reduction.

Fixes scala#21952
tgodzik pushed a commit to scala/scala3-lts that referenced this issue Mar 8, 2025
… shape

It's possible to define Functions with wrong apply methods by hand which will
give an error but pass on a function that does fails beta reduction.

Fixes scala#21952

[Cherry-picked 6896ea2]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:transform itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants