Skip to content

NoSuchElementException when passing implicit dependently typed function to method #3692

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
Jasper-M opened this issue Dec 22, 2017 · 0 comments

Comments

@Jasper-M
Copy link
Contributor

Jasper-M commented Dec 22, 2017

class C { type T }

object Main {
  def main(args: Array[String]): Unit = {
    val choose: implicit (c: C) => Set[Int] = Set.empty
    def applyF(f: (c: C) => Set[Int]) = f(new C{type T=Int})
    applyF(choose)
  }
}

Crashes with:

Exception in thread "main" java.util.NoSuchElementException
	at scala.collection.LinearSeqOptimized.last(LinearSeqOptimized.scala:146)
	at scala.collection.LinearSeqOptimized.last$(LinearSeqOptimized.scala:145)
	at scala.collection.immutable.List.last(List.scala:86)
	at dotty.tools.dotc.typer.ProtoTypes$.$anonfun$normalize$1(ProtoTypes.scala:473)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.ProtoTypes$.normalize(ProtoTypes.scala:450)
	at dotty.tools.dotc.typer.ErrorReporting$Errors.typeMismatch(ErrorReporting.scala:108)
	at dotty.tools.dotc.typer.Typer.recover$1(Typer.scala:2336)
	at dotty.tools.dotc.typer.Typer.adaptToSubType$1(Typer.scala:2347)
	at dotty.tools.dotc.typer.Typer.adaptNoArgsOther$1(Typer.scala:2240)
	at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:2285)
	at dotty.tools.dotc.typer.Typer.adaptInterpolated(Typer.scala:2408)
	at dotty.tools.dotc.typer.Typer.$anonfun$adapt$3(Typer.scala:1934)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.$anonfun$adapt$1(Typer.scala:1927)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:1927)
	at dotty.tools.dotc.typer.ProtoTypes$FunProto.typedArg(ProtoTypes.scala:244)
	at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:639)
	at dotty.tools.dotc.typer.Applications$ApplyToUntyped.typedArg(Applications.scala:637)
	at dotty.tools.dotc.typer.Applications$Application.addTyped$1(Applications.scala:412)
	at dotty.tools.dotc.typer.Applications$Application.matchArgs(Applications.scala:451)
	at dotty.tools.dotc.typer.Applications$Application.init(Applications.scala:233)
	at dotty.tools.dotc.typer.Applications$TypedApply.<init>(Applications.scala:543)
	at dotty.tools.dotc.typer.Applications$ApplyToUntyped.<init>(Applications.scala:638)
	at dotty.tools.dotc.typer.Applications.simpleApply$1(Applications.scala:694)
	at dotty.tools.dotc.typer.Applications.$anonfun$typedApply$7(Applications.scala:719)
	at dotty.tools.dotc.typer.Typer.tryEither(Typer.scala:1830)
	at dotty.tools.dotc.typer.Applications.$anonfun$typedApply$1(Applications.scala:720)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Applications.realApply$1(Applications.scala:664)
	at dotty.tools.dotc.typer.Applications.typedApply(Applications.scala:764)
	at dotty.tools.dotc.typer.Applications.typedApply$(Applications.scala:662)
	at dotty.tools.dotc.typer.Typer.typedApply(Typer.scala:69)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1698)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1748)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1765)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1761)
	at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1822)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedBlock$1(Typer.scala:634)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Typer.typedBlock(Typer.scala:626)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1705)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1748)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1765)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1761)
	at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1822)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedDefDef$1(Typer.scala:1378)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:1360)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1686)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1747)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1765)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1761)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:1787)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:1810)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedClassDef$1(Typer.scala:1471)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:1401)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1689)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1747)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1765)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1761)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:1787)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:1810)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedClassDef$1(Typer.scala:1471)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:1401)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1689)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1747)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1765)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1761)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:1787)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:1810)
	at dotty.tools.dotc.typer.Typer.$anonfun$typedPackageDef$1(Typer.scala:1584)
	at dotty.tools.dotc.util.Stats$.track(Stats.scala:35)
	at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:1571)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1729)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1748)
	at dotty.tools.dotc.typer.Typer.$anonfun$typed$2(Typer.scala:1765)
	at dotty.tools.dotc.reporting.trace$.op1$2(trace.scala:25)
	at dotty.tools.dotc.reporting.trace$.apply(trace.scala:26)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1761)
	at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1822)
	at dotty.tools.dotc.typer.FrontEnd.$anonfun$typeCheck$1(FrontEnd.scala:66)
	at dotty.tools.dotc.typer.FrontEnd.monitor(FrontEnd.scala:34)
	at dotty.tools.dotc.typer.FrontEnd.typeCheck(FrontEnd.scala:64)
	at dotty.tools.repl.REPLFrontEnd.runOn(ReplFrontEnd.scala:25)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$3(Run.scala:125)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
	at dotty.tools.dotc.util.Stats$.trackTime(Stats.scala:47)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$2(Run.scala:123)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$2$adapted(Run.scala:121)
	at scala.collection.IndexedSeqOptimized.foreach(IndexedSeqOptimized.scala:32)
	at scala.collection.IndexedSeqOptimized.foreach$(IndexedSeqOptimized.scala:29)
	at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:191)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:121)
	at dotty.tools.dotc.Run.$anonfun$compileUnits$1(Run.scala:141)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:88)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:107)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:99)
	at dotty.tools.repl.ReplCompiler.runCompilationUnit(ReplCompiler.scala:188)
	at dotty.tools.repl.ReplCompiler.compile(ReplCompiler.scala:197)
	at dotty.tools.repl.ReplDriver.compile(ReplDriver.scala:223)
	at dotty.tools.repl.ReplDriver.interpret(ReplDriver.scala:196)
	at dotty.tools.repl.ReplDriver.runUntilQuit(ReplDriver.scala:149)
	at dotty.tools.repl.Main$.main(Main.scala:6)
	at dotty.tools.repl.Main.main(Main.scala)

I tried to minimize as much as possible. Replace Int with c.T and the crash remains the same. Giving f an implicit function type doesn't make a difference.
If you replace (c: C) with C the crash goes away.

I would also like to add that I think there's an inconsistency lurking behind this issue. Judging from the stack trace it appears the compiler wants to issue an error message for this code, however the following code compiles without error:

val choose: implicit (c: C) => Set[Int] = implicit c => Set.empty
def applyF(f: C => Set[Int]) = f(new C{type T=Int})
applyF(choose)
odersky added a commit to dotty-staging/dotty that referenced this issue Dec 28, 2017
With this change,

    (implicit x: C): D  <:  (x: C): D

but not the other way around. This affects subtyping
of dependent implicit function types. Now:

    (implicit x: C) => D  <:  (x: C) => D

See also scala#2000.

As a second change, prevent crashing on type mismatch errors
involving dependent implicit function types.
odersky added a commit that referenced this issue Jan 13, 2018
Fix #3692: Generalize implicit function subtyping.
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