Skip to content

Commit ceef996

Browse files
oderskyallanrenucci
authored andcommitted
Bring back typed inliner
1 parent 3aed2e4 commit ceef996

File tree

8 files changed

+85
-26
lines changed

8 files changed

+85
-26
lines changed

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ object Contexts {
309309

310310
/** Is this a context for typechecking an inlined body? */
311311
def isInlineContext: Boolean =
312-
typer.isInstanceOf[Inliner#InlineTyper]
312+
typer.isInstanceOf[Inliner#InlineTyping]
313313

314314
/** The next outer context whose tree is a template or package definition
315315
* Note: Currently unused

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,9 @@ class TreePickler(pickler: TastyPickler) {
655655
// a different toplevel class, it is impossible to pickle a reference to it.
656656
// Such annotations will be reconstituted when unpickling the child class.
657657
// See tests/pickling/i3149.scala
658-
case _ => false
658+
case _ =>
659+
if (Inliner.typedInline) ann.symbol == defn.BodyAnnot // inline bodies are reconstituted automatically when unpickling
660+
else false
659661
}
660662

661663
def pickleAnnotation(owner: Symbol, ann: Annotation)(implicit ctx: Context) =

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import core.quoted.PickledQuotes
2424
import scala.quoted
2525
import scala.quoted.Types.TreeType
2626
import scala.quoted.Exprs.TastyTreeExpr
27+
import typer.Inliner.typedInline
2728

2829
import scala.annotation.internal.sharable
2930

@@ -556,6 +557,12 @@ class TreeUnpickler(reader: TastyReader,
556557
sym.completer.withDecls(newScope)
557558
forkAt(templateStart).indexTemplateParams()(localContext(sym))
558559
}
560+
else if (typedInline && sym.isInlineMethod)
561+
sym.addAnnotation(LazyBodyAnnotation { ctx0 =>
562+
implicit val ctx: Context = localContext(sym)(ctx0).addMode(Mode.ReadPositions)
563+
// avoids space leaks by not capturing the current context
564+
forkAt(rhsStart).readTerm()
565+
})
559566
goto(start)
560567
sym
561568
}
@@ -637,8 +644,10 @@ class TreeUnpickler(reader: TastyReader,
637644
val lazyAnnotTree = readLaterWithOwner(end, rdr => ctx => rdr.readTerm()(ctx))
638645

639646
owner =>
640-
if (tp.isRef(defn.BodyAnnot))
647+
if (tp.isRef(defn.BodyAnnot)) {
648+
assert(!typedInline)
641649
LazyBodyAnnotation(implicit ctx => lazyAnnotTree(owner).complete)
650+
}
642651
else
643652
Annotation.deferredSymAndTree(
644653
implicit ctx => tp.typeSymbol,
@@ -741,6 +750,11 @@ class TreeUnpickler(reader: TastyReader,
741750
def readRhs(implicit ctx: Context) =
742751
if (nothingButMods(end))
743752
EmptyTree
753+
else if (sym.isInlineMethod && typedInline)
754+
// The body of an inline method is stored in an annotation, so no need to unpickle it again
755+
new Trees.Lazy[Tree] {
756+
def complete(implicit ctx: Context) = typer.Inliner.bodyToInline(sym)
757+
}
744758
else
745759
readLater(end, rdr => ctx => rdr.readTerm()(ctx.retractMode(Mode.InSuperCall)))
746760

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

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import ast.TreeInfo
3434
object Inliner {
3535
import tpd._
3636

37+
val typedInline = true
38+
3739
/** A key to be used in a context property that provides a map from enclosing implicit
3840
* value bindings to their right hand sides.
3941
*/
@@ -382,7 +384,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
382384
// Compute bindings for all this-proxies, appending them to bindingsBuf
383385
computeThisBindings()
384386

385-
val inlineTyper = new InlineTyper
387+
val inlineTyper =
388+
if (typedInline) new InlineReTyper else new TransparentTyper
389+
386390
val inlineCtx = inlineContext(call).fresh.setTyper(inlineTyper).setNewScope
387391

388392
// A tree type map to prepare the inlined body for typechecked.
@@ -857,7 +861,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
857861
* 4. Make sure inlined code is type-correct.
858862
* 5. Make sure that the tree's typing is idempotent (so that future -Ycheck passes succeed)
859863
*/
860-
class InlineTyper extends Typer {
864+
trait InlineTyping extends Typer {
861865
import reducer._
862866

863867
override def ensureAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = {
@@ -873,12 +877,6 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
873877
super.ensureAccessible(tpe, superAccess, pos)
874878
}
875879

876-
override def typedTypedSplice(tree: untpd.TypedSplice)(implicit ctx: Context): Tree =
877-
reduceProjection(tryInline(tree.splice) `orElse` super.typedTypedSplice(tree))
878-
879-
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context) =
880-
constToLiteral(reduceProjection(super.typedSelect(tree, pt)))
881-
882880
override def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context) =
883881
typed(tree.cond, defn.BooleanType) match {
884882
case cond1 @ ConstantValue(b: Boolean) =>
@@ -895,6 +893,19 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
895893
super.typedIf(if1, pt)
896894
}
897895

896+
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context) =
897+
constToLiteral(betaReduce(super.typedApply(tree, pt)))
898+
}
899+
900+
private class TransparentTyper extends Typer with InlineTyping {
901+
import reducer._
902+
903+
override def typedTypedSplice(tree: untpd.TypedSplice)(implicit ctx: Context): Tree =
904+
reduceProjection(tryInline(tree.splice) `orElse` super.typedTypedSplice(tree))
905+
906+
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context) =
907+
constToLiteral(reduceProjection(super.typedSelect(tree, pt)))
908+
898909
override def typedMatchFinish(tree: untpd.Match, sel: Tree, selType: Type, pt: Type)(implicit ctx: Context) = tree match {
899910
case _: untpd.InlineMatch if !ctx.owner.isInlineMethod => // don't reduce match of nested inline method yet
900911
reduceInlineMatch(sel, sel.tpe, tree.cases, this) match {
@@ -916,10 +927,24 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
916927
super.typedMatchFinish(tree, sel, selType, pt)
917928
}
918929

919-
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context) =
920-
constToLiteral(betaReduce(super.typedApply(tree, pt)))
930+
override def newLikeThis: Typer = new TransparentTyper
931+
}
932+
933+
private class InlineReTyper extends ReTyper with InlineTyping {
934+
import reducer._
935+
936+
override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context) =
937+
tryInline(tree.asInstanceOf[tpd.Tree]) `orElse` super.typedIdent(tree, pt)
938+
939+
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
940+
assert(tree.hasType, tree)
941+
val qual1 = typed(tree.qualifier, selectionProto(tree.name, pt, this))
942+
val res = untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt)
943+
ensureAccessible(res.tpe, tree.qualifier.isInstanceOf[untpd.Super], tree.pos)
944+
res
945+
}
921946

