diff options
7 files changed, 58 insertions, 20 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 6cb935edad..2b6607e23e 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -493,8 +493,8 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val NoManifest = getRequiredModule("scala.reflect.NoManifest") lazy val ExprClass = getMember(getRequiredClass("scala.reflect.api.Exprs"), tpnme.Expr) - def ExprTree = getMemberClass(ExprClass, nme.tree) - def ExprTpe = getMemberClass(ExprClass, nme.tpe) + def ExprTree = getMember(ExprClass, nme.tree) + def ExprTpe = getMember(ExprClass, nme.tpe) def ExprEval = getMember(ExprClass, nme.eval) def ExprValue = getMember(ExprClass, nme.value) lazy val ExprModule = getMember(getRequiredClass("scala.reflect.api.Exprs"), nme.Expr) diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index 48dfe8bcfc..f4878139e9 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -602,7 +602,7 @@ abstract class TreeInfo { object ReifiedTree { def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match { - case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(Apply(_, List(tree)), List(Apply(_, List(tpe))))) if mrDef.name == nme.MIRROR_SHORT => + case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(Apply(_, List(tree)), List(Apply(_, tpe :: _)))) if mrDef.name == nme.MIRROR_SHORT => Some(reifee, symbolTable, tree, tpe) case _ => None 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 4e4c52e0f7..ef9bae700e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -856,7 +856,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 } @@ -954,6 +954,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 { @@ -980,15 +985,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) @@ -997,7 +996,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) @@ -1010,13 +1009,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/src/library/scala/reflect/makro/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala index ae6669946c..b1de8d9957 100644 --- a/src/library/scala/reflect/makro/Reifiers.scala +++ b/src/library/scala/reflect/makro/Reifiers.scala @@ -74,4 +74,4 @@ trait Reifiers { case class ReificationError(var pos: reflect.api.Position, val msg: String) extends Throwable(msg) -case class UnexpectedReificationError(val pos: reflect.api.Position, val msg: String, val cause: Throwable = null) extends Throwable(msg)
\ No newline at end of file +case class UnexpectedReificationError(val pos: reflect.api.Position, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause)
\ No newline at end of file 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 +} |