Skip to content

Commit 5df5552

Browse files
committed
Handle transparent implicits in implicit context
When adding implicit bindings to an implicit context of an inline body, we need to maintain the transparency of the implicits. The added implicit bindings are eliminated after inlining, since they are either unused or have been inlined.
1 parent c2de29d commit 5df5552

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,9 @@ object Flags {
560560
/** A transparent method */
561561
final val TransparentMethod = allOf(Transparent, Method)
562562

563+
/** A transparent implicit method */
564+
final val TransparentImplicitMethod = allOf(Transparent, Implicit, Method)
565+
563566
/** A transparent parameter */
564567
final val TransparentParam = allOf(Transparent, Param)
565568

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
793793
}
794794
countRefs.traverse(tree)
795795
for (binding <- bindings) countRefs.traverse(binding)
796+
797+
def retain(boundSym: Symbol) = {
798+
refCount.get(boundSym) match {
799+
case Some(x) => x > 1 || x == 1 && !boundSym.is(Method)
800+
case none => true
801+
}
802+
} && !boundSym.is(TransparentImplicitMethod)
803+
796804
val inlineBindings = new TreeMap {
797805
override def transform(t: Tree)(implicit ctx: Context) = t match {
798806
case t: RefTree =>
@@ -812,11 +820,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
812820
super.transform(t)
813821
}
814822
}
815-
def retain(binding: MemberDef) = refCount.get(binding.symbol) match {
816-
case Some(x) => x > 1 || x == 1 && !binding.symbol.is(Method)
817-
case none => true
818-
}
819-
val retained = bindings.filterConserve(retain)
823+
824+
val retained = bindings.filterConserve(binding => retain(binding.symbol))
820825
if (retained `eq` bindings) {
821826
(bindings, tree)
822827
}

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ object PrepareTransparent {
287287
!isLocalOrParam(tree.symbol, inlineMethod) &&
288288
!implicitRefTypes.contains(tree.tpe) =>
289289
if (tree.existsSubTree(t => isLocal(tree.symbol, inlineMethod)))
290-
ctx.warning("implicit reference $tree is dropped at inline site because it refers to local symbol(s)", tree.pos)
290+
ctx.warning(i"implicit reference $tree is dropped at inline site because it refers to local symbol(s)", tree.pos)
291291
else {
292292
implicitRefTypes += tree.tpe
293293
implicitRefs += tree
@@ -417,11 +417,23 @@ object PrepareTransparent {
417417
val localImplicit = iref.symbol.asTerm.copy(
418418
owner = inlineMethod,
419419
name = UniqueInlineName.fresh(iref.symbol.name.asTermName),
420-
flags = Implicit | Method | Stable,
420+
flags = Implicit | Method | Stable | iref.symbol.flags & (Transparent | Erased),
421421
info = iref.tpe.widen.ensureMethodic,
422422
coord = inlineMethod.pos).asTerm
423-
polyDefDef(localImplicit, tps => vrefss =>
423+
val idef = polyDefDef(localImplicit, tps => vrefss =>
424424
iref.appliedToTypes(tps).appliedToArgss(vrefss))
425+
if (localImplicit.is(Transparent)) {
426+
// produce a Body annotation for inlining
427+
def untype(tree: Tree): untpd.Tree = tree match {
428+
case Apply(fn, args) => untpd.cpy.Apply(tree)(untype(fn), args)
429+
case TypeApply(fn, args) => untpd.cpy.TypeApply(tree)(untype(fn), args)
430+
case _ => untpd.TypedSplice(tree)
431+
}
432+
val inlineBody = tpd.UntypedSplice(untype(idef.rhs)).withType(idef.rhs.tpe)
433+
inlining.println(i"body annot for $idef: $inlineBody")
434+
localImplicit.addAnnotation(ConcreteBodyAnnotation(inlineBody))
435+
}
436+
idef
425437
}
426438
val untpdSplice = tpd.UntypedSplice(addRefs.transform(original)).withType(typed.tpe)
427439
seq(implicitBindings, untpdSplice)

0 commit comments

Comments
 (0)