From c245e669aeaf03a2e67e8e6055d8e3e884802317 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 29 Apr 2022 17:04:05 +0200 Subject: [PATCH] Support inline methods calling private inline methods on `this` Fix #14042 --- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 7 +++++++ tests/pos/i14042.scala | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/pos/i14042.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index d097ed8dcc4e..fd54e4898ccc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -995,6 +995,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { inlinedFromOutside(TypeTree(t).withSpan(argSpan))(tree.span) case _ => tree } + case tree @ Select(qual: This, name) if tree.symbol.is(Private) && tree.symbol.isInlineMethod => + // This inline method refers to another (private) inline method (see tests/pos/i14042.scala). + // We insert upcast to access the private inline method once inlined. This makes the selection + // keep the symbol when re-typechecking in the InlineTyper. The method is inlined and hence no + // reference to a private method is kept at runtime. + cpy.Select(tree)(qual.asInstance(qual.tpe.widen), name) + case tree => tree }, oldOwners = inlinedMethod :: Nil, diff --git a/tests/pos/i14042.scala b/tests/pos/i14042.scala new file mode 100644 index 000000000000..d37d5251db9f --- /dev/null +++ b/tests/pos/i14042.scala @@ -0,0 +1,15 @@ +trait T { + inline def foo(handler: Int): Unit = + bar(handler) + + private inline def bar(handler: Int): Unit = () +} + +def test = new T { + foo(42) + this.foo(42) + def test = this.foo(42) +} + +def test2(t: T) = + t.foo(42)