Closed sirthias closed 10 years ago
I can reproduce it (check the gist):
Parser.scala:
import org.parboiled2._
sealed trait Command
case class Connect(host: String, port: Int) extends Command
case object Disconnect extends Command
class CommandParser(val input: ParserInput) extends Parser {
def CommandLine = rule { WhiteSpace ~ Command ~ WhiteSpace ~ EOI }
def Command = rule { DisconnectCommand | ConnectCommand }
def ConnectCommand = rule { "connect" ~ (HostPort | Host) ~> Connect }
def Host: Rule2[String, Int] = rule { capture(oneOrMore(CharPredicate.AlphaNum)) ~ push(9300) }
def HostPort: Rule2[String, Int] = rule {
capture(oneOrMore(CharPredicate.AlphaNum)) ~ WhiteSpace ~ capture(oneOrMore(CharPredicate.Digit)) ~> ((port: String) ⇒ port.toInt)
}
def DisconnectCommand = rule { "disconnect" ~ push(Disconnect) }
def WhiteSpace = rule { zeroOrMore(' ') }
implicit def wspStr(s: String): Rule0 = rule {
str(s) ~ WhiteSpace
}
}
build.sbt:
libraryDependencies ++= Seq(
"org.parboiled" %% "parboiled" % "2.0.0"
//,"org.scala-lang" % "scala-reflect" % "2.11.1" // fixes it
)
scalaVersion := "2.11.1"
Full stacktrace:
scala.ScalaReflectionException: object scala.reflect.macros.blackbox.Context in compiler mirror not found.
at scala.reflect.internal.Mirrors$RootsBase.staticClass(Mirrors.scala:123)
at scala.reflect.internal.Mirrors$RootsBase.staticClass(Mirrors.scala:22)
at org.parboiled2.support.OpTreeContext$Action$$typecreator28$1.apply(OpTreeContext.scala:560)
at scala.reflect.api.TypeTags$WeakTypeTagImpl.tpe$lzycompute(TypeTags.scala:231)
at scala.reflect.api.TypeTags$WeakTypeTagImpl.tpe(TypeTags.scala:231)
at scala.reflect.api.TypeTags$class.typeOf(TypeTags.scala:335)
at scala.reflect.api.Universe.typeOf(Universe.scala:61)
at org.parboiled2.support.OpTreeContext$Action.rewrite$2(OpTreeContext.scala:560)
at org.parboiled2.support.OpTreeContext$Action.actionBody$2(OpTreeContext.scala:563)
at org.parboiled2.support.OpTreeContext$Action.renderInner(OpTreeContext.scala:566)
at org.parboiled2.support.OpTreeContext$OpTree.render(OpTreeContext.scala:42)
at org.parboiled2.support.OpTreeContext$Sequence$$anonfun$renderInner$1.apply(OpTreeContext.scala:117)
at org.parboiled2.support.OpTreeContext$Sequence$$anonfun$renderInner$1.apply(OpTreeContext.scala:117)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.immutable.List.foreach(List.scala:383)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.immutable.List.map(List.scala:286)
at org.parboiled2.support.OpTreeContext$Sequence.renderInner(OpTreeContext.scala:117)
at org.parboiled2.support.OpTreeContext$OpTree.render(OpTreeContext.scala:42)
at org.parboiled2.support.OpTreeContext$OpTree.renderRule(OpTreeContext.scala:33)
at org.parboiled2.ParserMacros$$treecreator1$1.apply(Parser.scala:482)
at scala.reflect.api.Exprs$ExprImpl.tree$lzycompute(Exprs.scala:145)
at scala.reflect.api.Exprs$ExprImpl.tree(Exprs.scala:145)
at scala.tools.nsc.typechecker.Macros$class.macroExpandWithRuntime(Macros.scala:779)
The line (OpTreeContext.scala:560) triggering it in parboiled2 is this:
case x if actionType.last <:< typeOf[Rule[_, _]] ⇒ expand(x, wrapped)
Any idea what could be going on, @xeno-by? Maybe typeOf[Rule]
is triggering loading of Context
because Rule
contains macro definitions itself? The question is if scala-reflect
then shouldn't be part of the mirror at macro expansion time.
Interestingly enough, it works if I compile the file using console invocation of scalac, adding parboiled and shapeless to the classpath.
The problem is in code that is generated in typeOf
for actionType.last <:< typeOf[Rule[_, _]]
. Inner workings of how existential types are represented in scalac lead to typeOf reifying more than necessary and accidentally creating a dependency on scala-reflect.
The fix would be to replace actionType.last <:< typeOf[Rule[_, _]]
with an equivalent that doesn't involve typeOf, e.g. actionType.last.baseClasses.contains(c.mirror.staticClass("org.parboiled2.Rule"))
.
Cool, thanks, Eugene! I'll give that a spin.
Thanks again, problem solved.
Thanks guys.
Adding a dependency onto
scala-reflect
makes the problem go away, but adding this dependency shouldn't be required.See this thread: https://groups.google.com/d/msg/parboiled-user/6351b1AQKCU/PKofnvtMTLYJ