Skip to content

Compiler error and crash on context-function arg with default #12019

Closed
@japgolly

Description

@japgolly

Problems

  1. Compiler errors
  2. Compiler crashes
  3. Ambiguous syntax discovered

Compiler version

Tried both:

  • 3.0.0-RC1
  • 3.0.1-RC1-bin-20210406-b0061c4-NIGHTLY

Minimized code

import scala.quoted.*

object Eg1 {

  // no default arg: ok
  def ok  (f: (q: Quotes) ?=> q.reflect.Term) = ()

  // default the function *reference* to null: compilation error
  def ko_1(f: (q: Quotes) ?=> q.reflect.Term = null) = ()

  // default the function *result* to null: compilation error
  def ko_2(f: (q: Quotes) ?=> q.reflect.Term = (_: Quotes) ?=> null) = ()
}

object Eg2 {

  // no default arg: ok
  def ok  (f: (q: Quotes) ?=> q.reflect.ValDef => q.reflect.Term) = ()

  // default the function *reference* to null: crash!
  def ko_1(f: (q: Quotes) ?=> q.reflect.ValDef => q.reflect.Term = null) = ()

  // default the function *result* to null: crash!
  def ko_2(f: (q: Quotes) ?=> q.reflect.ValDef => q.reflect.Term = (_: Quotes) ?=> null) = ()
}

Output

