Skip to content

jackson-module-scala ClassTagExtensionsTest causes compiler loop (Scala 2.13.2 and after) #12422

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

Open
pjfanning opened this issue Jun 23, 2021 · 20 comments
Labels
compiler crash fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/)
Milestone

Comments

@pjfanning
Copy link

pjfanning commented Jun 23, 2021

reproduction steps

using Scala 2.13.2 up to 2.13.6, jackson-module-scala ClassTagExtensionsTest causes compiler loop and test compilation does not complete

works ok with Scala 3.0.0 and Scala 2.11, 2.12 and also 2.13.0 and 2.13.1.

Build uses sbt (sbt test will reproduce the problem). Test compilation runs indefinitely.

problem

ClassTagExtensions relies on implicit conversions and ClassTags and maybe this is what is causing the problem.

Removing ClassTagExtensionsTest allows the test compilation and test run to succeed.

I'd appreciate if someone who knows more about the scala compiler than I do could have a look.

@SethTisue
Copy link
Member

The most useful next step here would be to reduce the code in question to an standalone MCVE that reproduces the bug outside the context of the full jackson-module-scala codebase. I don't believe doing that minimization work requires compiler knowledge.

@pjfanning
Copy link
Author

Thanks @SethTisue - this is probably not a minimal reproducible case but it is more directed -- https://github.com/pjfanning/jackson-classtag-sample

@SethTisue
Copy link
Member

SethTisue commented Jun 23, 2021

Yes, that that does look nicer. But the crucial big thing would be to eliminate the external dependency (the dependency on jackson-module-scala).

Test compilation runs indefinitely

In such cases, a thread dump is useful to see what's at the top of the stack, so we know where it's getting stuck. At minimum we want to know what phase it's getting stuck in, but usually the stack trace gives even more specific and helpful clues than that.

@pjfanning
Copy link
Author

I'll see what I can do about producing a standalone test case.

In the mean time, this is the most active thread when the code is looping.

