From e205e6b9aaebe50135ffcf922945867b51929b1a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 2 Oct 2018 01:59:56 +0200 Subject: [PATCH 1/4] Fix #5119: Get underlying argument for synthetic local values --- compiler/src/dotty/tools/dotc/ast/tpd.scala | 9 ++++++--- compiler/test/dotc/run-test-pickling.blacklist | 1 + tests/run/i5119.check | 2 ++ tests/run/i5119/Macro_1.scala | 13 +++++++++++++ tests/run/i5119/Main_2.scala | 8 ++++++++ tests/run/xml-interpolation/Test_2.scala | 4 ++-- 6 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tests/run/i5119.check create mode 100644 tests/run/i5119/Macro_1.scala create mode 100644 tests/run/i5119/Main_2.scala diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index ffa501ce7181..b6139801eeac 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -942,11 +942,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } } - /** Map Inlined nodes and InlineProxy references to underlying arguments */ + /** Map Inlined nodes, InlineProxy references and Synthetic val references to underlying arguments */ object mapToUnderlying extends TreeMap { override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match { - case tree: Ident if tree.symbol.is(InlineProxy) => - tree.symbol.defTree.asInstanceOf[ValOrDefDef].rhs.underlyingArgument + case tree: Ident if tree.symbol.is(InlineProxy) || (tree.symbol.is(Synthetic) && !tree.symbol.owner.isClass) => + tree.symbol.defTree match { + case defTree: ValOrDefDef => defTree.rhs.underlyingArgument + case _ => tree + } case Inlined(_, _, arg) => arg.underlyingArgument case tree => diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index f6a0edc4e7f5..45cf1be304aa 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -20,6 +20,7 @@ i4803d i4803e i4803f i4947b +i5119 inline-varargs-1 implicitShortcut lazy-implicit-lists.scala diff --git a/tests/run/i5119.check b/tests/run/i5119.check new file mode 100644 index 000000000000..8ceb3b582ff2 --- /dev/null +++ b/tests/run/i5119.check @@ -0,0 +1,2 @@ +Term.Select(Term.Apply(Term.Select(Term.New(TypeTree.TypeIdent("StringContextOps")), "", Some(Signature(List(scala.Function0), Macro$.StringContextOps))), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("_root_"), "scala", None), "StringContext", None), "apply", Some(Signature(List(scala.collection.Seq), scala.StringContext))), List(Term.Typed(Term.Repeated(List(Term.Literal(Constant.String("Hello World ")), Term.Literal(Constant.String("!")))), TypeTree.Synthetic()))))), "inline$sc", Some(Signature(Nil, scala.StringContext))) +Term.Typed(Term.Repeated(List(Term.Literal(Constant.Int(1)))), TypeTree.Synthetic()) diff --git a/tests/run/i5119/Macro_1.scala b/tests/run/i5119/Macro_1.scala new file mode 100644 index 000000000000..bbcd4da86104 --- /dev/null +++ b/tests/run/i5119/Macro_1.scala @@ -0,0 +1,13 @@ +import scala.quoted._ +import scala.tasty.Tasty + +object Macro { + class StringContextOps(sc: => StringContext) { + inline def ff(args: => Any*): String = ~Macro.impl('(sc), '(args)) + } + implicit inline def XmlQuote(sc: => StringContext): StringContextOps = new StringContextOps(sc) + def impl(sc: Expr[StringContext], args: Expr[Seq[Any]])(implicit tasty: Tasty): Expr[String] = { + import tasty._ + (sc.toTasty.underlyingArgument.show + "\n" + args.toTasty.underlyingArgument.show).toExpr + } +} diff --git a/tests/run/i5119/Main_2.scala b/tests/run/i5119/Main_2.scala new file mode 100644 index 000000000000..9242dcabc5b1 --- /dev/null +++ b/tests/run/i5119/Main_2.scala @@ -0,0 +1,8 @@ + +object Test { + import Macro._ + + def main(args: Array[String]): Unit = { + println(ff"Hello World ${1}!") + } +} \ No newline at end of file diff --git a/tests/run/xml-interpolation/Test_2.scala b/tests/run/xml-interpolation/Test_2.scala index 6dda8d1a00d7..9a3d8d64161b 100644 --- a/tests/run/xml-interpolation/Test_2.scala +++ b/tests/run/xml-interpolation/Test_2.scala @@ -2,8 +2,8 @@ import XmlQuote._ object Test { def main(args: Array[String]): Unit = { - // TODO: enable once #5119 is fixed - // assert(xml"Hello Allan!" == Xml("Hello Allan!", Nil)) + + assert(xml"Hello Allan!" == Xml("Hello Allan!", Nil)) val name = new Object{} assert(xml"Hello $name!" == Xml("Hello ??!", List(name))) From 87d555a506550d66495897ea8963ae4382c9754a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 2 Oct 2018 14:14:13 +0200 Subject: [PATCH 2/4] Add test --- compiler/test/dotc/run-test-pickling.blacklist | 1 + tests/run/i5119b.check | 4 ++++ tests/run/i5119b/Macro_1.scala | 13 +++++++++++++ tests/run/i5119b/Main_2.scala | 11 +++++++++++ 4 files changed, 29 insertions(+) create mode 100644 tests/run/i5119b.check create mode 100644 tests/run/i5119b/Macro_1.scala create mode 100644 tests/run/i5119b/Main_2.scala diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index 45cf1be304aa..39680daf65f8 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -21,6 +21,7 @@ i4803e i4803f i4947b i5119 +i5119b inline-varargs-1 implicitShortcut lazy-implicit-lists.scala diff --git a/tests/run/i5119b.check b/tests/run/i5119b.check new file mode 100644 index 000000000000..6ca15579e175 --- /dev/null +++ b/tests/run/i5119b.check @@ -0,0 +1,4 @@ +Term.NamedArg("arg1", Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(1))))) +Term.NamedArg("arg2", Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(2))))) +Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(4)))) +Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(3)))) diff --git a/tests/run/i5119b/Macro_1.scala b/tests/run/i5119b/Macro_1.scala new file mode 100644 index 000000000000..4521a5ca9317 --- /dev/null +++ b/tests/run/i5119b/Macro_1.scala @@ -0,0 +1,13 @@ +import scala.quoted._ +import scala.tasty.Tasty + +object Macro { + + inline def ff(arg1: Any, arg2: Any): String = ~Macro.impl('(arg1), '(arg2)) + + def impl(arg1: Expr[Any], arg2: Expr[Any])(implicit tasty: Tasty): Expr[String] = { + import tasty._ + (arg1.toTasty.underlyingArgument.show + "\n" + arg2.toTasty.underlyingArgument.show).toExpr + } + +} diff --git a/tests/run/i5119b/Main_2.scala b/tests/run/i5119b/Main_2.scala new file mode 100644 index 000000000000..e6a797d97dca --- /dev/null +++ b/tests/run/i5119b/Main_2.scala @@ -0,0 +1,11 @@ + +object Test { + import Macro._ + + def main(args: Array[String]): Unit = { + println(ff(arg1 = foo(1), arg2 = foo(2))) + println(ff(arg2 = foo(3), arg1 = foo(4))) + } + + def foo(x: Any): Any = () +} From bf5c8d12815c9337159481b1633a14beb3683212 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 2 Oct 2018 14:17:11 +0200 Subject: [PATCH 3/4] Skip NamedArg in underlyingArgument --- compiler/src/dotty/tools/dotc/ast/tpd.scala | 2 ++ tests/run/i5119b.check | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index b6139801eeac..36c8bf0bb948 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -952,6 +952,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } case Inlined(_, _, arg) => arg.underlyingArgument + case NamedArg(_, arg) => + arg.underlyingArgument case tree => super.transform(tree) } diff --git a/tests/run/i5119b.check b/tests/run/i5119b.check index 6ca15579e175..29e18e92d65b 100644 --- a/tests/run/i5119b.check +++ b/tests/run/i5119b.check @@ -1,4 +1,4 @@ -Term.NamedArg("arg1", Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(1))))) -Term.NamedArg("arg2", Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(2))))) +Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(1)))) +Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(2)))) Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(4)))) Term.Apply(Term.Ident("foo"), List(Term.Literal(Constant.Int(3)))) From bf4faeff1b27de6f30d97ea35e64e54d52aa710d Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 2 Oct 2018 14:19:34 +0200 Subject: [PATCH 4/4] Avoid useless indirections Also makes mapToUnderlying.transform be a tailrec --- compiler/src/dotty/tools/dotc/ast/tpd.scala | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 36c8bf0bb948..471350ba3d03 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -947,15 +947,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: Ident if tree.symbol.is(InlineProxy) || (tree.symbol.is(Synthetic) && !tree.symbol.owner.isClass) => tree.symbol.defTree match { - case defTree: ValOrDefDef => defTree.rhs.underlyingArgument + case defTree: ValOrDefDef => transform(defTree.rhs) case _ => tree } - case Inlined(_, _, arg) => - arg.underlyingArgument - case NamedArg(_, arg) => - arg.underlyingArgument - case tree => - super.transform(tree) + case Inlined(_, _, arg) => transform(arg) + case NamedArg(_, arg) => transform(arg) + case tree => super.transform(tree) } }