diff options
26 files changed, 384 insertions, 119 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 2043eb5d5d..40b97394f2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -501,10 +501,6 @@ trait ContextErrors { } // doTypeApply - //tryNamesDefaults - def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) = - NormalTypeError(tree, "macro applications do not support named and/or default arguments") - def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) = NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun)) @@ -603,12 +599,11 @@ trait ContextErrors { //adapt def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = { + val errorExplanation = "missing arguments for " + meth.fullLocationString + val suggestPartialApplication = ";\nfollow this method with `_' if you want to treat it as a partially applied function" val message = - if (meth.isMacro) MacroTooFewArgumentListsMessage - else "missing arguments for " + meth.fullLocationString + ( - if (meth.isConstructor) "" - else ";\nfollow this method with `_' if you want to treat it as a partially applied function" - ) + if (meth.isMacro || meth.isConstructor) errorExplanation + else errorExplanation + suggestPartialApplication issueNormalTypeError(tree, message) setError(tree) } @@ -748,15 +743,12 @@ trait ContextErrors { throw MacroExpansionException } - private def MacroTooFewArgumentListsMessage = "too few argument lists for macro invocation" - def MacroTooFewArgumentListsError(expandee: Tree) = macroExpansionError2(expandee, MacroTooFewArgumentListsMessage) - - private def MacroTooManyArgumentListsMessage = "too many argument lists for macro invocation" - def MacroTooManyArgumentListsError(expandee: Tree) = macroExpansionError2(expandee, MacroTooManyArgumentListsMessage) - - def MacroTooFewArgumentsError(expandee: Tree) = macroExpansionError2(expandee, "too few arguments for macro invocation") - - def MacroTooManyArgumentsError(expandee: Tree) = macroExpansionError2(expandee, "too many arguments for macro invocation") + def MacroFastTrackFailed(expandee: Tree) = { + // here we speculate that the reason why FastTrackEntry.validate failed is the lack arguments for a given method + // that's not ideal, but on the other hand this allows us to keep FastTrack simple without hooking errorgen into it + MissingArgsForMethodTpeError(expandee, expandee.symbol) + throw MacroExpansionException + } def MacroGeneratedAbort(expandee: Tree, ex: AbortMacroException) = { // errors have been reported by the macro itself, so we do nothing here diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index cf82d6baac..29b3ec7f3e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -353,7 +353,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { new { val universe: self.global.type = self.global val callsiteTyper: universe.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer] - val expandee = universe.analyzer.macroExpanderAttachment(expandeeTree).original orElse duplicateAndKeepPositions(expandeeTree) + val expandee = universe.analyzer.macroExpanderAttachment(expandeeTree).desugared orElse duplicateAndKeepPositions(expandeeTree) } with UnaffiliatedMacroContext { val prefix = Expr[Nothing](prefixTree)(TypeTag.Nothing) override def toString = "MacroContext(%s@%s +%d)".format(expandee.symbol.name, expandee.pos, enclosingMacros.length - 1 /* exclude myself */) @@ -371,7 +371,15 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { def standardMacroArgs(typer: Typer, expandee: Tree): MacroArgs = { val macroDef = expandee.symbol val paramss = macroDef.paramss - val treeInfo.Applied(core, targs, argss) = expandee + val treeInfo.Applied(core, targs, maybeNamedArgss) = expandee + val argss = map2(maybeNamedArgss, paramss)((args, params) => { + if (args.exists(_.isInstanceOf[AssignOrNamedArg])) { + val sorted = ListBuffer.fill(params.length)(EmptyTree: Tree) + args foreach { case AssignOrNamedArg(Ident(name), arg) => sorted(params.indexWhere(_.name == name)) = arg } + sorted.toList + } else if (params.length == args.length) args + else args ++ List.fill(params.length - args.length)(EmptyTree) + }) val prefix = core match { case Select(qual, _) => qual; case _ => EmptyTree } val context = expandee.attachments.get[MacroRuntimeAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefix, expandee)) @@ -383,16 +391,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { |paramss: $paramss """.trim) - import typer.TyperErrorGen._ - val isNullaryArgsEmptyParams = argss.isEmpty && paramss == ListOfNil - if (paramss.length < argss.length) MacroTooManyArgumentListsError(expandee) - if (paramss.length > argss.length && !isNullaryArgsEmptyParams) MacroTooFewArgumentListsError(expandee) - val macroImplArgs: List[Any] = if (fastTrack contains macroDef) { // Take a dry run of the fast track implementation if (fastTrack(macroDef) validate expandee) argss.flatten - else MacroTooFewArgumentListsError(expandee) + else typer.TyperErrorGen.MacroFastTrackFailed(expandee) } else { def calculateMacroArgs(binding: MacroImplBinding) = { @@ -403,14 +406,6 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { // wrap argss in c.Expr if necessary (i.e. if corresponding macro impl param is of type c.Expr[T]) // expand varargs (nb! varargs can apply to any parameter section, not necessarily to the last one) val trees = map3(argss, paramss, signature)((args, defParams, implParams) => { - val isVarargs = isVarArgsList(defParams) - if (isVarargs) { - if (defParams.length > args.length + 1) MacroTooFewArgumentsError(expandee) - } else { - if (defParams.length < args.length) MacroTooManyArgumentsError(expandee) - if (defParams.length > args.length) MacroTooFewArgumentsError(expandee) - } - val wrappedArgs = mapWithIndex(args)((arg, j) => { val fingerprint = implParams(min(j, implParams.length - 1)) fingerprint match { @@ -421,7 +416,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { } }) - if (isVarargs) { + if (isVarArgsList(defParams)) { val (normal, varargs) = wrappedArgs splitAt (defParams.length - 1) normal :+ varargs // pack all varargs into a single Seq argument (varargs Scala style) } else wrappedArgs @@ -529,9 +524,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * the expandee with an error marker set if there has been an error */ abstract class MacroExpander(val typer: Typer, val expandee: Tree) { + val symbol = expandee match { case Block(_, expr) => expr.symbol; case tree => tree.symbol } + def onSuccess(expanded: Tree): Tree def onFallback(expanded: Tree): Tree - def onSuppressed(expandee: Tree): Tree = expandee + def onSuppressed(expanded: Tree): Tree = expanded def onDelayed(expanded: Tree): Tree = expanded def onSkipped(expanded: Tree): Tree = expanded def onFailure(expanded: Tree): Tree = { typer.infer.setError(expandee); expandee } @@ -551,15 +548,15 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { if (Statistics.canEnable) Statistics.incCounter(macroExpandCount) try { withInfoLevel(nodePrinters.InfoLevel.Quiet) { // verbose printing might cause recursive macro expansions - if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) { - val reason = if (expandee.symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments" + if (symbol.isErroneous || (expandee exists (_.isErroneous)) || (desugared exists (_.isErroneous))) { + val reason = if (symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments" macroLogVerbose(s"cancelled macro expansion because of $reason: $expandee") onFailure(typer.infer.setError(expandee)) } else try { val expanded = { - val runtime = macroRuntime(expandee) - if (runtime != null) macroExpandWithRuntime(typer, expandee, runtime) - else macroExpandWithoutRuntime(typer, expandee) + val runtime = macroRuntime(desugared) + if (runtime != null) macroExpandWithRuntime(typer, desugared, runtime) + else macroExpandWithoutRuntime(typer, desugared) } expanded match { case Success(expanded) => @@ -591,7 +588,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { extends MacroExpander(typer, expandee) { lazy val innerPt = { val tp = if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe - if (isBlackbox(expandee)) tp + if (isBlackbox(symbol)) tp else { // approximation is necessary for whitebox macros to guide type inference // read more in the comments for onDelayed below @@ -599,6 +596,50 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { deriveTypeWithWildcards(undetparams)(tp) } } + override protected def expand(desugared: Tree) = { + // SI-5940 in order for a macro expansion that involves named or default arguments + // to see the actual prefix and arguments being passed by the user instead of their desugarings + // we need to inline synthetics in case when `fun` is actually a macro + // underlying macro implementation is going to get explicitly passed arguments in correct order + // and the rest (defaults filled in by the vanilla part of `tryNamesDefaults`) will become empty trees + // in order for the macro to be able to account for evaluation order, the original is provided in `c.macroApplication` + // of course, ideally we would like to provide the impl with right-hand sides of those default arguments + // but currently that is flat out impossible because of the difference in scopes + // anyway this is already an improvement over the former status quo when named/default invocations were outright prohibited + def undoNamesDefaults(tree: Tree): Tree = { + val (qualsym, qual, vdefs0, app @ Applied(_, _, argss)) = tree match { + case Block((qualdef @ ValDef(_, name, _, qual)) +: vdefs, app) if name.startsWith(nme.QUAL_PREFIX) => (qualdef.symbol, qual, vdefs, app) + case Block(vdefs, app) => (NoSymbol, EmptyTree, vdefs, app) + case tree => (NoSymbol, EmptyTree, Nil, tree) + } + val vdefs = vdefs0.map{ case vdef: ValDef => vdef } + def hasNamesDefaults(args: List[Tree]) = { + args.exists(arg => isDefaultGetter(arg) || vdefs.exists(_.symbol == arg.symbol)) + } + def undoNamesDefaults(args: List[Tree], depth: Int) = { + def extractRhs(vdef: ValDef) = vdef.rhs.changeOwner(vdef.symbol -> typer.context.owner) + case class Arg(tree: Tree, ipos: Int, inamed: Int) { val param = app.symbol.paramss(depth)(ipos) } + val indexed = args.map(arg => arg -> vdefs.indexWhere(_.symbol == arg.symbol)).zipWithIndex.flatMap({ + /* default */ case ((arg, _), _) if isDefaultGetter(arg) => None + /* positional */ case ((arg, -1), ipos) => Some(Arg(arg, ipos, -1)) + /* default+named */ case ((_, inamed), _) if isDefaultGetter(extractRhs(vdefs(inamed))) => None + /* named */ case ((arg, inamed), ipos) => Some(Arg(extractRhs(vdefs(inamed)), ipos, inamed)) + }) + if (indexed.forall(_.inamed == -1)) indexed.map(_.tree) + else indexed.sortBy(_.inamed).map(arg => AssignOrNamedArg(Ident(arg.param.name), arg.tree)) + } + def loop(tree: Tree, depth: Int): Tree = tree match { + case Apply(fun, args) if hasNamesDefaults(args) => treeCopy.Apply(tree, loop(fun, depth - 1), undoNamesDefaults(args, depth)) + case Apply(fun, args) => treeCopy.Apply(tree, loop(fun, depth - 1), args) + case TypeApply(core, targs) => treeCopy.TypeApply(tree, core, targs) + case Select(core, name) if qualsym != NoSymbol && core.symbol == qualsym => treeCopy.Select(tree, qual, name) + case core => core + } + if (app.symbol == null || app.symbol == NoSymbol || app.exists(_.isErroneous)) tree + else loop(app, depth = argss.length - 1) + } + super.expand(undoNamesDefaults(desugared)) + } override def onSuccess(expanded0: Tree) = { // prematurely annotate the tree with a macro expansion attachment // so that adapt called indirectly by typer.typed knows that it needs to apply the existential fixup @@ -616,7 +657,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { } } - if (isBlackbox(expandee)) { + if (isBlackbox(symbol)) { val expanded1 = atPos(enclosingMacroPosition.makeTransparent)(Typed(expanded0, TypeTree(innerPt))) typecheck("blackbox typecheck", expanded1, outerPt) } else { @@ -676,7 +717,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { // Thanks to that the materializer can take a look at what's going on and react accordingly. val shouldInstantiate = typer.context.undetparams.nonEmpty && !mode.inPolyMode if (shouldInstantiate) { - if (isBlackbox(expandee)) typer.instantiatePossiblyExpectingUnit(delayed, mode, outerPt) + if (isBlackbox(symbol)) typer.instantiatePossiblyExpectingUnit(delayed, mode, outerPt) else { forced += delayed typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), outerPt, keepNothings = false) diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 57f27a05fd..1a6d2f0011 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -85,6 +85,7 @@ trait StdAttachments { tree match { // see the comment to `isMacroExpansionSuppressed` to learn why we need // a special traversal strategy here + case Block(_, expr) => unsuppressMacroExpansion(expr) case Apply(fn, _) => unsuppressMacroExpansion(fn) case TypeApply(fn, _) => unsuppressMacroExpansion(fn) case _ => // do nothing @@ -101,6 +102,8 @@ trait StdAttachments { // we have to account for the fact that during typechecking an expandee might become wrapped, // i.e. surrounded by an inferred implicit argument application or by an inferred type argument application. // in that case the expandee itself will no longer be suppressed and we need to look at the core + // upd. we also need to allow for blocks, because that's what names and defaults are often desugared to + case Block(_, expr) => isMacroExpansionSuppressed(expr) case Apply(fn, _) => isMacroExpansionSuppressed(fn) case TypeApply(fn, _) => isMacroExpansionSuppressed(fn) case _ => false diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 10fe530445..020d26c712 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1155,7 +1155,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case mt: MethodType if mode.typingExprNotFunNotLhs && mt.isImplicit => // (4.1) adaptToImplicitMethod(mt) - case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode && !treeInfo.isMacroApplicationOrBlock(tree) => + case mt: MethodType if mode.typingExprNotFunNotLhs && !hasUndetsInMonoMode => instantiateToMethodType(mt) case _ => vanillaAdapt(tree) @@ -3292,12 +3292,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper */ def tryNamesDefaults: Tree = { val lencmp = compareLengths(args, formals) - - def checkNotMacro() = { - if (treeInfo.isMacroApplication(fun)) - tryTupleApply orElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) - } - if (mt.isErroneous) duplErrTree else if (mode.inPatternMode) { // #2064 @@ -3316,18 +3310,15 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper else if (allArgsArePositional(argPos) && !isNamedApplyBlock(fun)) { // if there's no re-ordering, and fun is not transformed, no need to transform // more than an optimization, e.g. important in "synchronized { x = update-x }" - checkNotMacro() doTypedApply(tree, fun, namelessArgs, mode, pt) } else { - checkNotMacro() - transformNamedApplication(Typer.this, mode, pt)( - treeCopy.Apply(tree, fun, namelessArgs), argPos) + unsuppressMacroExpansion(transformNamedApplication(Typer.this, mode, pt)( + treeCopy.Apply(tree, suppressMacroExpansion(fun), namelessArgs), argPos)) } } else { // defaults are needed. they are added to the argument list in named style as // calls to the default getters. Example: // foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a)) - checkNotMacro() // SI-8111 transformNamedApplication eagerly shuffles around the application to preserve // evaluation order. During this process, it calls `changeOwner` on symbols that @@ -3350,7 +3341,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper symsOwnedByContextOwner foreach (_.owner = context.owner) } - val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x) + val fun1 = transformNamedApplication(Typer.this, mode, pt)(suppressMacroExpansion(fun), x => x) if (fun1.isErroneous) duplErrTree else { assert(isNamedApplyBlock(fun1), fun1) @@ -3376,7 +3367,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]() val note = "Error occurred in an application involving default arguments." if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic - doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) + unsuppressMacroExpansion(doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)) } else { rollbackNamesDefaultsOwnerChanges() tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 1eb0743bc8..7ff482d021 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -852,13 +852,8 @@ abstract class TreeInfo { case _ => false }) - def isMacroApplication(tree: Tree): Boolean = !tree.isDef && { - val sym = tree.symbol - sym != null && sym.isTermMacro && !sym.isErroneous - } - - def isMacroApplicationOrBlock(tree: Tree): Boolean = tree match { - case Block(_, expr) => isMacroApplicationOrBlock(expr) - case tree => isMacroApplication(tree) + def isMacroApplication(tree: Tree): Boolean = tree match { + case Block(_, expr) => isMacroApplication(expr) + case tree => !tree.isDef && tree.symbol != null && tree.symbol.isTermMacro && !tree.symbol.isErroneous } } diff --git a/test/files/neg/macro-argc-mismatch.check b/test/files/neg/macro-argc-mismatch.check new file mode 100644 index 0000000000..617daa890c --- /dev/null +++ b/test/files/neg/macro-argc-mismatch.check @@ -0,0 +1,49 @@ +Test_2.scala:4: error: missing arguments for macro method one in object Macros + one + ^ +Test_2.scala:5: error: not enough arguments for macro method one: (x: Int)Unit. +Unspecified value parameter x. + one() + ^ +Test_2.scala:6: error: too many arguments for macro method one: (x: Int)Unit + one(2, 3) + ^ +Test_2.scala:7: error: not enough arguments for macro method one: (x: Int)Unit. +Unspecified value parameter x. + one()() + ^ +Test_2.scala:8: error: Unit does not take parameters + one(1)() + ^ +Test_2.scala:10: error: missing arguments for macro method two in object Macros + two + ^ +Test_2.scala:11: error: not enough arguments for macro method two: (x: Int)(y: Int)Unit. +Unspecified value parameter x. + two() + ^ +Test_2.scala:12: error: too many arguments for macro method two: (x: Int)(y: Int)Unit + two(2, 3) + ^ +Test_2.scala:13: error: not enough arguments for macro method two: (x: Int)(y: Int)Unit. +Unspecified value parameter x. + two()() + ^ +Test_2.scala:14: error: missing arguments for macro method two in object Macros + two(1) + ^ +Test_2.scala:15: error: not enough arguments for macro method two: (y: Int)Unit. +Unspecified value parameter y. + two(1)() + ^ +Test_2.scala:16: error: too many arguments for macro method two: (y: Int)Unit + two(1)(2, 3) + ^ +Test_2.scala:17: error: not enough arguments for macro method two: (y: Int)Unit. +Unspecified value parameter y. + two(1)()() + ^ +Test_2.scala:18: error: Unit does not take parameters + two(1)(1)() + ^ +14 errors found diff --git a/test/files/neg/macro-argc-mismatch/Macros_1.scala b/test/files/neg/macro-argc-mismatch/Macros_1.scala new file mode 100644 index 0000000000..4dca644172 --- /dev/null +++ b/test/files/neg/macro-argc-mismatch/Macros_1.scala @@ -0,0 +1,16 @@ +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + +object Macros { + def one(x: Int): Unit = macro oneImpl + def oneImpl(c: Context)(x: c.Tree) = { + import c.universe._ + q"()" + } + + def two(x: Int)(y: Int): Unit = macro twoImpl + def twoImpl(c: Context)(x: c.Tree)(y: c.Tree) = { + import c.universe._ + q"()" + } +} diff --git a/test/files/neg/macro-argc-mismatch/Test_2.scala b/test/files/neg/macro-argc-mismatch/Test_2.scala new file mode 100644 index 0000000000..28f9c35654 --- /dev/null +++ b/test/files/neg/macro-argc-mismatch/Test_2.scala @@ -0,0 +1,19 @@ +import Macros._ + +object Test extends App { + one + one() + one(2, 3) + one()() + one(1)() + + two + two() + two(2, 3) + two()() + two(1) + two(1)() + two(1)(2, 3) + two(1)()() + two(1)(1)() +}
\ No newline at end of file diff --git a/test/files/neg/macro-invalidusage-badargs.check b/test/files/neg/macro-invalidusage-badargs.check index 4c1115418b..3fd3c53691 100644 --- a/test/files/neg/macro-invalidusage-badargs.check +++ b/test/files/neg/macro-invalidusage-badargs.check @@ -3,13 +3,14 @@ Macros_Test_2.scala:5: error: type mismatch; required: Int foo("42") ^ -Macros_Test_2.scala:6: error: too few argument lists for macro invocation +Macros_Test_2.scala:6: error: missing arguments for macro method foo in object Macros foo ^ Macros_Test_2.scala:7: error: Int does not take parameters foo(4)(2) ^ -Macros_Test_2.scala:8: error: macro applications do not support named and/or default arguments +Macros_Test_2.scala:8: error: not enough arguments for macro method foo: (x: Int)Int. +Unspecified value parameter x. foo() ^ Macros_Test_2.scala:9: error: too many arguments for macro method foo: (x: Int)Int diff --git a/test/files/neg/macro-qmarkqmarkqmark.check b/test/files/neg/macro-qmarkqmarkqmark.check index bc3e25edaf..b4f8ea905f 100644 --- a/test/files/neg/macro-qmarkqmarkqmark.check +++ b/test/files/neg/macro-qmarkqmarkqmark.check @@ -1,7 +1,7 @@ macro-qmarkqmarkqmark.scala:5: error: macro implementation is missing foo1 ^ -macro-qmarkqmarkqmark.scala:8: error: too few argument lists for macro invocation +macro-qmarkqmarkqmark.scala:8: error: missing arguments for macro method foo2 in object Macros foo2 ^ macro-qmarkqmarkqmark.scala:9: error: macro implementation is missing diff --git a/test/files/neg/t7157.check b/test/files/neg/t7157.check index c6a7af9a23..3988460d4b 100644 --- a/test/files/neg/t7157.check +++ b/test/files/neg/t7157.check @@ -7,7 +7,8 @@ Test_2.scala:6: error: too many arguments for macro method m1_0_0: ()Unit Test_2.scala:7: error: too many arguments for macro method m1_0_0: ()Unit m1_0_0(1, 2, 3) ^ -Test_2.scala:9: error: macro applications do not support named and/or default arguments +Test_2.scala:9: error: not enough arguments for macro method m1_1_1: (x: Int)Unit. +Unspecified value parameter x. m1_1_1() ^ Test_2.scala:11: error: too many arguments for macro method m1_1_1: (x: Int)Unit @@ -16,22 +17,27 @@ Test_2.scala:11: error: too many arguments for macro method m1_1_1: (x: Int)Unit Test_2.scala:12: error: too many arguments for macro method m1_1_1: (x: Int)Unit m1_1_1(1, 2, 3) ^ -Test_2.scala:14: error: macro applications do not support named and/or default arguments +Test_2.scala:14: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit. +Unspecified value parameters x, y. m1_2_2() ^ -Test_2.scala:15: error: macro applications do not support named and/or default arguments +Test_2.scala:15: error: not enough arguments for macro method m1_2_2: (x: Int, y: Int)Unit. +Unspecified value parameter y. m1_2_2(1) ^ Test_2.scala:17: error: too many arguments for macro method m1_2_2: (x: Int, y: Int)Unit m1_2_2(1, 2, 3) ^ -Test_2.scala:24: error: macro applications do not support named and/or default arguments +Test_2.scala:24: error: not enough arguments for macro method m1_1_inf: (x: Int, y: Int*)Unit. +Unspecified value parameters x, y. m1_1_inf() ^ -Test_2.scala:29: error: macro applications do not support named and/or default arguments +Test_2.scala:29: error: not enough arguments for macro method m1_2_inf: (x: Int, y: Int, z: Int*)Unit. +Unspecified value parameters x, y, z. m1_2_inf() ^ -Test_2.scala:30: error: macro applications do not support named and/or default arguments +Test_2.scala:30: error: not enough arguments for macro method m1_2_inf: (x: Int, y: Int, z: Int*)Unit. +Unspecified value parameters y, z. m1_2_inf(1) ^ Test_2.scala:35: error: too many arguments for macro method m2_0_0: ()Unit @@ -43,7 +49,8 @@ Test_2.scala:36: error: too many arguments for macro method m2_0_0: ()Unit Test_2.scala:37: error: too many arguments for macro method m2_0_0: ()Unit m2_0_0()(1, 2, 3) ^ -Test_2.scala:39: error: macro applications do not support named and/or default arguments +Test_2.scala:39: error: not enough arguments for macro method m2_1_1: (x: Int)Unit. +Unspecified value parameter x. m2_1_1()() ^ Test_2.scala:41: error: too many arguments for macro method m2_1_1: (x: Int)Unit @@ -52,22 +59,27 @@ Test_2.scala:41: error: too many arguments for macro method m2_1_1: (x: Int)Unit Test_2.scala:42: error: too many arguments for macro method m2_1_1: (x: Int)Unit m2_1_1()(1, 2, 3) ^ -Test_2.scala:44: error: macro applications do not support named and/or default arguments +Test_2.scala:44: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit. +Unspecified value parameters x, y. m2_2_2()() ^ -Test_2.scala:45: error: macro applications do not support named and/or default arguments +Test_2.scala:45: error: not enough arguments for macro method m2_2_2: (x: Int, y: Int)Unit. +Unspecified value parameter y. m2_2_2()(1) ^ Test_2.scala:47: error: too many arguments for macro method m2_2_2: (x: Int, y: Int)Unit m2_2_2()(1, 2, 3) ^ -Test_2.scala:54: error: macro applications do not support named and/or default arguments +Test_2.scala:54: error: not enough arguments for macro method m2_1_inf: (x: Int, y: Int*)Unit. +Unspecified value parameters x, y. m2_1_inf()() ^ -Test_2.scala:59: error: macro applications do not support named and/or default arguments +Test_2.scala:59: error: not enough arguments for macro method m2_2_inf: (x: Int, y: Int, z: Int*)Unit. +Unspecified value parameters x, y, z. m2_2_inf()() ^ -Test_2.scala:60: error: macro applications do not support named and/or default arguments +Test_2.scala:60: error: not enough arguments for macro method m2_2_inf: (x: Int, y: Int, z: Int*)Unit. +Unspecified value parameters y, z. m2_2_inf()(1) ^ 24 errors found diff --git a/test/files/run/macro-expand-default-named.check b/test/files/run/macro-expand-default-named.check new file mode 100644 index 0000000000..2d75772572 --- /dev/null +++ b/test/files/run/macro-expand-default-named.check @@ -0,0 +1,56 @@ +Test.this.one(2, -40) = 42 +Test.this.one(y = -40, x = 2) = 42 +Test.this.one(2, -40) = 42 +Test.this.one(100) = 140 +Test.this.one(y = 100) = -98 +Test.this.one(100) = 140 +Test.this.one() = 42 +Test.this.qualone.one(2, -40) = 42 +Test.this.qualone.one(y = -40, x = 2) = 42 +Test.this.qualone.one(2, -40) = 42 +Test.this.qualone.one(x = 100) = 140 +Test.this.qualone.one(y = 100) = -98 +Test.this.qualone.one(x = 100) = 140 +Test.this.qualone.one() = 42 +Test.this.onezero(2, -40)(1, 2) = 41 +Test.this.onezero(y = -40, x = 2)(z = 3, w = 4) = 41 +Test.this.onezero(2, -40)(5, 6) = 41 +Test.this.onezero(100)(7, 8) = 139 +Test.this.onezero(y = 100)(z = 9, w = 10) = -99 +Test.this.onezero(100)(11, 12) = 139 +Test.this.onezero()(13, 14) = 41 +Test.this.qualonezero.onezero(2, -40)(15, 16) = 41 +Test.this.qualonezero.onezero(y = -40, x = 2)(z = 17, w = 18) = 41 +Test.this.qualonezero.onezero(2, -40)(19, 20) = 41 +Test.this.qualonezero.onezero(x = 100)(z = 21, w = 22) = 139 +Test.this.qualonezero.onezero(y = 100)(z = 23, w = 24) = -99 +Test.this.qualonezero.onezero(x = 100)(z = 25, w = 26) = 139 +Test.this.qualonezero.onezero()(z = 27, w = 28) = 41 +Test.this.zeroone(1, 2)(2, -40) = 41 +Test.this.zeroone(x = 3, y = 4)(w = -40, z = 2) = 41 +Test.this.zeroone(5, 6)(2, -40) = 41 +Test.this.zeroone(x = 7, y = 8)(z = 100) = 139 +Test.this.zeroone(x = 9, y = 10)(w = 100) = -99 +Test.this.zeroone(x = 11, y = 12)(z = 100) = 139 +Test.this.zeroone(x = 13, y = 14)() = 41 +Test.this.qualzeroone.zeroone(15, 16)(2, -40) = 41 +Test.this.qualzeroone.zeroone(x = 17, y = 18)(w = -40, z = 2) = 41 +Test.this.qualzeroone.zeroone(19, 20)(2, -40) = 41 +Test.this.qualzeroone.zeroone(x = 21, y = 22)(z = 100) = 139 +Test.this.qualzeroone.zeroone(x = 23, y = 24)(w = 100) = -99 +Test.this.qualzeroone.zeroone(x = 25, y = 26)(z = 100) = 139 +Test.this.qualzeroone.zeroone(x = 27, y = 28)() = 41 +Test.this.oneone(2, -40)(2, -40) = 84 +Test.this.oneone(y = -40, x = 2)(w = -40, z = 2) = 84 +Test.this.oneone(2, -40)(2, -40) = 84 +Test.this.oneone(x = 100)(z = 100) = 280 +Test.this.oneone(y = 100)(w = 100) = -196 +Test.this.oneone(x = 100)(z = 100) = 280 +Test.this.oneone()() = 84 +Test.this.qualoneone.oneone(2, -40)(2, -40) = 84 +Test.this.qualoneone.oneone(y = -40, x = 2)(w = -40, z = 2) = 84 +Test.this.qualoneone.oneone(2, -40)(2, -40) = 84 +Test.this.qualoneone.oneone(x = 100)(z = 100) = 280 +Test.this.qualoneone.oneone(y = 100)(w = 100) = -196 +Test.this.qualoneone.oneone(x = 100)(z = 100) = 280 +Test.this.qualoneone.oneone()() = 84 diff --git a/test/files/run/macro-expand-default-named/Impls_1.scala b/test/files/run/macro-expand-default-named/Impls_1.scala new file mode 100644 index 0000000000..73774cd56a --- /dev/null +++ b/test/files/run/macro-expand-default-named/Impls_1.scala @@ -0,0 +1,37 @@ +import scala.reflect.macros.blackbox.Context + +object Impls { + def one(c: Context)(x: c.Tree, y: c.Tree) = { + import c.universe._ + val x1 = x orElse q"2" + val y1 = y orElse q"-40" + q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1))" + } + + def onezero(c: Context)(x: c.Tree, y: c.Tree)(z: c.Tree, w: c.Tree) = { + import c.universe._ + val x1 = x orElse q"2" + val y1 = y orElse q"-40" + val z1 = z + val w1 = w + q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1 + $z1 - $w1))" + } + + def zeroone(c: Context)(x: c.Tree, y: c.Tree)(z: c.Tree, w: c.Tree) = { + import c.universe._ + val x1 = x + val y1 = y + val z1 = z orElse q"2" + val w1 = w orElse q"-40" + q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1 + $z1 - $w1))" + } + + def oneone(c: Context)(x: c.Tree, y: c.Tree)(z: c.Tree, w: c.Tree) = { + import c.universe._ + val x1 = x orElse q"2" + val y1 = y orElse q"-40" + val z1 = z orElse q"2" + val w1 = w orElse q"-40" + q"println(${c.macroApplication.toString + " = "} + ($x1 - $y1 + $z1 - $w1))" + } +}
\ No newline at end of file diff --git a/test/files/run/macro-expand-default-named/Macros_Test_2.scala b/test/files/run/macro-expand-default-named/Macros_Test_2.scala new file mode 100644 index 0000000000..e58eddd9a3 --- /dev/null +++ b/test/files/run/macro-expand-default-named/Macros_Test_2.scala @@ -0,0 +1,71 @@ +import scala.language.experimental.macros + +object Test extends App { + def one(x: Int = 2, y: Int = -40): Unit = macro Impls.one + one(2, -40) + one(y = -40, x = 2) + one(x = 2, y = -40) + one(x = 100) + one(y = 100) + one(100) + one() + var qualone = this + qualone.one(2, -40) + qualone.one(y = -40, x = 2) + qualone.one(x = 2, y = -40) + qualone.one(x = 100) + qualone.one(y = 100) + qualone.one(100) + qualone.one() + + def onezero(x: Int = 2, y: Int = -40)(z: Int, w: Int): Unit = macro Impls.onezero + onezero(2, -40)(1, 2) + onezero(y = -40, x = 2)(3, 4) + onezero(x = 2, y = -40)(5, 6) + onezero(x = 100)(7, 8) + onezero(y = 100)(9, 10) + onezero(100)(11, 12) + onezero()(13, 14) + var qualonezero = this + qualonezero.onezero(2, -40)(15, 16) + qualonezero.onezero(y = -40, x = 2)(17, 18) + qualonezero.onezero(x = 2, y = -40)(19, 20) + qualonezero.onezero(x = 100)(21, 22) + qualonezero.onezero(y = 100)(23, 24) + qualonezero.onezero(100)(25, 26) + qualonezero.onezero()(27, 28) + + def zeroone(x: Int, y: Int)(z: Int = 2, w: Int = -40): Unit = macro Impls.zeroone + zeroone(1, 2)(2, -40) + zeroone(3, 4)(w = -40, z = 2) + zeroone(5, 6)(z = 2, w = -40) + zeroone(7, 8)(z = 100) + zeroone(9, 10)(w = 100) + zeroone(11, 12)(100) + zeroone(13, 14)() + var qualzeroone = this + qualzeroone.zeroone(15, 16)(2, -40) + qualzeroone.zeroone(17, 18)(w = -40, z = 2) + qualzeroone.zeroone(19, 20)(z = 2, w = -40) + qualzeroone.zeroone(21, 22)(z = 100) + qualzeroone.zeroone(23, 24)(w = 100) + qualzeroone.zeroone(25, 26)(100) + qualzeroone.zeroone(27, 28)() + + def oneone(x: Int = 2, y: Int = -40)(z: Int = 2, w: Int = -40): Unit = macro Impls.oneone + oneone(2, -40)(2, -40) + oneone(y = -40, x = 2)(w = -40, z = 2) + oneone(x = 2, y = -40)(z = 2, w = -40) + oneone(x = 100)(z = 100) + oneone(y = 100)(w = 100) + oneone(100)(100) + oneone()() + var qualoneone = this + qualoneone.oneone(2, -40)(2, -40) + qualoneone.oneone(y = -40, x = 2)(w = -40, z = 2) + qualoneone.oneone(x = 2, y = -40)(z = 2, w = -40) + qualoneone.oneone(x = 100)(z = 100) + qualoneone.oneone(y = 100)(w = 100) + qualoneone.oneone(100)(100) + qualoneone.oneone()() +}
\ No newline at end of file diff --git a/test/files/run/macro-expand-ownerchain-a.check b/test/files/run/macro-expand-ownerchain-a.check new file mode 100644 index 0000000000..51993f072d --- /dev/null +++ b/test/files/run/macro-expand-ownerchain-a.check @@ -0,0 +1,2 @@ +2 +2 diff --git a/test/files/run/macro-expand-ownerchain-a/Macros_1.scala b/test/files/run/macro-expand-ownerchain-a/Macros_1.scala new file mode 100644 index 0000000000..0d11c24ad1 --- /dev/null +++ b/test/files/run/macro-expand-ownerchain-a/Macros_1.scala @@ -0,0 +1,11 @@ +import scala.reflect.macros.whitebox._ +import scala.language.experimental.macros + +object Macros { + def impl(c: Context)(x: c.Tree, y: c.Tree) = { + import c.universe._ + q"println($x)" + } + + def foo(x: Int, y: Int): Unit = macro impl +}
\ No newline at end of file diff --git a/test/files/run/macro-expand-ownerchain-a/Test_2.scala b/test/files/run/macro-expand-ownerchain-a/Test_2.scala new file mode 100644 index 0000000000..738afc75df --- /dev/null +++ b/test/files/run/macro-expand-ownerchain-a/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + Macros.foo(y = 1, x = ((x: Int) => x)(2)) + Macros.foo(y = 1, x = {val x = 2; x}) +}
\ No newline at end of file diff --git a/test/files/run/macro-invalidusage-partialapplication-with-tparams.check b/test/files/run/macro-invalidusage-partialapplication-with-tparams.check index 6cbcb9e5af..f1061e00f7 100644 --- a/test/files/run/macro-invalidusage-partialapplication-with-tparams.check +++ b/test/files/run/macro-invalidusage-partialapplication-with-tparams.check @@ -1,3 +1,3 @@ reflective compilation has failed: -too few argument lists for macro invocation +missing arguments for macro method foo in object Macros diff --git a/test/files/run/macro-invalidusage-partialapplication.check b/test/files/run/macro-invalidusage-partialapplication.check index 6cbcb9e5af..f1061e00f7 100644 --- a/test/files/run/macro-invalidusage-partialapplication.check +++ b/test/files/run/macro-invalidusage-partialapplication.check @@ -1,3 +1,3 @@ reflective compilation has failed: -too few argument lists for macro invocation +missing arguments for macro method foo in object Macros diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check index 29ccee3cc6..c78d95dbed 100644 --- a/test/files/run/reify-repl-fail-gracefully.check +++ b/test/files/run/reify-repl-fail-gracefully.check @@ -10,7 +10,7 @@ import scala.reflect.runtime.universe._ scala> scala> reify -<console>:12: error: too few argument lists for macro invocation +<console>:12: error: missing arguments for macro method reify in class Universe reify ^ diff --git a/test/pending/run/macro-expand-default.flags b/test/pending/run/macro-expand-default.flags deleted file mode 100644 index cd66464f2f..0000000000 --- a/test/pending/run/macro-expand-default.flags +++ /dev/null @@ -1 +0,0 @@ --language:experimental.macros
\ No newline at end of file diff --git a/test/pending/run/macro-expand-default/Impls_1.scala b/test/pending/run/macro-expand-default/Impls_1.scala deleted file mode 100644 index fd5d8d7f18..0000000000 --- a/test/pending/run/macro-expand-default/Impls_1.scala +++ /dev/null @@ -1,10 +0,0 @@ -import scala.reflect.macros.blackbox.Context - -object Impls { - def foo(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) = { - import c.universe._ - val sum = Apply(Select(x.tree, TermName("$minus")), List(y.tree)) - val body = Apply(Select(Ident(definitions.PredefModule), TermName("println")), List(sum)) - Expr[Unit](body) - } -}
\ No newline at end of file diff --git a/test/pending/run/macro-expand-default/Macros_Test_2.scala b/test/pending/run/macro-expand-default/Macros_Test_2.scala deleted file mode 100644 index 92fe84d04a..0000000000 --- a/test/pending/run/macro-expand-default/Macros_Test_2.scala +++ /dev/null @@ -1,8 +0,0 @@ -object Test extends App { - def foo(x: Int = 2, y: Int = -40) = macro Impls.foo - foo(y = -40, x = 2) - foo(x = 2, y = -40) - foo(x = 100) - foo(y = 100) - foo() -}
\ No newline at end of file diff --git a/test/pending/run/macro-expand-named.flags b/test/pending/run/macro-expand-named.flags deleted file mode 100644 index cd66464f2f..0000000000 --- a/test/pending/run/macro-expand-named.flags +++ /dev/null @@ -1 +0,0 @@ --language:experimental.macros
\ No newline at end of file diff --git a/test/pending/run/macro-expand-named/Impls_1.scala b/test/pending/run/macro-expand-named/Impls_1.scala deleted file mode 100644 index fd5d8d7f18..0000000000 --- a/test/pending/run/macro-expand-named/Impls_1.scala +++ /dev/null @@ -1,10 +0,0 @@ -import scala.reflect.macros.blackbox.Context - -object Impls { - def foo(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) = { - import c.universe._ - val sum = Apply(Select(x.tree, TermName("$minus")), List(y.tree)) - val body = Apply(Select(Ident(definitions.PredefModule), TermName("println")), List(sum)) - Expr[Unit](body) - } -}
\ No newline at end of file diff --git a/test/pending/run/macro-expand-named/Macros_Test_2.scala b/test/pending/run/macro-expand-named/Macros_Test_2.scala deleted file mode 100644 index abebcf8448..0000000000 --- a/test/pending/run/macro-expand-named/Macros_Test_2.scala +++ /dev/null @@ -1,5 +0,0 @@ -object Test extends App { - def foo(x: Int, y: Int) = macro Impls.foo - foo(y = -40, x = 2) - foo(x = 2, y = -40) -}
\ No newline at end of file |