"pool-7-thread-4" #91 prio=5 os_prio=31 tid=0x00007fea2e8f7000 nid=0x7b03 runnable [0x0000700010b3d000]
   java.lang.Thread.State: RUNNABLE
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6040)
	at scala.tools.nsc.typechecker.Typers$Typer.typedTypeApply$1(Typers.scala:6133)
	at scala.tools.nsc.typechecker.Typers$Typer.typedOutsidePatternMode$1(Typers.scala:5962)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5995)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6041)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$typed1$41(Typers.scala:5074)
	at scala.tools.nsc.typechecker.Typers$Typer$$Lambda$5017/699115963.apply(Unknown Source)
	at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:698)
	at scala.tools.nsc.typechecker.Typers$Typer.normalTypedApply$1(Typers.scala:5076)
	at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:5104)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5985)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6041)
	at scala.tools.nsc.typechecker.Typers$Typer.typedPos(Typers.scala:6117)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.success$1(Implicits.scala:1471)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.tagOfType(Implicits.scala:1508)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.materializeImplicit(Implicits.scala:1663)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1717)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)
	at scala.tools.nsc.Global$$anon$6.inferImplicit(Global.scala:485)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor(Implicits.scala:47)
	at scala.tools.nsc.typechecker.Implicits.inferImplicitFor$(Implicits.scala:46)
	at scala.tools.nsc.Global$$anon$6.inferImplicitFor(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.applyImplicitArgs(Typers.scala:263)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6056)
	at scala.tools.nsc.typechecker.Typers$Typer.computeType(Typers.scala:6130)
	at scala.tools.nsc.typechecker.Namers$Namer.assignTypeToTree(Namers.scala:1138)
	at scala.tools.nsc.typechecker.Namers$Namer.valDefSig(Namers.scala:1750)
	at scala.tools.nsc.typechecker.Namers$Namer.memberSig(Namers.scala:1935)
	at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1885)
	at scala.tools.nsc.typechecker.Namers$Namer$ValTypeCompleter.completeImpl(Namers.scala:955)
	at scala.tools.nsc.typechecker.Namers$LockingTypeCompleter.complete(Namers.scala:2083)
	at scala.tools.nsc.typechecker.Namers$LockingTypeCompleter.complete$(Namers.scala:2081)
	at scala.tools.nsc.typechecker.Namers$TypeCompleterBase.complete(Namers.scala:2076)
	at scala.reflect.internal.Symbols$Symbol.completeInfo(Symbols.scala:1561)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1533)
	at scala.reflect.internal.Symbols$Symbol.initialize(Symbols.scala:1722)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5625)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6041)
	at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:6119)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$typedStats$8(Typers.scala:3410)
	at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3410)
	at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:2064)
	at scala.tools.nsc.typechecker.Typers$Typer.typedModuleDef(Typers.scala:1940)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5952)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6041)
	at scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:6119)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$typedStats$8(Typers.scala:3410)
	at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3410)
	at scala.tools.nsc.typechecker.Typers$Typer.typedPackageDef$1(Typers.scala:5634)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5954)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6041)
	at scala.tools.nsc.typechecker.Analyzer$typerFactory$TyperPhase.apply(Analyzer.scala:112)
	at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:454)
	at scala.tools.nsc.typechecker.Analyzer$typerFactory$TyperPhase.run(Analyzer.scala:101)
	at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1519)
	at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1503)
	at scala.tools.nsc.Global$Run.compileSources(Global.scala:1495)
	at scala.tools.nsc.Global$Run.compileFiles(Global.scala:1609)
	at xsbt.CachedCompiler0.run(CompilerBridge.scala:163)
	at xsbt.CachedCompiler0.run(CompilerBridge.scala:134)
	- locked <0x0000000703621340> (a xsbt.CachedCompiler0)
	at xsbt.CompilerBridge.run(CompilerBridge.scala:39)
	at sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91)
	at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:186)
	at sbt.internal.inc.MixedAnalyzingCompiler$$Lambda$4725/42073860.apply$mcV$sp(Unknown Source)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
	at sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:241)
	at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:176)
	at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:157)
	at sbt.internal.inc.MixedAnalyzingCompiler$$Lambda$4721/1604459255.apply(Unknown Source)
	at sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:239)
	at sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:157)
	at sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:204)
	at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:528)
	at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:528)
	at sbt.internal.inc.IncrementalCompilerImpl$$Lambda$3199/1944085609.apply(Unknown Source)
	at sbt.internal.inc.Incremental$.$anonfun$apply$5(Incremental.scala:174)
	at sbt.internal.inc.Incremental$.$anonfun$apply$5$adapted(Incremental.scala:172)
	at sbt.internal.inc.Incremental$$$Lambda$3206/604144549.apply(Unknown Source)
	at sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:457)
	at sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:116)
	at sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56)
	at sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52)
	at sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:261)
	at sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:412)
	at sbt.internal.inc.Incremental$$$Lambda$3243/1010662414.apply(Unknown Source)
	at sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:499)
	at sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:399)
	at sbt.internal.inc.Incremental$.apply(Incremental.scala:166)
	at sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:528)
	at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:482)
	at sbt.internal.inc.IncrementalCompilerImpl$$Lambda$3113/2129967190.apply(Unknown Source)
	at sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332)
	at sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:420)
	at sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137)
	at sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2357)
	at sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2314)
	at sbt.Defaults$$$Lambda$3107/698146021.apply(Unknown Source)
	at sbt.internal.io.Retry$.apply(Retry.scala:46)
	at sbt.internal.io.Retry$.apply(Retry.scala:28)
	at sbt.internal.io.Retry$.apply(Retry.scala:23)
	at sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:31)
	at sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2310)
	at sbt.Defaults$$$Lambda$830/1210607069.apply(Unknown Source)
	at scala.Function1.$anonfun$compose$1(Function1.scala:49)
	at scala.Function1$$Lambda$247/60100348.apply(Unknown Source)
	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
	at sbt.internal.util.$tilde$greater$$Lambda$2637/171160803.apply(Unknown Source)
	at sbt.std.Transform$$anon$4.work(Transform.scala:68)
	at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
	at sbt.Execute$$Lambda$2665/1642003496.apply(Unknown Source)
	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
	at sbt.Execute.work(Execute.scala:291)
	at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
	at sbt.Execute$$Lambda$2648/225753796.apply(Unknown Source)
	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
	at sbt.ConcurrentRestrictions$$anon$4$$Lambda$2663/44249014.apply(Unknown Source)
	at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
	- <0x00000007019fa228> (a java.util.concurrent.ThreadPoolExecutor$Worker)

