Skip to content

Commit 53d69cd

Browse files
committed
Refactor inlining condition logic
1 parent aee1555 commit 53d69cd

File tree

5 files changed

+41
-36
lines changed

5 files changed

+41
-36
lines changed

compiler/src/dotty/tools/dotc/transform/Inlining.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class Inlining extends MacroTransform {
8787
else super.transform(tree)
8888
case _: Typed | _: Block =>
8989
super.transform(tree)
90-
case _ if Inliner.isInlineable(tree) && !tree.tpe.widen.isInstanceOf[MethodOrPoly] && StagingContext.level == 0 =>
90+
case _ if Inliner.needsInlining(tree) =>
9191
val tree1 = super.transform(tree)
9292
if tree1.tpe.isError then tree1
9393
else Inliner.inlineCall(tree1)

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,29 @@ object Inliner {
5252
def inInlineMethod(using Context): Boolean =
5353
ctx.owner.ownersIterator.exists(_.isInlineMethod)
5454

55-
/** Should call to method `meth` be inlined in this context? */
55+
/** Can a call to method `meth` be inlined? */
5656
def isInlineable(meth: Symbol)(using Context): Boolean =
5757
meth.is(Inline) && meth.hasAnnotation(defn.BodyAnnot) && !inInlineMethod
5858

5959
/** Should call be inlined in this context? */
60-
def isInlineable(tree: Tree)(using Context): Boolean = tree match {
61-
case Block(_, expr) => isInlineable(expr)
62-
case _ => isInlineable(tree.symbol) && !tree.tpe.isInstanceOf[MethodOrPoly]
60+
def needsInlining(tree: Tree)(using Context): Boolean = tree match {
61+
case Block(_, expr) => needsInlining(expr)
62+
case _ =>
63+
isInlineable(tree.symbol)
64+
&& !tree.tpe.widenTermRefExpr.isInstanceOf[MethodOrPoly]
65+
&& StagingContext.level == 0
66+
&& (
67+
ctx.phase == Phases.inliningPhase
68+
|| (ctx.phase == Phases.typerPhase && needsTransparentInlining(tree))
69+
)
70+
&& !ctx.typer.hasInliningErrors
6371
}
6472

73+
private def needsTransparentInlining(tree: Tree)(using Context): Boolean =
74+
tree.symbol.is(Transparent)
75+
|| ctx.mode.is(Mode.ForceInline)
76+
|| ctx.settings.YforceInlineWhileTyping.value
77+
6578
/** Try to inline a call to an inline method. Fail with error if the maximal
6679
* inline depth is exceeded.
6780
*
@@ -283,14 +296,15 @@ object Inliner {
283296
assert(tree.symbol == defn.CompiletimeTesting_typeChecks || tree.symbol == defn.CompiletimeTesting_typeCheckErrors)
284297
def stripTyped(t: Tree): Tree = t match {
285298
case Typed(t2, _) => stripTyped(t2)
299+
case Block(Nil, t2) => stripTyped(t2)
286300
case Inlined(_, Nil, t2) => stripTyped(t2)
287301
case _ => t
288302
}
289303

290304
val Apply(_, codeArg :: Nil) = tree
291305
val codeArg1 = stripTyped(codeArg.underlying)
292306
val underlyingCodeArg =
293-
if Inliner.isInlineable(codeArg1) then stripTyped(Inliner.inlineCall(codeArg1))
307+
if Inliner.isInlineable(codeArg1.symbol) then stripTyped(Inliner.inlineCall(codeArg1))
294308
else codeArg1
295309

296310
ConstFold(underlyingCodeArg).tpe.widenTermRefExpr match {
@@ -1240,9 +1254,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
12401254
super.ensureAccessible(tpe, superAccess, pos)
12411255
}
12421256

1257+
override def typed(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree =
1258+
val tree1 = super.typed(tree, pt)
1259+
if Inliner.needsInlining(tree1)
1260+
then Inliner.inlineCall(tree1)
1261+
else tree1
1262+
12431263
override def typedIdent(tree: untpd.Ident, pt: Type)(using Context): Tree =
1244-
val tree1 = tryInlineArg(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt)
1245-
inlineIfIsNestedInlineCall(tree1)
1264+
tryInlineArg(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt)
12461265

12471266
override def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = {
12481267
assert(tree.hasType, tree)
@@ -1254,7 +1273,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
12541273
else
12551274
val res = resMaybeReduced
12561275
ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.srcPos)
1257-
inlineIfIsNestedInlineCall(res)
1276+
res
12581277
}
12591278

12601279
override def typedIf(tree: untpd.If, pt: Type)(using Context): Tree =
@@ -1287,18 +1306,18 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
12871306
val res = constToLiteral(betaReduce(super.typedApply(tree, pt))) match {
12881307
case res: Apply if res.symbol == defn.QuotedRuntime_exprSplice
12891308
&& level == 0
1290-
&& !suppressInline =>
1309+
&& !hasInliningErrors =>
12911310
val expanded = expandMacro(res.args.head, tree.span)
12921311
typedExpr(expanded) // Inline calls and constant fold code generated by the macro
12931312
case res =>
1294-
inlineIfIsNestedInlineCall(res)
1313+
res
12951314
}
12961315
if res.symbol == defn.QuotedRuntime_exprQuote then
12971316
ctx.compilationUnit.needsQuotePickling = true
12981317
res
12991318

13001319
override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(using Context): Tree =
1301-
inlineIfIsNestedInlineCall(constToLiteral(betaReduce(super.typedTypeApply(tree, pt))))
1320+
constToLiteral(betaReduce(super.typedTypeApply(tree, pt)))
13021321

13031322
override def typedMatch(tree: untpd.Match, pt: Type)(using Context): Tree =
13041323
val tree1 =
@@ -1354,19 +1373,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
13541373

13551374
override def newLikeThis: Typer = new InlineTyper(initialErrorCount)
13561375

1357-
/** Suppress further inlining if this inline typer has already issued errors */
1358-
override def suppressInline(using Context) =
1359-
ctx.reporter.errorCount > initialErrorCount || super.suppressInline
1360-
1361-
private def inlineIfIsNestedInlineCall(tree: Tree)(using Context): Tree =
1362-
if
1363-
!suppressInline &&
1364-
!tree.tpe.widenTermRefExpr.isInstanceOf[MethodOrPoly] &&
1365-
Inliner.isInlineable(tree) &&
1366-
StagingContext.level == 0 &&
1367-
(ctx.isAfterTyper || tree.symbol.is(Transparent) || ctx.mode.is(Mode.ForceInline) || ctx.settings.YforceInlineWhileTyping.value)
1368-
then Inliner.inlineCall(tree)
1369-
else tree
1376+
/** True if this inline typer has already issued errors */
1377+
override def hasInliningErrors(using Context) = ctx.reporter.errorCount > initialErrorCount
1378+
13701379
}
13711380

13721381
/** Drop any side-effect-free bindings that are unused in expansion or other reachable bindings.

compiler/src/dotty/tools/dotc/typer/ReTyper.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class ReTyper extends Typer with ReChecking {
118118
try super.typedUnadapted(tree, pt, locked)
119119
catch {
120120
case NonFatal(ex) =>
121-
if ctx.isAfterTyper && ctx.phase != Phases.inliningPhase then
121+
if ctx.phase != Phases.typerPhase && ctx.phase != Phases.inliningPhase then
122122
println(i"exception while typing $tree of class ${tree.getClass} # ${tree.uniqueId}")
123123
throw ex
124124
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,9 @@ class Typer extends Namer
865865
*/
866866
val arg1 = pt match {
867867
case AppliedType(a, typ :: Nil) if ctx.isJava && a.isRef(defn.ArrayClass) =>
868-
tryAlternatively { typed(tree.arg, pt) } {
868+
tryAlternatively { typed(tree.arg, pt) } {
869869
val elemTp = untpd.TypedSplice(TypeTree(typ))
870-
typed(untpd.JavaSeqLiteral(tree.arg :: Nil, elemTp), pt)
870+
typed(untpd.JavaSeqLiteral(tree.arg :: Nil, elemTp), pt)
871871
}
872872
case _ => typed(tree.arg, pt)
873873
}
@@ -3406,11 +3406,7 @@ class Typer extends Namer
34063406
val meth = methPart(tree).symbol
34073407
if meth.isAllOf(DeferredInline) && !Inliner.inInlineMethod then
34083408
errorTree(tree, i"Deferred inline ${meth.showLocated} cannot be invoked")
3409-
else if
3410-
Inliner.isInlineable(tree) &&
3411-
!suppressInline &&
3412-
StagingContext.level == 0 &&
3413-
(tree.symbol.is(Transparent) || ctx.settings.YforceInlineWhileTyping.value)
3409+
else if Inliner.needsInlining(tree)
34143410
then
34153411
tree.tpe <:< wildApprox(pt)
34163412
val errorCount = ctx.reporter.errorCount
@@ -3734,8 +3730,8 @@ class Typer extends Namer
37343730
}
37353731
}
37363732

3737-
// Overridden in InlineTyper
3738-
def suppressInline(using Context): Boolean = ctx.isAfterTyper && ctx.phase != Phases.inliningPhase
3733+
/** True if this inline typer has already issued errors */
3734+
def hasInliningErrors(using Context): Boolean = false
37393735

37403736
/** Does the "contextuality" of the method type `methType` match the one of the prototype `pt`?
37413737
* This is the case if

tests/pos-custom-args/erased/i7878.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ object Boom {
22
import scala.compiletime._
33
trait Fail[A <: Int, B <: Int]
44

5-
erased inline given fail[X <: Int, Y <: Int]: Fail[X, Y] = {
5+
erased transparent inline given fail[X <: Int, Y <: Int]: Fail[X, Y] = {
66
scala.compiletime.summonFrom {
77
case t: Fail[X, y] if constValue[y] < constValue[Y] => ???
88
}

0 commit comments

Comments
 (0)