Skip to content

Fix #5503: Keep outermost inlined call #5641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
9 changes: 6 additions & 3 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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) =>
Expand Down Expand Up @@ -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
}
}
Expand Down Expand Up @@ -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) =>
Expand Down
15 changes: 14 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -1123,14 +1126,24 @@ 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.
*/
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
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/Staging.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
16 changes: 16 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions compiler/test/dotc/pos-from-tasty.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions compiler/test/dotc/pos-test-pickling.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions compiler/test/dotc/run-from-tasty.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ implicitMatch.scala
typeclass-derivation1.scala
typeclass-derivation2.scala

# assertion failed: owner discrepancy for value a, expected: class <refinement>, found: class <refinement>
i4496a.scala
3 changes: 3 additions & 0 deletions compiler/test/dotc/run-test-pickling.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ t7374
tuples1.scala
tuples1a.scala
typeclass-derivation2.scala

# assertion failed: owner discrepancy for value a, expected: class <refinement>
i4496a.scala
11 changes: 11 additions & 0 deletions tests/pos/inline-import-b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

object Test {

@inline def locally[T](x: T): T = x

locally {
import Test._
val bool: Boolean = true
}

}
6 changes: 6 additions & 0 deletions tests/pos/inline-import-c/Predef2_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

object Predef2 {

@inline def locally[T](x: T): T = x

}
9 changes: 9 additions & 0 deletions tests/pos/inline-import-c/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

object Test {

Predef2.locally {
import Test._
val bool: Boolean = true
}

}
9 changes: 9 additions & 0 deletions tests/pos/inline-import.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

object Test {

locally {
import Test._
val bool: Boolean = true
}

}
Original file line number Diff line number Diff line change
@@ -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("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), 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("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), 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("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), 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()))))
Expand All @@ -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("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), 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("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), 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("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), 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()))))
Expand Down
6 changes: 6 additions & 0 deletions tests/run/tasty-outermost-call.check
Original file line number Diff line number Diff line change
@@ -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"))))
14 changes: 14 additions & 0 deletions tests/run/tasty-outermost-call/quoted_1.scala
Original file line number Diff line number Diff line change
@@ -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
}

}
21 changes: 21 additions & 0 deletions tests/run/tasty-outermost-call/quoted_2.scala
Original file line number Diff line number Diff line change
@@ -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)

}