@pjfanning
Copy link
Author

also on same thread later:

"pool-7-thread-4" #91 prio=5 os_prio=31 tid=0x00007fea2e8f7000 nid=0x7b03 runnable [0x0000700010b3c000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.System.identityHashCode(Native Method)
	at scala.reflect.internal.Trees$Tree.hashCode(Trees.scala:102)
	at java.util.WeakHashMap.hash(WeakHashMap.java:298)
	at java.util.WeakHashMap.get(WeakHashMap.java:396)
	at scala.collection.convert.JavaCollectionWrappers$JMapWrapperLike.get(JavaCollectionWrappers.scala:324)
	at scala.collection.convert.JavaCollectionWrappers$JMapWrapperLike.get$(JavaCollectionWrappers.scala:323)
	at scala.collection.convert.JavaCollectionWrappers$AbstractJMapWrapper.get(JavaCollectionWrappers.scala:309)
	at scala.collection.MapOps.contains(Map.scala:281)
	at scala.collection.MapOps.contains$(Map.scala:281)
	at scala.collection.AbstractMap.contains(Map.scala:405)
	at scala.tools.nsc.typechecker.Macros$$anon$4.transform(Macros.scala:902)
	at scala.tools.nsc.typechecker.Macros.macroExpandAll(Macros.scala:917)
	at scala.tools.nsc.typechecker.Macros.macroExpandAll$(Macros.scala:898)
	at scala.tools.nsc.Global$$anon$6.macroExpandAll(Global.scala:485)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6058)
	at scala.tools.nsc.typechecker.Typers$Typer.typedArg(Typers.scala:3428)
	at scala.tools.nsc.typechecker.Typers$Typer.handlePolymorphicCall$1(Typers.scala:3827)
	at scala.tools.nsc.typechecker.Typers$Typer.doTypedApply(Typers.scala:3846)
	at scala.tools.nsc.typechecker.Typers$Typer.normalTypedApply$1(Typers.scala:5095)
	at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:5104)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5985)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6041)
	at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$adapt$1(Typers.scala:869)
	at scala.tools.nsc.typechecker.Typers$Typer.adaptToImplicitMethod$1(Typers.scala:488)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1274)
	at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:1271)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:873)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:810)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:629)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:1208)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:1245)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1302)
	at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1722)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit1(Implicits.scala:113)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit(Implicits.scala:92)
	at scala.tools.nsc.typechecker.Implicits.inferImplicit$(Implicits.scala:89)

@SethTisue
Copy link
Member

Looks like implicit search is looping. Perhaps -Vimplicits would produce some additional diagnostic output.

@pjfanning
Copy link
Author

@SethTisue -Vimplicits doesn't seem to lead to any additional output in this case

@pjfanning
Copy link
Author

I slightly simplified https://github.com/pjfanning/jackson-classtag-sample and now all the scala code is in the test project - it still depends on the Java jackson-databind jar.

@joroKr21
Copy link
Member

Minimization:

