From 5ac5a34095c4e3166ef6743495d5eee9da47be8b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 6 Jan 2020 11:48:19 +0100 Subject: [PATCH 1/3] Fix printing of types --- .../tasty/reflect/SourceCodePrinter.scala | 2 +- tests/run-macros/flops-rewrite.check | 4 +- tests/run-macros/quote-matcher-runtime.check | 46 +++++++++---------- .../quote-matching-optimize-1.check | 8 ++-- tests/run-macros/quoted-matching-docs-2.check | 2 +- tests/run-macros/tasty-macro-positions.check | 4 +- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/library/src/scala/tasty/reflect/SourceCodePrinter.scala b/library/src/scala/tasty/reflect/SourceCodePrinter.scala index cc2b8ad1114a..73b31c92c8ef 100644 --- a/library/src/scala/tasty/reflect/SourceCodePrinter.scala +++ b/library/src/scala/tasty/reflect/SourceCodePrinter.scala @@ -1467,7 +1467,7 @@ class SourceCodePrinter[R <: Reflection & Singleton](val tasty: R)(syntaxHighlig object ScalaPackage { def unapply(tpe: TypeOrBounds)(given ctx: Context): Boolean = tpe match { - case tpe: TermRef => tpe.termSymbol == defn.ScalaPackage + case tpe: Type => tpe.termSymbol == defn.ScalaPackage case _ => false } } diff --git a/tests/run-macros/flops-rewrite.check b/tests/run-macros/flops-rewrite.check index 0a1a7e272b5b..1df685ef872f 100644 --- a/tests/run-macros/flops-rewrite.check +++ b/tests/run-macros/flops-rewrite.check @@ -4,6 +4,6 @@ scala.Nil scala.Nil.map[scala.Nothing](((x: scala.Nothing) => x)).++[scala.Nothing](scala.Nil.map[scala.Nothing](((x: scala.Nothing) => x))) scala.Nil -scala.Nil.map[scala.Nothing](((x: scala.Nothing) => x)).++[scala.Int](scala.List.apply[scala.Int]((3: scala.[scala.Int]))).++[scala.Int](scala.Nil) -scala.List.apply[scala.Int]((3: scala.[scala.Int])) +scala.Nil.map[scala.Nothing](((x: scala.Nothing) => x)).++[scala.Int](scala.List.apply[scala.Int](3)).++[scala.Int](scala.Nil) +scala.List.apply[scala.Int](3) diff --git a/tests/run-macros/quote-matcher-runtime.check b/tests/run-macros/quote-matcher-runtime.check index 41908e892b53..736a53af2532 100644 --- a/tests/run-macros/quote-matcher-runtime.check +++ b/tests/run-macros/quote-matcher-runtime.check @@ -189,20 +189,20 @@ Pattern: fs() Result: Some(List()) Scrutinee: fs() -Pattern: fs((scala.internal.Quoted.patternHole[scala.Seq[scala.Int]]: scala.[scala.Int])) -Result: Some(List(Expr((: scala.[scala.Int])))) +Pattern: fs(scala.internal.Quoted.patternHole[scala.Seq[scala.Int]]: _*) +Result: Some(List(Expr())) -Scrutinee: fs((1, 2, 3: scala.[scala.Int])) -Pattern: fs((1, 2, 3: scala.[scala.Int])) +Scrutinee: fs(1, 2, 3) +Pattern: fs(1, 2, 3) Result: Some(List()) -Scrutinee: fs((1, 2, 3: scala.[scala.Int])) -Pattern: fs((scala.internal.Quoted.patternHole[scala.Int], scala.internal.Quoted.patternHole[scala.Int], 3: scala.[scala.Int])) +Scrutinee: fs(1, 2, 3) +Pattern: fs(scala.internal.Quoted.patternHole[scala.Int], scala.internal.Quoted.patternHole[scala.Int], 3) Result: Some(List(Expr(1), Expr(2))) -Scrutinee: fs((1, 2, 3: scala.[scala.Int])) -Pattern: fs((scala.internal.Quoted.patternHole[scala.Seq[scala.Int]]: scala.[scala.Int])) -Result: Some(List(Expr((1, 2, 3: scala.[scala.Int])))) +Scrutinee: fs(1, 2, 3) +Pattern: fs(scala.internal.Quoted.patternHole[scala.Seq[scala.Int]]: _*) +Result: Some(List(Expr(1, 2, 3))) Scrutinee: f2(1, 2) Pattern: f2(1, 2) @@ -240,17 +240,17 @@ Scrutinee: ((x: scala.Int) => "abc") Pattern: ((x: scala.Int @scala.internal.Quoted.patternBindHole) => scala.internal.Quoted.patternHole[scala.Predef.String]) Result: Some(List(Sym(x), Expr("abc"))) -Scrutinee: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Pattern: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) +Scrutinee: scala.StringContext.apply("abc", "xyz") +Pattern: scala.StringContext.apply("abc", "xyz") Result: Some(List()) -Scrutinee: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Pattern: scala.StringContext.apply((scala.internal.Quoted.patternHole[java.lang.String], scala.internal.Quoted.patternHole[java.lang.String]: scala.[scala.Predef.String])) +Scrutinee: scala.StringContext.apply("abc", "xyz") +Pattern: scala.StringContext.apply(scala.internal.Quoted.patternHole[java.lang.String], scala.internal.Quoted.patternHole[java.lang.String]) Result: Some(List(Expr("abc"), Expr("xyz"))) -Scrutinee: scala.StringContext.apply(("abc", "xyz": scala.[scala.Predef.String])) -Pattern: scala.StringContext.apply((scala.internal.Quoted.patternHole[scala.Seq[scala.Predef.String]]: scala.[scala.Predef.String])) -Result: Some(List(Expr(("abc", "xyz": scala.[scala.Predef.String])))) +Scrutinee: scala.StringContext.apply("abc", "xyz") +Pattern: scala.StringContext.apply(scala.internal.Quoted.patternHole[scala.Seq[scala.Predef.String]]: _*) +Result: Some(List(Expr("abc", "xyz"))) Scrutinee: { val a: scala.Int = 45 @@ -714,21 +714,21 @@ Pattern: try scala.internal.Quoted.patternHole[scala.Int] finally { } Result: Some(List(Expr(1), Expr(2))) -Scrutinee: scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int])).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) +Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { @scala.internal.Quoted.patternBindHole type T scala.internal.Quoted.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.Quoted.patternHole[scala.Function1[scala.Int, T]]) } -Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int]))), Expr(((x: scala.Int) => scala.Predef.println(x))))) +Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => scala.Predef.println(x))))) -Scrutinee: scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int])).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) +Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { @scala.internal.Quoted.patternBindHole type T = scala.Unit scala.internal.Quoted.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.Quoted.patternHole[scala.Function1[scala.Int, T]]) } -Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int]))), Expr(((x: scala.Int) => scala.Predef.println(x))))) +Result: Some(List(Type(scala.Unit), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => scala.Predef.println(x))))) -Scrutinee: scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int])).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) +Scrutinee: scala.List.apply[scala.Int](1, 2, 3).foreach[scala.Unit](((x: scala.Int) => scala.Predef.println(x))) Pattern: { @scala.internal.Quoted.patternBindHole type T <: scala.Predef.String scala.internal.Quoted.patternHole[scala.List[scala.Int]].foreach[T](scala.internal.Quoted.patternHole[scala.Function1[scala.Int, T]]) @@ -787,7 +787,7 @@ Pattern: { } Result: None -Scrutinee: scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int])).map[scala.Double](((x: scala.Int) => x.toDouble./(2))).map[java.lang.String](((y: scala.Double) => y.toString())) +Scrutinee: scala.List.apply[scala.Int](1, 2, 3).map[scala.Double](((x: scala.Int) => x.toDouble./(2))).map[java.lang.String](((y: scala.Double) => y.toString())) Pattern: { @scala.internal.Quoted.patternBindHole type T @scala.internal.Quoted.patternBindHole type U @@ -795,7 +795,7 @@ Pattern: { (scala.internal.Quoted.patternHole[scala.List[T]].map[U](scala.internal.Quoted.patternHole[scala.Function1[T, U]]).map[V](scala.internal.Quoted.patternHole[scala.Function1[U, V]]): scala.collection.immutable.List[scala.Any]) } -Result: Some(List(Type(scala.Int), Type(scala.Double), Type(java.lang.String), Expr(scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int]))), Expr(((x: scala.Int) => x.toDouble./(2))), Expr(((y: scala.Double) => y.toString())))) +Result: Some(List(Type(scala.Int), Type(scala.Double), Type(java.lang.String), Expr(scala.List.apply[scala.Int](1, 2, 3)), Expr(((x: scala.Int) => x.toDouble./(2))), Expr(((y: scala.Double) => y.toString())))) Scrutinee: ((x: scala.Int) => x) Pattern: { diff --git a/tests/run-macros/quote-matching-optimize-1.check b/tests/run-macros/quote-matching-optimize-1.check index 2f86188f9fa9..383e8c426e8a 100644 --- a/tests/run-macros/quote-matching-optimize-1.check +++ b/tests/run-macros/quote-matching-optimize-1.check @@ -16,15 +16,15 @@ Original: ls.filter(((x: scala.Int) => x.<(3))).foreach[scala.Unit](((x: scala.I Optimized: ls.foreach[scala.Unit](((x: scala.Int) => if (x.<(3)) scala.Predef.println(x) else ())) Result: () -Original: scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int])).map[scala.Int](((a: scala.Int) => a.*(2))).map[java.lang.String](((b: scala.Int) => b.toString())) -Optimized: scala.List.apply[scala.Int]((1, 2, 3: scala.[scala.Int])).map[java.lang.String](((x: scala.Int) => { +Original: scala.List.apply[scala.Int](1, 2, 3).map[scala.Int](((a: scala.Int) => a.*(2))).map[java.lang.String](((b: scala.Int) => b.toString())) +Optimized: scala.List.apply[scala.Int](1, 2, 3).map[java.lang.String](((x: scala.Int) => { val x$1: scala.Int = x.*(2) x$1.toString() })) Result: List(2, 4, 6) -Original: scala.List.apply[scala.Int]((55, 67, 87: scala.[scala.Int])).map[scala.Char](((a: scala.Int) => a.toChar)).map[java.lang.String](((b: scala.Char) => b.toString())) -Optimized: scala.List.apply[scala.Int]((55, 67, 87: scala.[scala.Int])).map[java.lang.String](((x: scala.Int) => { +Original: scala.List.apply[scala.Int](55, 67, 87).map[scala.Char](((a: scala.Int) => a.toChar)).map[java.lang.String](((b: scala.Char) => b.toString())) +Optimized: scala.List.apply[scala.Int](55, 67, 87).map[java.lang.String](((x: scala.Int) => { val x$2: scala.Char = x.toChar x$2.toString() })) diff --git a/tests/run-macros/quoted-matching-docs-2.check b/tests/run-macros/quoted-matching-docs-2.check index a00f5528b2ab..942779221360 100644 --- a/tests/run-macros/quoted-matching-docs-2.check +++ b/tests/run-macros/quoted-matching-docs-2.check @@ -2,5 +2,5 @@ 6 12.+(Test.a) 17 -4.+(Macro_1$package.sum((Test.seq: scala.[scala.Int]))) +4.+(Macro_1$package.sum(Test.seq: _*)) 13 diff --git a/tests/run-macros/tasty-macro-positions.check b/tests/run-macros/tasty-macro-positions.check index 23c6a5fa3ffe..24dba3363a8e 100644 --- a/tests/run-macros/tasty-macro-positions.check +++ b/tests/run-macros/tasty-macro-positions.check @@ -11,7 +11,7 @@ quoted_2.scala:[217..222] quoted_2.scala:[232..245] ("abc": scala.Predef.String) quoted_2.scala:[255..269] -_root_.scala.StringContext.apply(("abc", "": scala.[scala.Predef.String])).s(("def": scala.[scala.Any])) +_root_.scala.StringContext.apply("abc", "").s("def") quoted_2.scala:[281..282] a quoted_2.scala:[293..294] @@ -25,7 +25,7 @@ quoted_2.scala:[329..334] quoted_2.scala:[345..358] ("abc": scala.Predef.String) quoted_2.scala:[369..383] -_root_.scala.StringContext.apply(("abc", "": scala.[scala.Predef.String])).s(("def": scala.[scala.Any])) +_root_.scala.StringContext.apply("abc", "").s("def") quoted_2.scala:[426..427] T quoted_2.scala:[438..444] From 1d64af510f1c1c122e75bec892594be4fa13a875 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 6 Jan 2020 11:01:09 +0100 Subject: [PATCH 2/3] Fix #7898: Handle annotation without symbols --- .../scala/tasty/reflect/SourceCodePrinter.scala | 2 +- tests/run-macros/i7898.check | 4 ++++ tests/run-macros/i7898/Macro_1.scala | 17 +++++++++++++++++ tests/run-macros/i7898/Test_2.scala | 7 +++++++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/run-macros/i7898.check create mode 100644 tests/run-macros/i7898/Macro_1.scala create mode 100644 tests/run-macros/i7898/Test_2.scala diff --git a/library/src/scala/tasty/reflect/SourceCodePrinter.scala b/library/src/scala/tasty/reflect/SourceCodePrinter.scala index 73b31c92c8ef..d1dc96024bee 100644 --- a/library/src/scala/tasty/reflect/SourceCodePrinter.scala +++ b/library/src/scala/tasty/reflect/SourceCodePrinter.scala @@ -1228,7 +1228,7 @@ class SourceCodePrinter[R <: Reflection & Singleton](val tasty: R)(syntaxHighlig def printAnnotation(annot: Term)(given elideThis: Option[Symbol]): Buffer = { val Annotation(ref, args) = annot - if (annot.symbol.owner.fullName == "scala.internal.quoted.showName") this + if (annot.symbol.exists && annot.symbol.owner.fullName == "scala.internal.quoted.showName") this else { this += "@" printTypeTree(ref) diff --git a/tests/run-macros/i7898.check b/tests/run-macros/i7898.check new file mode 100644 index 000000000000..64da4a308f63 --- /dev/null +++ b/tests/run-macros/i7898.check @@ -0,0 +1,4 @@ +scala.List.apply[scala.PartialFunction[scala.Int, scala.Predef.String]](((x$1: scala.Int) => (x$1: @scala.unchecked) match { + case 1 => + "x" +})) diff --git a/tests/run-macros/i7898/Macro_1.scala b/tests/run-macros/i7898/Macro_1.scala new file mode 100644 index 000000000000..d76d0567535e --- /dev/null +++ b/tests/run-macros/i7898/Macro_1.scala @@ -0,0 +1,17 @@ +import quoted._ +object Main { + + def myMacroImpl(body: Expr[_])(given qctx: QuoteContext): Expr[_] = { + import qctx.tasty.{_, given} + val bodyTerm = body.underlyingArgument.unseal + val showed = bodyTerm.show + '{ + println(${Expr(showed)}) + ${bodyTerm.seal} + } + } + + inline def myMacro(body: => Any) <: Any = ${ + myMacroImpl('body) + } +} diff --git a/tests/run-macros/i7898/Test_2.scala b/tests/run-macros/i7898/Test_2.scala new file mode 100644 index 000000000000..2bbc5b5741d7 --- /dev/null +++ b/tests/run-macros/i7898/Test_2.scala @@ -0,0 +1,7 @@ +object Test { + def main(args: Array[String]) = { + val _ = Main.myMacro(List[PartialFunction[Int, String]] { + case 1 => "x" + }) + } +} From 28231bfe05fe0422888626896eb99e0c158799ef Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 6 Jan 2020 11:55:27 +0100 Subject: [PATCH 3/3] Add maybeOwner to TASTy reflect --- .../dotc/tastyreflect/ReflectionCompilerInterface.scala | 1 + library/src/scala/tasty/reflect/CompilerInterface.scala | 5 ++++- library/src/scala/tasty/reflect/SourceCodePrinter.scala | 2 +- library/src/scala/tasty/reflect/SymbolOps.scala | 5 ++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 2d1e8f130b24..a2e69dc8d1eb 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1590,6 +1590,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend type Symbol = core.Symbols.Symbol def Symbol_owner(self: Symbol)(given Context): Symbol = self.owner + def Symbol_maybeOwner(self: Symbol)(given Context): Symbol = self.maybeOwner def Symbol_flags(self: Symbol)(given Context): Flags = self.flags diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index ea99f9f26aa9..8c07834c7618 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -1164,9 +1164,12 @@ trait CompilerInterface { */ type Symbol <: AnyRef - /** Owner of this symbol. The owner is the symbol in which this symbol is defined. */ + /** Owner of this symbol. The owner is the symbol in which this symbol is defined. Throws if this symbol does not have an owner. */ def Symbol_owner(self: Symbol)(given ctx: Context): Symbol + /** Owner of this symbol. The owner is the symbol in which this symbol is defined. Returns `NoSymbol` if this symbol does not have an owner. */ + def Symbol_maybeOwner(self: Symbol)(given ctx: Context): Symbol + /** Flags of this symbol */ def Symbol_flags(self: Symbol)(given ctx: Context): Flags diff --git a/library/src/scala/tasty/reflect/SourceCodePrinter.scala b/library/src/scala/tasty/reflect/SourceCodePrinter.scala index d1dc96024bee..b7ef83616a84 100644 --- a/library/src/scala/tasty/reflect/SourceCodePrinter.scala +++ b/library/src/scala/tasty/reflect/SourceCodePrinter.scala @@ -1228,7 +1228,7 @@ class SourceCodePrinter[R <: Reflection & Singleton](val tasty: R)(syntaxHighlig def printAnnotation(annot: Term)(given elideThis: Option[Symbol]): Buffer = { val Annotation(ref, args) = annot - if (annot.symbol.exists && annot.symbol.owner.fullName == "scala.internal.quoted.showName") this + if (annot.symbol.maybeOwner.fullName == "scala.internal.quoted.showName") this else { this += "@" printTypeTree(ref) diff --git a/library/src/scala/tasty/reflect/SymbolOps.scala b/library/src/scala/tasty/reflect/SymbolOps.scala index c7b7aea427aa..7b22c57e9dbd 100644 --- a/library/src/scala/tasty/reflect/SymbolOps.scala +++ b/library/src/scala/tasty/reflect/SymbolOps.scala @@ -16,9 +16,12 @@ trait SymbolOps extends Core { selfSymbolOps: FlagsOps => given symbolOps: extension (self: Symbol) { - /** Owner of this symbol. The owner is the symbol in which this symbol is defined */ + /** Owner of this symbol. The owner is the symbol in which this symbol is defined. Throws if this symbol does not have an owner. */ def owner(given ctx: Context): Symbol = internal.Symbol_owner(self) + /** Owner of this symbol. The owner is the symbol in which this symbol is defined. Returns `NoSymbol` if this symbol does not have an owner. */ + def maybeOwner(given ctx: Context): Symbol = internal.Symbol_maybeOwner(self) + /** Flags of this symbol */ def flags(given ctx: Context): Flags = internal.Symbol_flags(self)