diff --git a/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala index 25269c17e863..6593364a6283 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -107,8 +107,8 @@ class TreeTypeMap( val expr1 = tmap1.transform(expr) cpy.Block(blk)(stats1, expr1) case inlined @ Inlined(call, bindings, expanded) => - val (tmap1, bindings1) = transformDefs(bindings) - val expanded1 = tmap1.transform(expanded) + val (tmap1, bindings1) = transformDefs(bindings)(inlinedTreeContext) + val expanded1 = tmap1.transform(expanded)(inlineContext(call)) cpy.Inlined(inlined)(call, bindings1, expanded1) case cdef @ CaseDef(pat, guard, rhs) => val tmap = withMappedSyms(patVars(pat)) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 603e95af29ef..08a84d615ce0 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1201,6 +1201,9 @@ object Trees { */ protected def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx + /** Return a contexts marked as inside an Inlined tree */ + protected def inlinedTreeContext(implicit ctx: Context): Context = ctx + abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { self => def transform(tree: Tree)(implicit ctx: Context): Tree = { @@ -1254,7 +1257,7 @@ object Trees { case SeqLiteral(elems, elemtpt) => cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt)) case Inlined(call, bindings, expansion) => - cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(inlineContext(call))) + cpy.Inlined(tree)(call, transformSub(bindings)(inlinedTreeContext), transform(expansion)(inlineContext(call))) case TypeTree() => tree case SingletonTypeTree(ref) => @@ -1321,7 +1324,7 @@ object Trees { transform(trees).asInstanceOf[List[Tr]] protected def transformMoreCases(tree: Tree)(implicit ctx: Context): Tree = { - assert(ctx.reporter.errorsReported) + assert(ctx.reporter.errorsReported, tree) tree } } @@ -1380,7 +1383,7 @@ object Trees { case SeqLiteral(elems, elemtpt) => this(this(x, elems), elemtpt) case Inlined(call, bindings, expansion) => - this(this(x, bindings), expansion)(inlineContext(call)) + this(this(x, bindings)(inlinedTreeContext), expansion)(inlineContext(call)) case TypeTree() => x case SingletonTypeTree(ref) => diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 3fce069dd475..0df5f285418b 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1110,6 +1110,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** A key to be used in a context property that tracks enclosing inlined calls */ private val InlinedCalls = new Property.Key[List[Tree]] + /** A key to be used in a context property that tracks if the current tree is inside an Inlined tree */ + private val IsInInlinedTree = new Property.Key[Boolean] + /** Record an enclosing inlined call. * EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it. * We assume parameters are never nested inside parameters. @@ -1123,7 +1126,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { ts2 case _ => call :: oldIC } - ctx.fresh.setProperty(InlinedCalls, newIC) + ctx.fresh.setProperty(InlinedCalls, newIC).setProperty(IsInInlinedTree, true) + } + + /** Return a contexts marked as inside an Inlined tree */ + override def inlinedTreeContext(implicit ctx: Context): Context = { + if (isInInlinedTree) ctx + else ctx.fresh.setProperty(IsInInlinedTree, true) } /** All enclosing calls that are currently inlined, from innermost to outermost. @@ -1131,6 +1140,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def enclosingInlineds(implicit ctx: Context): List[Tree] = ctx.property(InlinedCalls).getOrElse(Nil) + /** Returns true iff this the current contexts is inside of an Inliend tree */ + def isInInlinedTree(implicit ctx: Context): Boolean = + ctx.property(IsInInlinedTree).getOrElse(false) + /** The source file where the symbol of the `inline` method referred to by `call` * is defined */ diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index 2eb28cda5b06..6385395b877a 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -14,6 +14,7 @@ import dotty.tools.dotc.core.Types.Type import dotty.tools.dotc.core.tasty.TreePickler.Hole import dotty.tools.dotc.core.tasty.{PositionPickler, TastyPickler, TastyPrinter, TastyString} import dotty.tools.dotc.core.tasty.TreeUnpickler.UnpickleMode +import dotty.tools.dotc.typer.Inliner import scala.quoted.Types._ import scala.quoted.Exprs._ diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 0203d438cbcc..d39072dd9f96 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -239,8 +239,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase super.transform(tree1) } case Inlined(call, bindings, expansion) if !call.isEmpty => - val callTrace = Inliner.inlineCallTrace(call.symbol, call.pos) - cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(inlineContext(call))) + val callTrace = + if (!isInInlinedTree) Inliner.outlineCallTrace(call) + else Inliner.inlineCallTrace(call.symbol, call.pos) + cpy.Inlined(tree)(callTrace, transformSub(bindings)(inlinedTreeContext), transform(expansion)(inlineContext(call))) case tree: Template => withNoCheckNews(tree.parents.flatMap(newPart)) { val templ1 = paramFwd.forwardParamAccessors(tree) diff --git a/compiler/src/dotty/tools/dotc/transform/Staging.scala b/compiler/src/dotty/tools/dotc/transform/Staging.scala index 6a04d9bc01fa..2f5fced729c1 100644 --- a/compiler/src/dotty/tools/dotc/transform/Staging.scala +++ b/compiler/src/dotty/tools/dotc/transform/Staging.scala @@ -620,6 +620,9 @@ class Staging extends MacroTransformWithImplicits { """.stripMargin, tree.rhs.pos) EmptyTree } + case tree @ Inlined(call, bindings, expansion) if !call.isEmpty && inQuote => + // Remove inline call (and keep trace) of quoted trees that will be pickled + super.transform(cpy.Inlined(tree)(Inliner.inlineCallTrace(call.symbol, call.pos), bindings, expansion)) case _ => markDef(tree) checkLevel(mapOverTree(enteredSyms)) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 12e8010995d4..1ccc56bbea31 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -158,6 +158,22 @@ object Inliner { */ def inlineCallTrace(callSym: Symbol, pos: Position)(implicit ctx: Context): Tree = Ident(callSym.topLevelClass.typeRef).withPos(pos) + + /** Reonstruct the original (non-inlined) call. + * Assumes that `inlineCallTrace` has not been used on any nested `Inlined`. + */ + def outlineCallTrace(call: Tree)(implicit ctx: Context): Tree = { + val outline = new TreeTypeMap( + oldOwners = ctx.owner :: Nil, newOwners = ctx.owner :: Nil, // To clone the definitions + treeMap = { + case tree @ Inlined(call, _, _) => + if (tree.tpe <:< call.tpe) call + else call.asInstance(tree.tpe) // add casts explicitly for inlined methods that refined their return type + case tree => tree + } + ) + outline.transform(call) + } } /** Produces an inlined version of `call` via its `inlined` method. diff --git a/compiler/test/dotc/pos-from-tasty.blacklist b/compiler/test/dotc/pos-from-tasty.blacklist index 64aff439e0f8..e8f927d00f80 100644 --- a/compiler/test/dotc/pos-from-tasty.blacklist +++ b/compiler/test/dotc/pos-from-tasty.blacklist @@ -20,3 +20,8 @@ default-super.scala i3050.scala i4006b.scala i4006c.scala + +# Inlined import generates wrong tasty or unreadable tasty. +# It only seams to happen if the inlined methods redefined in the DottyPredef +inline-import.scala +t8301b.scala diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index 90cd8dbf757e..67cf829d4218 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -10,3 +10,9 @@ t3249 t3486 t3612.scala typelevel0.scala + +# Inlined import generates wrong tasty or unreadable tasty. +# It only seams to happen if the inlined methods redefined in the DottyPredef +inline-import.scala +t8301b.scala +typedIdents diff --git a/compiler/test/dotc/run-from-tasty.blacklist b/compiler/test/dotc/run-from-tasty.blacklist index a2fbf589a9c8..42a6d8cea7bf 100644 --- a/compiler/test/dotc/run-from-tasty.blacklist +++ b/compiler/test/dotc/run-from-tasty.blacklist @@ -9,3 +9,5 @@ implicitMatch.scala typeclass-derivation1.scala typeclass-derivation2.scala +# assertion failed: owner discrepancy for value a, expected: class , found: class +i4496a.scala diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index aa1c42f1a07e..92e802a4d3e4 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -6,3 +6,6 @@ t7374 tuples1.scala tuples1a.scala typeclass-derivation2.scala + +# assertion failed: owner discrepancy for value a, expected: class +i4496a.scala diff --git a/tests/pos/inline-import-b.scala b/tests/pos/inline-import-b.scala new file mode 100644 index 000000000000..745598d8a562 --- /dev/null +++ b/tests/pos/inline-import-b.scala @@ -0,0 +1,11 @@ + +object Test { + + @inline def locally[T](x: T): T = x + + locally { + import Test._ + val bool: Boolean = true + } + +} diff --git a/tests/pos/inline-import-c/Predef2_1.scala b/tests/pos/inline-import-c/Predef2_1.scala new file mode 100644 index 000000000000..e24f456d388e --- /dev/null +++ b/tests/pos/inline-import-c/Predef2_1.scala @@ -0,0 +1,6 @@ + +object Predef2 { + + @inline def locally[T](x: T): T = x + +} diff --git a/tests/pos/inline-import-c/Test_2.scala b/tests/pos/inline-import-c/Test_2.scala new file mode 100644 index 000000000000..d30b53c6a585 --- /dev/null +++ b/tests/pos/inline-import-c/Test_2.scala @@ -0,0 +1,9 @@ + +object Test { + + Predef2.locally { + import Test._ + val bool: Boolean = true + } + +} diff --git a/tests/pos/inline-import.scala b/tests/pos/inline-import.scala new file mode 100644 index 000000000000..aaeefe0bb330 --- /dev/null +++ b/tests/pos/inline-import.scala @@ -0,0 +1,9 @@ + +object Test { + + locally { + import Test._ + val bool: Boolean = true + } + +} diff --git a/tests/run-custom-args/Yretain-trees/tasty-extractors-owners.check b/tests/run-custom-args/Yretain-trees/tasty-extractors-owners.check index 364296141757..1e1fb9b0a74b 100644 --- a/tests/run-custom-args/Yretain-trees/tasty-extractors-owners.check +++ b/tests/run-custom-args/Yretain-trees/tasty-extractors-owners.check @@ -1,5 +1,5 @@ foo -DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(TypeTree.Ident("Macros$")), Nil, Term.Typed(Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Inferred())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Inferred())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~"), TypeTree.Ident("Unit")))))) +DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(Term.Apply(Term.TypeApply(Term.Ident("printOwners"), List(TypeTree.Inferred())), List(Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))), Nil, Term.Typed(Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Inferred())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Inferred())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~"), TypeTree.Ident("Unit")))))) bar DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))) @@ -8,7 +8,7 @@ bar2 DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))) foo2 -DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(TypeTree.Ident("Macros$")), Nil, Term.Typed(Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Inferred())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Inferred())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~"), TypeTree.Ident("Unit")))))) +DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(Term.Apply(Term.TypeApply(Term.Ident("printOwners"), List(TypeTree.Inferred())), List(Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))), Nil, Term.Typed(Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Inferred())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Inferred())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~"), TypeTree.Ident("Unit")))))) baz ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))) diff --git a/tests/run/tasty-outermost-call.check b/tests/run/tasty-outermost-call.check new file mode 100644 index 000000000000..00058e35bcc5 --- /dev/null +++ b/tests/run/tasty-outermost-call.check @@ -0,0 +1,6 @@ +Term.Inlined(None, Nil, Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Literal(Constant.Int(54)), TypeTree.Ident("Int")))) +Term.Inlined(None, Nil, Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Literal(Constant.Int(8)), TypeTree.Ident("Int")))) +Term.Inlined(None, Nil, Term.Inlined(Some(TypeTree.Ident("Test$")), List(ValDef("i", TypeTree.Inferred(), Some(Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Literal(Constant.Int(54)), TypeTree.Ident("Int")))))), Term.Typed(Term.Apply(Term.Select(Term.Ident("i"), "+"), List(Term.Ident("i"))), TypeTree.Ident("Int")))) +Term.Inlined(None, Nil, Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Literal(Constant.Int(10)), TypeTree.Ident("Int"))), TypeTree.Ident("Int")))) +Term.Inlined(None, Nil, Term.Inlined(Some(TypeTree.Ident("Test$")), List(ValDef("i", TypeTree.Inferred(), Some(Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Literal(Constant.Int(54)), TypeTree.Ident("Int")))))), Term.Typed(Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Apply(Term.Select(Term.Ident("i"), "+"), List(Term.Ident("i"))), TypeTree.Ident("Int"))), TypeTree.Ident("Int")))) +Term.Inlined(None, Nil, Term.Inlined(Some(TypeTree.Ident("Test$")), List(ValDef("i", TypeTree.Inferred(), Some(Term.Inlined(Some(TypeTree.Ident("Test$")), List(ValDef("i", TypeTree.Inferred(), Some(Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Literal(Constant.Int(54)), TypeTree.Ident("Int")))))), Term.Typed(Term.Apply(Term.Select(Term.Ident("i"), "+"), List(Term.Ident("i"))), TypeTree.Ident("Int")))))), Term.Typed(Term.Inlined(Some(TypeTree.Ident("Test$")), Nil, Term.Typed(Term.Apply(Term.Select(Term.Ident("i"), "+"), List(Term.Ident("i"))), TypeTree.Ident("Int"))), TypeTree.Ident("Int")))) diff --git a/tests/run/tasty-outermost-call/quoted_1.scala b/tests/run/tasty-outermost-call/quoted_1.scala new file mode 100644 index 000000000000..c7360083304e --- /dev/null +++ b/tests/run/tasty-outermost-call/quoted_1.scala @@ -0,0 +1,14 @@ +import scala.quoted._ + +import scala.tasty._ + +object Macros { + + inline def show(x: => Any): String = ~impl('(x)) + + def impl(x: Expr[Any])(implicit reflect: Reflection): Expr[String] = { + import reflect._ + x.unseal.show.toExpr + } + +} diff --git a/tests/run/tasty-outermost-call/quoted_2.scala b/tests/run/tasty-outermost-call/quoted_2.scala new file mode 100644 index 000000000000..d7be2b085136 --- /dev/null +++ b/tests/run/tasty-outermost-call/quoted_2.scala @@ -0,0 +1,21 @@ + +import Macros._ + +object Test { + def main(args: Array[String]): Unit = { + println(show(foo0)) + println(show(foo1(4))) + println(show(foo1(foo0))) + println(show(foo2(5))) + println(show(foo2(foo0))) + println(show(foo2(foo1(foo0)))) + foo1(foo0) + foo2(foo0) + foo2(foo1(foo0)) + } + + inline def foo0: Int = 54 + inline def foo1(i: Int): Int = i + i + inline def foo2(i: Int): Int = foo1(i) + +}