object Main extends App {
  trait JavaTypeable[T]
  object JavaTypeable {
    implicit def anyJavaTypeable: JavaTypeable[Any] = ???
    implicit def mapJavaTypeable[M[_,_] <: Map[_,_], K : JavaTypeable, V: JavaTypeable]: JavaTypeable[M[K, V]] = ???
    implicit def gen5JavaTypeable[T[_, _, _, _, _], A: JavaTypeable, B: JavaTypeable, C: JavaTypeable, D: JavaTypeable, E: JavaTypeable]: JavaTypeable[T[A, B, C, D, E]] = ???
    implicit def gen4JavaTypeable[T[_, _, _, _], A: JavaTypeable, B: JavaTypeable, C: JavaTypeable, D: JavaTypeable]: JavaTypeable[T[A, B, C, D]] = ???
    implicit def gen3JavaTypeable[T[_, _, _], A: JavaTypeable, B: JavaTypeable, C: JavaTypeable]: JavaTypeable[T[A, B, C]] = ???
    implicit def gen2JavaTypeable[T[_, _], A: JavaTypeable, B: JavaTypeable]: JavaTypeable[T[A, B]] = ???
    implicit def gen1JavaTypeable[T[_], A: JavaTypeable]: JavaTypeable[T[A]] = ???
    implicit def gen0JavaTypeable[T]: JavaTypeable[T] = ???
  }

  implicitly[JavaTypeable[Map[String, Any]]]
}

Add more arities (genNJavaTypeable) to make it (exponentially) slower, remove some arities to make it faster. I'm not sure if this qualifies as a bug or performance regression but either way code like this is detrimental to users 😕

@joroKr21
Copy link
Member

Workaround: reorder the implicits like this:

object Main extends App {
  trait JavaTypeable[T]
  object JavaTypeable {
    implicit def gen5JavaTypeable[T[_, _, _, _, _], A: JavaTypeable, B: JavaTypeable, C: JavaTypeable, D: JavaTypeable, E: JavaTypeable]: JavaTypeable[T[A, B, C, D, E]] = ???
    implicit def gen4JavaTypeable[T[_, _, _, _], A: JavaTypeable, B: JavaTypeable, C: JavaTypeable, D: JavaTypeable]: JavaTypeable[T[A, B, C, D]] = ???
    implicit def gen3JavaTypeable[T[_, _, _], A: JavaTypeable, B: JavaTypeable, C: JavaTypeable]: JavaTypeable[T[A, B, C]] = ???
    implicit def gen2JavaTypeable[T[_, _], A: JavaTypeable, B: JavaTypeable]: JavaTypeable[T[A, B]] = ???
    implicit def gen1JavaTypeable[T[_], A: JavaTypeable]: JavaTypeable[T[A]] = ???
    implicit def gen0JavaTypeable[T]: JavaTypeable[T] = ???
    implicit def mapJavaTypeable[M[_,_] <: Map[_,_], K : JavaTypeable, V: JavaTypeable]: JavaTypeable[M[K, V]] = ???
    implicit def anyJavaTypeable: JavaTypeable[Any] = ???
  }

  implicitly[JavaTypeable[Map[String, Any]]]
}

Note that the OP is extremely slow also on Scala 2.13.1 - if we think of a Scope as a linked list (aka stack) that we grow in definition order, then when we lookup the implicits toList we get them in reverse. There are just too many matching implicits with all the generics but if we happen to try the simpler ones first it's faster.

@joroKr21
Copy link
Member

Why it matter which implicit we try first is because we compute typedFirstPending which triggers a recursive implicit search which in this case fails and we discard later:
https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/nsc/typechecker/Implicits.scala#L1205-L1215

I don't know what's the purpose of typedFirstPending - is it an optimisation for code not like this?

@pjfanning
Copy link
Author

thanks @joroKr21, I committed a code reorder to jackson-module-scala and it makes a big difference

@joroKr21
Copy link
Member

Scala 3 doesn't have this problem so it's either smarter or dumber depending on your PoV

@joroKr21
Copy link
Member

I don't know what's the purpose of typedFirstPending - is it an optimisation for code not like this?

I couldn't trace it past paulp so I guess I'm not a good archaeologist.
But it looks central to the way implicits work in Scala 2.

@joroKr21
Copy link
Member

joroKr21 commented Jun 23, 2021

