diff options
author | Paul Phillips <paulp@improving.org> | 2012-04-25 06:43:45 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-04-25 06:43:45 -0700 |
commit | edc7071d3b284fcf82bd17c7a1cf83f23e32788f (patch) | |
tree | 848344b1cfca8015a125723960691b60732ba30e | |
parent | bf621aa912ec76ba5794280b88f62d0861aa530d (diff) | |
download | scala-edc7071d3b284fcf82bd17c7a1cf83f23e32788f.tar.gz scala-edc7071d3b284fcf82bd17c7a1cf83f23e32788f.tar.bz2 scala-edc7071d3b284fcf82bd17c7a1cf83f23e32788f.zip |
Fix reifier crashing repl.
Very first time I tried "reify" in the repl and it crashed.
I changed an assert to issue a proper error, as best I could
figure out how. We probably need to do a lot more of this.
4 files changed, 54 insertions, 16 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index c13be0e39d..2d1369b11d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -343,6 +343,11 @@ trait ContextErrors { issueNormalTypeError(tree, "macros cannot be eta-expanded") setError(tree) } + + def MacroPartialApplicationError(tree: Tree) = { + issueNormalTypeError(tree, "macros cannot be partially applied") + setError(tree) + } //typedReturn def ReturnOutsideOfDefError(tree: Tree) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 5d4cd0be77..4d35549773 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -855,7 +855,7 @@ trait Macros { self: Analyzer => val numParamLists = paramss_without_evidences.length val numArgLists = argss.length if (numParamLists != numArgLists) { - typer.context.error(expandee.pos, "macros cannot be partially applied") + typer.TyperErrorGen.MacroPartialApplicationError(expandee) return None } @@ -953,6 +953,11 @@ trait Macros { self: Analyzer => * the expandee with an error marker set if there has been an error */ def macroExpand(typer: Typer, expandee: Tree, mode: Int = EXPRmode, pt: Type = WildcardType): Tree = { + def fail(what: String, tree: Tree): Tree = { + val err = typer.context.errBuffer.head + this.fail(typer, tree, "failed to perform %s: %s at %s".format(what, err.errMsg, err.errPos)) + return expandee + } val start = startTimer(macroExpandNanos) incCounter(macroExpandCount) try { @@ -979,15 +984,9 @@ trait Macros { self: Analyzer => case _ => ; } - def fail(what: String): Tree = { - val err = typer.context.errBuffer.head - this.fail(typer, expanded, "failed to perform %s: %s at %s".format(what, err.errMsg, err.errPos)) - return expandee - } - if (macroDebug) println("typechecking1 against %s: %s".format(expectedTpe, expanded)) var typechecked = typer.context.withImplicitsEnabled(typer.typed(expanded, EXPRmode, expectedTpe)) - if (typer.context.hasErrors) fail("typecheck1") + if (typer.context.hasErrors) fail("typecheck1", expanded) if (macroDebug) { println("typechecked1:") println(typechecked) @@ -996,7 +995,7 @@ trait Macros { self: Analyzer => if (macroDebug) println("typechecking2 against %s: %s".format(pt, expanded)) typechecked = typer.context.withImplicitsEnabled(typer.typed(typechecked, EXPRmode, pt)) - if (typer.context.hasErrors) fail("typecheck2") + if (typer.context.hasErrors) fail("typecheck2", expanded) if (macroDebug) { println("typechecked2:") println(typechecked) @@ -1009,13 +1008,16 @@ trait Macros { self: Analyzer => } case Delay(expandee) => // need to save the context to preserve enclosures - val args = macroArgs(typer, expandee) - assert(args.isDefined, expandee) - val context = args.get.head.asInstanceOf[MacroContext] - var result = expandee withAttachment MacroAttachment(delayed = true, context = Some(context)) - // adapting here would be premature, we must wait until undetparams are inferred -// result = typer.adapt(result, mode, pt) - result + macroArgs(typer, expandee) match { + case Some((context: MacroContext) :: _) => + // adapting here would be premature, we must wait until undetparams are inferred + expandee withAttachment MacroAttachment(delayed = true, context = Some(context)) + case _ => + // !!! The correct place to issue an error needs to be clarified. + // I have the else condition here only as a fallback. + if (expandee.isErroneous) expandee + else fail("macros cannot be partially applied", expandee) + } case Fallback(fallback) => typer.context.withImplicitsEnabled(typer.typed(fallback, EXPRmode, pt)) case Other(result) => diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check new file mode 100644 index 0000000000..680db12667 --- /dev/null +++ b/test/files/run/reify-repl-fail-gracefully.check @@ -0,0 +1,21 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> import language.experimental.macros +import language.experimental.macros + +scala> import scala.reflect.mirror._ +import scala.reflect.mirror._ + +scala> + +scala> reify +<console>:12: error: macros cannot be partially applied + reify + ^ + +scala> + +scala> diff --git a/test/files/run/reify-repl-fail-gracefully.scala b/test/files/run/reify-repl-fail-gracefully.scala new file mode 100644 index 0000000000..d7a06e8da8 --- /dev/null +++ b/test/files/run/reify-repl-fail-gracefully.scala @@ -0,0 +1,10 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ + |import language.experimental.macros + |import scala.reflect.mirror._ + | + |reify + """.stripMargin +} |