Skip to content

Commit d46a5b9

Browse files
committed
Don't create inline accessors or proxies for local references
- Don't create an inline accessor wo a private field contained in the inlined method. - Don't create a this proxy to a class contained in the inlined method.
1 parent 22a6f4e commit d46a5b9

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,19 @@ object Inliner {
4040
private def makeInlineable(tree: Tree)(implicit ctx: Context) = {
4141

4242
/** A tree map which inserts accessors for all non-public term members accessed
43-
* from inlined code. Accesors are collected in the `accessors` buffer.
43+
* from inlined code. Accessors are collected in the `accessors` buffer.
4444
*/
4545
object addAccessors extends TreeMap {
4646
val inlineMethod = ctx.owner
4747
val accessors = new mutable.ListBuffer[MemberDef]
4848

49-
/** A definition needs an accessor if it is private, protected, or qualified private */
49+
/** A definition needs an accessor if it is private, protected, or qualified private
50+
* and it is not part of the tree that gets inlined. The latter test is implemented
51+
* by excluding all symbols properly contained in the inlined method.
52+
*/
5053
def needsAccessor(sym: Symbol)(implicit ctx: Context) =
51-
sym.is(AccessFlags) || sym.privateWithin.exists
54+
(sym.is(AccessFlags) || sym.privateWithin.exists) &&
55+
!sym.owner.isContainedIn(inlineMethod)
5256

5357
/** The name of the next accessor to be generated */
5458
def accessorName(implicit ctx: Context) = InlineAccessorName.fresh(inlineMethod.name.asTermName)
@@ -359,13 +363,15 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
359363

360364
private def canElideThis(tpe: ThisType): Boolean =
361365
prefix.tpe == tpe && ctx.owner.isContainedIn(tpe.cls) ||
366+
tpe.cls.isContainedIn(meth) ||
362367
tpe.cls.is(Package)
363368

364369
/** Populate `thisProxy` and `paramProxy` as follows:
365370
*
366371
* 1a. If given type refers to a static this, thisProxy binds it to corresponding global reference,
367-
* 1b. If given type refers to an instance this, create a proxy symbol and bind the thistype to
368-
* refer to the proxy. The proxy is not yet entered in `bindingsBuf` that will come later.
372+
* 1b. If given type refers to an instance this to a class that is not contained in the
373+
* inlined method, create a proxy symbol and bind the thistype to refer to the proxy.
374+
* The proxy is not yet entered in `bindingsBuf`; that will come later.
369375
* 2. If given type refers to a parameter, make `paramProxy` refer to the entry stored
370376
* in `paramNames` under the parameter's name. This roundabout way to bind parameter
371377
* references to proxies is done because we not known a priori what the parameter

tests/pos/i3130b.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
trait F { def f(): Int }
2+
class Outer {
3+
inline def inner: F = {
4+
class InnerClass(x: Int) extends F {
5+
def this() = this(3)
6+
def f() = x
7+
}
8+
new InnerClass(3)
9+
}
10+
}
11+
12+
object Test extends App {
13+
val o = new Outer
14+
assert(o.inner.f() == 3)
15+
}

0 commit comments

Comments
 (0)