Console fails when using Typelevel Scala with monocle-macro
julianmichael opened this issue · 6 comments
I'm porting a project over to Mill (using 0.1.7) from SBT and I'm having issues running the console
command, which is important for my project.
I've isolated the problem to the following build.sc
:
import mill._, mill.scalalib._
val thisScalaVersion = "2.11.8"
val monocleVersion = "1.4.0"
def typelevelScalaCompilerIvyDeps(scalaVersion: String) = Agg[Dep](
ivy"org.typelevel:scala-compiler:$scalaVersion",
ivy"org.typelevel:scala-reflect:$scalaVersion"
)
def typelevelScalaRuntimeIvyDeps(scalaVersion: String) = Agg[Dep](
ivy"org.typelevel:scala-library:$scalaVersion"
)
object foo extends ScalaModule {
def scalaVersion = thisScalaVersion
def scalaLibraryIvyDeps = T{ typelevelScalaRuntimeIvyDeps(scalaVersion()) }
def scalaCompilerClasspath: T[Agg[PathRef]] = T{
resolveDeps(
T.task{typelevelScalaCompilerIvyDeps(scalaVersion()) ++ typelevelScalaRuntimeIvyDeps(scalaVersion())}
)()
}
def ivyDeps = Agg(
ivy"com.github.julien-truffaut::monocle-macro::$monocleVersion"
)
}
When I run mill -i foo.console
, right when the scala console starts up, it spits out:
Failed to initialize compiler: NoSuchMethodError. This is most often remedied by a full clean and recompile.
Otherwise, your classpath may continue bytecode compiled by
different and incompatible versions of scala.
java.lang.NoSuchMethodError: scala.reflect.internal.Types$ConstantType$.apply(Lscala/reflect/internal/Constants$Constant;)Lscala/reflect/internal/Types$ConstantType; at scala.tools.nsc.symtab.classfile.ClassfileParser.scala$tools$nsc$symtab$classfile$ClassfileParser$$parseAttribute$1(ClassfileParser.scala:817) at scala.tools.nsc.symtab.classfile.ClassfileParser$$anonfun$parseAttributes$1.apply$mcVI$sp(ClassfileParser.scala:1017)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
...
with a long stack trace, followed by another error with the same message and another long stack trace.
If I remove the def ivyDeps = ...
statement or the Typelevel Scala specifications, it works fine. The compile
target works fine too, including in my actual project which has Scala sources that require the Typelevel compiler (whereas the console has the same error). I also tried changing the Scala version to 2.12.0
and again got the same error (though my project needs 2.11.8
at the moment).
Not sure exactly what's causing this—it seems to be a weird interaction between this dependency and Typelevel Scala. But the console worked fine in my SBT version of the build, and this issue is preventing me from porting over to Mill.
Ah actually I discovered another problem which shows that monocle-macro
isn't working properly. While compilation worked fine, when I tried to publishLocal
my project which made use of the macros, it failed, complaining about missing members (particularly the lenses which were supposed to be generated by the @Lenses
macro). So something is going wrong there.
If you want to use macro annotations such as
@Lenses
, you will also need to include:
addCompilerPlugin("org.scalamacros" %% "paradise" % "2.1.0" cross CrossVersion.full)
@julianmichael could you be missing this?
@lihaoyi It fails with that as well. I did
def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ Agg(
ivy"org.scalamacros:::paradise:2.1.0"
)
I happened to remove it while making the example "minimal," but yeah should have left it in there. The failure is the same.
It could be something with cross CrossVersion.full
though, maybe? I can't quite tell from the SBT documentation how to emulate what it does in Mill.
Seems the problem is that while you subbed out scalaCompilerClasspath
& friends, other ivy deps are still pulling in the scala-lang
compiler & library transitively
lihaoyi typelevel$ mill -i show foo.ivyDepsTree
[1/1] show
[4/4] foo.ivyDepsTree
└─ com.github.julien-truffaut:monocle-macro_2.11:1.4.0
├─ com.github.julien-truffaut:monocle-core_2.11:1.4.0
│ ├─ org.scala-lang:scala-library:2.11.8
│ ├─ org.scala-lang.modules:scala-java8-compat_2.11:0.7.0
│ │ └─ org.scala-lang:scala-library:2.11.7 -> 2.11.8
│ └─ org.scalaz:scalaz-core_2.11:7.2.8
│ └─ org.scala-lang:scala-library:2.11.8
├─ org.scala-lang:scala-library:2.11.8
├─ org.scala-lang:scala-reflect:2.11.8
│ └─ org.scala-lang:scala-library:2.11.8
└─ org.typelevel:macro-compat_2.11:1.1.1
└─ org.scala-lang:scala-library:2.11.7 -> 2.11.8
Not sure what the story around exclusions is for coursier, but I'm sure there's a way to force-exclude those
This should be fixed in master, but you'll need to use a newly provided API to enable org.typelevel
rather than what you're doing now:
object foo extends ScalaModule {
def scalaVersion = "2.11.8"
override def mapDependencies(d: coursier.Dependency) = {
val artifacts = Set("scala-library", "scala-compiler", "scala-reflect")
if (d.module.organization != "org.scala-lang" || !artifacts(d.module.name)) d
else d.copy(module = d.module.copy(organization = "org.typelevel"))
}
def ivyDeps = Agg(
ivy"com.github.julien-truffaut::monocle-macro::1.4.0"
)
def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ Agg(
ivy"org.scalamacros:::paradise:2.1.0"
)
}