sbt / zinc

Scala incremental compiler library, used by sbt and other build tools
Apache License 2.0
336 stars 121 forks source link

Changing abstract class to trait causes "invalid superClass" #598

Open pauldraper opened 6 years ago

pauldraper commented 6 years ago

Using sbt 1.2.3, Scala 2.12.6

git clone git@github.com:typelevel/cats.git
cd cats
sbt compile
sed -i 's/abstract class StateTFunctions/trait StateTFunctions/' core/src/main/scala/cats/data/IndexedStateT.scala
sbt compile
[info] Compiling 1 Scala source to /home/paul/dev/typelevel/cats/core/.jvm/target/scala-2.12/classes ...
java.lang.AssertionError: assertion failed: Invalid superClass in Lcats/data/package$StateT$;: Some(Lcats/data/StateTFunctions;)
    at scala.tools.nsc.backend.jvm.BTypes$ClassBType.scala$tools$nsc$backend$jvm$BTypes$ClassBType$$checkInfoConsistency(BTypes.scala:649)
    at scala.tools.nsc.backend.jvm.BTypes$ClassBType$.apply(BTypes.scala:817)
    at scala.tools.nsc.backend.jvm.BTypesFromSymbols.classBTypeFromSymbol(BTypesFromSymbols.scala:104)
    at scala.tools.nsc.backend.jvm.BTypesFromSymbols.$anonfun$typeToBType$1(BTypesFromSymbols.scala:158)
    at scala.collection.MapLike.getOrElse(MapLike.scala:128)
    at scala.collection.MapLike.getOrElse$(MapLike.scala:126)
    at scala.collection.AbstractMap.getOrElse(Map.scala:59)
    at scala.tools.nsc.backend.jvm.BTypesFromSymbols.primitiveOrClassToBType$1(BTypesFromSymbols.scala:158)
    at scala.tools.nsc.backend.jvm.BTypesFromSymbols.typeToBType(BTypesFromSymbols.scala:173)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.tpeTK(BCodeSkelBuilder.scala:80)
    at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:249)
    at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoadQualifier(BCodeBodyBuilder.scala:900)
    at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genApply(BCodeBodyBuilder.scala:664)
    at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.genLoad(BCodeBodyBuilder.scala:296)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.emitNormalMethodBody$1(BCodeSkelBuilder.scala:602)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.genDefDef(BCodeSkelBuilder.scala:634)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.gen(BCodeSkelBuilder.scala:508)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.$anonfun$gen$7(BCodeSkelBuilder.scala:510)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.gen(BCodeSkelBuilder.scala:510)
    at scala.tools.nsc.backend.jvm.BCodeSkelBuilder$PlainSkelBuilder.genPlainClass(BCodeSkelBuilder.scala:110)
    at scala.tools.nsc.backend.jvm.CodeGen.genClass(CodeGen.scala:69)
    at scala.tools.nsc.backend.jvm.CodeGen.genClassDef$1(CodeGen.scala:31)
    at scala.tools.nsc.backend.jvm.CodeGen.$anonfun$genUnit$3(CodeGen.scala:54)
    at scala.tools.nsc.backend.jvm.CodeGen.genClassDefs$1(CodeGen.scala:54)
    at scala.tools.nsc.backend.jvm.CodeGen.$anonfun$genUnit$2(CodeGen.scala:53)
    at scala.tools.nsc.backend.jvm.CodeGen.genClassDefs$1(CodeGen.scala:53)
    at scala.tools.nsc.backend.jvm.CodeGen.$anonfun$genUnit$2(CodeGen.scala:53)
    at scala.tools.nsc.backend.jvm.CodeGen.genClassDefs$1(CodeGen.scala:53)
    at scala.tools.nsc.backend.jvm.CodeGen.$anonfun$genUnit$4(CodeGen.scala:58)
    at scala.tools.nsc.backend.jvm.CodeGen.genUnit(CodeGen.scala:58)
    at scala.tools.nsc.backend.jvm.GenBCode$BCodePhase.apply(GenBCode.scala:67)
    at scala.tools.nsc.Global$GlobalPhase.$anonfun$applyPhase$1(Global.scala:426)
    at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:419)
    at scala.tools.nsc.Global$GlobalPhase.$anonfun$run$1(Global.scala:390)
    at scala.tools.nsc.Global$GlobalPhase.$anonfun$run$1$adapted(Global.scala:390)
    at scala.collection.Iterator.foreach(Iterator.scala:944)
    at scala.collection.Iterator.foreach$(Iterator.scala:944)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1432)
    at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:390)
    at scala.tools.nsc.backend.jvm.GenBCode$BCodePhase.super$run(GenBCode.scala:73)
    at scala.tools.nsc.backend.jvm.GenBCode$BCodePhase.$anonfun$run$1(GenBCode.scala:73)
    at scala.tools.nsc.backend.jvm.GenBCode$BCodePhase.run(GenBCode.scala:71)
    at scala.tools.nsc.Global$Run.compileUnitsInternal(Global.scala:1446)
    at scala.tools.nsc.Global$Run.compileUnits(Global.scala:1430)
    at scala.tools.nsc.Global$Run.compileSources(Global.scala:1423)
    at scala.tools.nsc.Global$Run.compile(Global.scala:1539)
    at xsbt.CachedCompiler0.run(CompilerInterface.scala:130)
    at xsbt.CachedCompiler0.run(CompilerInterface.scala:105)
    at xsbt.CompilerInterface.run(CompilerInterface.scala:31)
    at sun.reflect.GeneratedMethodAccessor25.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sbt.internal.inc.AnalyzingCompiler.call(AnalyzingCompiler.scala:237)
    at sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:111)
    at sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:90)
    at sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$3(MixedAnalyzingCompiler.scala:82)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
    at sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:133)
    at sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:73)
    at sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:116)
    at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:307)
    at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:307)
    at sbt.internal.inc.Incremental$.doCompile(Incremental.scala:106)
    at sbt.internal.inc.Incremental$.$anonfun$compile$4(Incremental.scala:87)
    at sbt.internal.inc.IncrementalCommon.recompileClasses(IncrementalCommon.scala:116)
    at sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:63)
    at sbt.internal.inc.Incremental$.$anonfun$compile$3(Incremental.scala:89)
    at sbt.internal.inc.Incremental$.manageClassfiles(Incremental.scala:134)
    at sbt.internal.inc.Incremental$.compile(Incremental.scala:80)
    at sbt.internal.inc.IncrementalCompile$.apply(Compile.scala:67)
    at sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:311)
    at sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:269)
    at sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:159)
    at sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:238)
    at sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:69)
    at sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:1544)
    at sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:1518)
    at scala.Function1.$anonfun$compose$1(Function1.scala:44)
    at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
    at sbt.std.Transform$$anon$4.work(System.scala:67)
    at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
    at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
    at sbt.Execute.work(Execute.scala:278)
    at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
    at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
    at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
    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)
[error] Error while emitting IndexedStateT.scala
[error] assertion failed: Invalid superClass in Lcats/data/package$StateT$;: Some(Lcats/data/StateTFunctions;)

A clean fixes the compilation.

jvican commented 6 years ago

Can you reproduce in a scripted test and submit a PR with the test marked as pending?

jvican commented 6 years ago

@adriaanm @lrytz This looks like a compiler bug in genbcode. I cannot not reproduce the issue, but Zinc is not at fault here since the error happens in the first compilation of the modified sources (not in subsequent versions where the zinc analysis is performed). Do you have any idea of what could be going on here? Looks related to the handling of package objects.

smarter commented 5 years ago

but Zinc is not at fault here since the error happens in the first compilation of the modified sources

Zinc is assuming that compiling the modified sources by themselves should always work, but it looks like this assumption is broken when files refer to each other, I've created a repo to illustrate this and reproduce the bug: https://github.com/smarter/trait-class-bug/commits/master

Because Zinc knows that A.scala refers to symbols in B.scala, and B.scala refers to symbols in A.scala, it should never attempt to compile one of those without the other, even for the first compilation of modified sources.