922-
override def newLikeThis: Typer = new InlineTyper
947+
override def newLikeThis: Typer = new InlineReTyper
923948
}
924949

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

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,10 @@ object PrepareInlineable {
243243
val typedBody =
244244
if (ctx.reporter.hasErrors) rawBody
245245
else ctx.compilationUnit.inlineAccessors.makeInlineable(rawBody)
246-
if (inlined.isInlineMethod)
247-
checkInlineMethod(inlined, typedBody)
248-
val inlineableBody = addReferences(inlined, originalBody, typedBody)
246+
checkInlineMethod(inlined, typedBody)
247+
val inlineableBody =
248+
if (Inliner.typedInline) typedBody
249+
else addReferences(inlined, originalBody, typedBody)
249250
inlining.println(i"Body to inline for $inlined: $inlineableBody")
250251
inlineableBody
251252
})

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ object ProtoTypes {
8181
* achieved by replacing expected type parameters with wildcards.
8282
*/
8383
def constrainResult(meth: Symbol, mt: Type, pt: Type)(implicit ctx: Context): Boolean =
84-
if (Inliner.isInlineable(meth)) {
84+
if (Inliner.isInlineable(meth) && !Inliner.typedInline) {
8585
constrainResult(mt, wildApprox(pt))
8686
true
8787
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class ReTyper extends Typer with ReChecking {
117117
throw ex
118118
}
119119

120+
override def inlineExpansion(mdef: DefDef)(implicit ctx: Context): Tree = mdef
121+
120122
override def checkVariance(tree: Tree)(implicit ctx: Context) = ()
121123
override def inferView(from: Tree, to: Type)(implicit ctx: Context): Implicits.SearchResult =
122124
Implicits.NoMatchingImplicitsFailure

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ class Typer extends Namer
711711
}
712712

713713
def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = track("typedIf") {
714-
if (tree.isInstanceOf[untpd.InlineIf]) checkInInlineContext("inline if", tree.pos)
714+
if (tree.isInstanceOf[untpd.InlineIf] && !Inliner.typedInline) checkInInlineContext("inline if", tree.pos)
715715
val cond1 = typed(tree.cond, defn.BooleanType)
716716
val thenp2 :: elsep2 :: Nil = harmonic(harmonize) {
717717
val thenp1 = typed(tree.thenp, pt.notApplied)
@@ -981,7 +981,7 @@ class Typer extends Namer
981981
val sel1 = id.withType(defn.ImplicitScrutineeTypeRef)
982982
typedMatchFinish(tree, sel1, sel1.tpe, pt)
983983
case _ =>
984-
if (tree.isInstanceOf[untpd.InlineMatch]) checkInInlineContext("inline match", tree.pos)
984+
if (tree.isInstanceOf[untpd.InlineMatch] && !Inliner.typedInline) checkInInlineContext("inline match", tree.pos)
985985
val sel1 = typedExpr(tree.selector)
986986
val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen
987987
typedMatchFinish(tree, sel1, selType, pt)
@@ -1999,10 +1999,17 @@ class Typer extends Namer
19991999
case none =>
20002000
typed(mdef) match {
20012001
case mdef1: DefDef if Inliner.hasBodyToInline(mdef1.symbol) =>
2002-
assert(mdef1.symbol.isInlineMethod, mdef.symbol)
2003-
Inliner.bodyToInline(mdef1.symbol) // just make sure accessors are computed,
2004-
buf += mdef1 // but keep original definition, since inline-expanded code
2005-
// is pickled in this case.
2002+
if (Inliner.typedInline) {
2003+
buf += inlineExpansion(mdef1)
2004+
// replace body with expansion, because it will be used as inlined body
2005+
// from separately compiled files - the original BodyAnnotation is not kept.
2006+
}
2007+
else {
2008+
assert(mdef1.symbol.isInlineMethod, mdef.symbol)
2009+
Inliner.bodyToInline(mdef1.symbol) // just make sure accessors are computed,
2010+
buf += mdef1 // but keep original definition, since inline-expanded code
2011+
// is pickled in this case.
2012+
}
20062013
case mdef1 =>
20072014
import untpd.modsDeco
20082015
mdef match {
@@ -2034,6 +2041,13 @@ class Typer extends Namer
20342041
checkEnumCompanions(traverse(stats)(localCtx), enumContexts)
20352042
}
20362043

2044+
/** Given an inline method `mdef`, the method rewritten so that its body
2045+
* uses accessors to access non-public members.
2046+
* Overwritten in Retyper to return `mdef` unchanged.
2047+
*/
2048+
protected def inlineExpansion(mdef: DefDef)(implicit ctx: Context): Tree =
2049+
tpd.cpy.DefDef(mdef)(rhs = Inliner.bodyToInline(mdef.symbol))
2050+
20372051
def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree =
20382052
typed(tree, pt)(ctx retractMode Mode.PatternOrTypeBits)
20392053
def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = // todo: retract mode between Type and Pattern?
@@ -2445,8 +2459,9 @@ class Typer extends Namer
24452459
else if (Inliner.isInlineable(tree) &&
24462460
!ctx.settings.YnoInline.value &&
24472461
!ctx.isAfterTyper &&
2448-
!ctx.reporter.hasErrors) {
2449-
tree.tpe <:< wildApprox(pt)
2462+
!ctx.reporter.hasErrors &&
2463+
(!Inliner.typedInline || tree.tpe <:< pt)) {
2464+
if (!Inliner.typedInline) tree.tpe <:< wildApprox(pt)
24502465
readaptSimplified(Inliner.inlineCall(tree, pt))
24512466
}
24522467
else if (tree.tpe <:< pt) {

0 commit comments

Comments
 (0)