Scala 3 doesn't have this problem so it's either smarter or dumber depending on your PoV

I forgot about the new given rules for implicit resolution where definitions with less implicit parameters have higher priority which is exactly what we want in this case:

      /** A relation that influences the order in which eligible implicits are tried.
       *
       *  We prefer (in order of importance)
       *   1. more deeply nested definitions
       *   2. definitions with fewer implicit parameters
       *   3. definitions whose owner has more parents (see `compareBaseClassesLength`)
       *  The reason for (2) is that we want to fail fast if the search type
       *  is underconstrained. So we look for "small" goals first, because that
       *  will give an ambiguity quickly.
       */
      def compareEligibles(e1: Candidate, e2: Candidate): Int =

Maybe we could apply this in Scala 2 not as a semantic change but as an optimisation? WDYT?

@joroKr21
Copy link
Member

Maybe we could apply this in Scala 2 not as a semantic change but as an optimisation? WDYT?

Well I tried it with shapeless and it became slower, so it looks like it's not a definitive improvement ... and on the other hand having a deterministic order seems at least like a workable solution.

@lrytz
Copy link
Member

lrytz commented Jun 24, 2021

Thank you @joroKr21 for diving in!

rules for implicit resolution where definitions with less implicit parameters have higher priority

I could not find this in https://dotty.epfl.ch/docs/reference/changed-features/implicit-resolution.html? The comment on compareEligibles sounds like it only affects the order in which implicits are tried, not selection / semantics?

It sounds like something we could do, but as you say it might have a negative impact on code that has the implicits in a better order (by accident or maybe even deliberately).

I didn't make an attempt to understand why the order matters. Playing around with your example, the mapJavaTypeable implicit is not needed for the reproduction. Compiling with -Vimplicits -Vdebug shows an exponentially growing list of gen1JavaTypeable is not a valid implicit value for Main.this.JavaTypeable[A] because:... messages when uncommenting more of the arities.

Moving the anyJavaTypeable to the bottom there's none of those messages.

Maybe @smarter hears some bells ringing when reading through this discussion?

@joroKr21
Copy link
Member

I could not find this in dotty.epfl.ch/docs/reference/changed-features/implicit-resolution.html? The comment on compareEligibles sounds like it only affects the order in which implicits are tried, not selection / semantics?

Ah yes you are right, my bad. I remember at some point it was discussed making this a semantic change but now it's indeed only an optimisation whereas the semantic change is that normal overloading rules apply also wrt to given parameters not only the result type.

@joroKr21
Copy link
Member

I didn't make an attempt to understand why the order matters.

The order of definitions basically ends up in reverse as the eligible implicits in rankImplicits. There we try to typecheck the first one aka typedFirstPending (after applying some pruning implemented by @milessabin). That triggers another implicit search for its implicit parameters and so on. But if we happen to try a simpler candidate first we are done quicker.

Playing around with your example, the mapJavaTypeable implicit is not needed for the reproduction. Compiling with -Vimplicits -Vdebug shows an exponentially growing list of gen1JavaTypeable is not a valid implicit value for Main.this.JavaTypeable[A] because:... messages when uncommenting more of the arities.

Thanks for verifying, I didn't try it. I just fired up a debugger right away based on the provided stack traces. 👍

@smarter
Copy link
Member

smarter commented Jun 24, 2021

rules for implicit resolution where definitions with less implicit parameters have higher priority

I could not find this in dotty.epfl.ch/docs/reference/changed-features/implicit-resolution.html?

Point 7 on that page says:

An alternative A is more specific than an alternative B if [...] the relative weights are the same, and A takes no implicit parameters but B does

@SethTisue SethTisue added the fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/) label Sep 22, 2021
@dwijnand dwijnand added this to the Backlog milestone Sep 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler crash fixed in Scala 3 This issue does not exist in the Scala 3 compiler (https://github.com/lampepfl/dotty/)
Projects
None yet
Development

No branches or pull requests

6 participants