[error] -- [E007] Type Mismatch Error: ~/scala3bug/sbt/src/main/scala/asd.scala:9:47 
[error] 9 |  def ko_1(f: (q: Quotes) ?=> q.reflect.Term = null) = ()
[error]   |                                               ^^^^
[error]   |                                      Found:    (quoted.Quotes) ?=> Null
[error]   |                                      Required: (q: quoted.Quotes) ?=> <?>
[error] -- [E007] Type Mismatch Error: ~/scala3bug/sbt/src/main/scala/asd.scala:12:47 
[error] 12 |  def ko_2(f: (q: Quotes) ?=> q.reflect.Term = (_: Quotes) ?=> null) = ()
[error]    |                                               ^^^^^^^^^^^^^^^^^^^^
[error]    |                                    Found:    (quoted.Quotes) ?=> Null
[error]    |                                    Required: (q: quoted.Quotes) ?=> <?>
[info] exception occurred while typechecking ~/scala3bug/sbt/src/main/scala/asd.scala
[info] exception occurred while compiling ~/scala3bug/sbt/src/main/scala/asd.scala
java.lang.Error: internal error: type of right-hand side (quoted.Quotes) ?=> <?> => <?> is not fully defined, pos = <607..611> while compiling ~/scala3bug/sbt/src/main/scala/asd.scala
[error] ## Exception when compiling 2 sources to ~/scala3bug/sbt/target/scala-3.0.1-RC1/classes
[error] java.lang.Error: internal error: type of right-hand side (quoted.Quotes) ?=> <?> => <?> is not fully defined, pos = <607..611>
[error] dotty.tools.dotc.typer.Inferencing$.fullyDefinedType(Inferencing.scala:54)
[error] dotty.tools.dotc.typer.Namer.lhsType$1(Namer.scala:1539)
[error] dotty.tools.dotc.typer.Namer.inferredType$1(Namer.scala:1550)
[error] dotty.tools.dotc.typer.Namer.valOrDefDefSig(Namer.scala:1559)
[error] dotty.tools.dotc.typer.Namer.defDefSig(Namer.scala:1642)
[error] dotty.tools.dotc.typer.Namer$Completer.typeSig(Namer.scala:703)
[error] dotty.tools.dotc.typer.Namer$Completer.completeInCreationContext(Namer.scala:826)
[error] dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:727)
[error] dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:167)
[error] dotty.tools.dotc.core.Denotations$Denotation.completeInfo$1(Denotations.scala:188)
[error] dotty.tools.dotc.core.Denotations$Denotation.info(Denotations.scala:190)
[error] dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:369)
[error] dotty.tools.dotc.typer.Typer.retrieveSym(Typer.scala:2616)
[error] dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2641)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2735)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2801)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2805)
[error] dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2827)
[error] dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2877)
[error] dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:2333)
[error] dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$2(Typer.scala:2662)
[error] dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2666)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2735)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2801)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2805)
[error] dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2827)
[error] dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2877)
[error] dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:2456)
[error] dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2707)
[error] dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2736)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2801)
[error] dotty.tools.dotc.typer.Typer.typed(Typer.scala:2805)
[error] dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:2921)
[error] dotty.tools.dotc.typer.FrontEnd.liftedTree1$1(FrontEnd.scala:79)
[error] dotty.tools.dotc.typer.FrontEnd.typeCheck$$anonfun$1(FrontEnd.scala:84)
[error] dotty.tools.dotc.typer.FrontEnd.monitor(FrontEnd.scala:43)
[error] dotty.tools.dotc.typer.FrontEnd.typeCheck(FrontEnd.scala:85)
[error] dotty.tools.dotc.typer.FrontEnd.runOn$$anonfun$3(FrontEnd.scala:120)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.immutable.List.foreach(List.scala:333)
[error] dotty.tools.dotc.typer.FrontEnd.runOn(FrontEnd.scala:120)
[error] dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:205)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
[error] dotty.tools.dotc.Run.runPhases$5(Run.scala:215)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:223)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
[error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:67)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:230)
[error] dotty.tools.dotc.Run.compileSources(Run.scala:166)
[error] dotty.tools.dotc.Run.compile(Run.scala:150)
[error] dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
[error] dotty.tools.xsbt.CompilerBridgeDriver.run(CompilerBridgeDriver.java:88)
[error] dotty.tools.xsbt.CompilerBridge.run(CompilerBridge.java:22)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:92)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:186)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:241)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:176)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:157)
[error] sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:157)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:204)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:573)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:573)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:174)
[error] sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:172)
[error] sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:459)
[error] sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
[error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
[error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:261)
[error] sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:414)
[error] sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:499)
[error] sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:401)
[error] sbt.internal.inc.Incremental$.apply(Incremental.scala:166)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:573)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:491)
[error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:420)
[error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
[error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2200)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2157)
[error] sbt.internal.io.Retry$.apply(Retry.scala:40)
[error] sbt.internal.io.Retry$.apply(Retry.scala:23)
[error] sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:31)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2153)
[error] scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] sbt.Execute.work(Execute.scala:291)
[error] sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[error] java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[error] java.base/java.lang.Thread.run(Thread.java:834)
[error]            
[error] stack trace is suppressed; run last Compile / compileIncremental for the full output
[error] (Compile / compileIncremental) java.lang.Error: internal error: type of right-hand side (quoted.Quotes) ?=> <?> => <?> is not fully defined, pos = <607..611>
[error] Total time: 0 s, completed 8 Apr. 2021, 9:44:15 am

Expectation

  1. It should all compile

  2. The ko_1 methods are actually ambiguous in that they could be interpreted as setting the f reference to null, or the compiler could synthesise a leading (_ :Quotes) ?=> like it does elsewhere. Whichever interpretation is correct, it should be clarified and enforced so that it's unambiguous and clear to users. Otherwise we'll be introducing new confusing Scala Puzzlers.

  3. It's a bit of a hack that carries over from Scala 2 but there should be a way to declare context-function arguments and have the argument itself default to null. You could do the same thing by wrapping all the arguments in Option which is morally great, but has the unfortunate downside that end-users have to wrap their arguments in Some which decreases dev ergonomics a bit. I wonder if a more direct solution would be to introduce a concept of optional args at a language level? Something like

    def f(i: Int?, j: Int?): Int = ???
    // ^^ translates to def f(i: Option[Int]=None, j: Option[Int]=None): Int = ???
    
    f()
    f(1)   // translates to f(Some(1))
    f(j=3) // translates to f(j = Some(3))

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions