diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index 0667532797db..98aca1a98607 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -39,7 +39,6 @@ class Bridges(root: ClassSymbol)(implicit ctx: Context) { * before erasure, if the following conditions are satisfied. * * - `member` and other have different signatures - * - `member` is not inline * - there is not yet a bridge with the same name and signature in `root` * * The bridge has the erased info of `other` and forwards to `member`. @@ -48,7 +47,7 @@ class Bridges(root: ClassSymbol)(implicit ctx: Context) { def bridgeExists = bridgesScope.lookupAll(member.name).exists(bridge => bridgeTarget(bridge) == member && bridge.signature == other.signature) - if (!(member.is(Inline) || member.signature == other.signature || bridgeExists)) + if (!(member.signature == other.signature || bridgeExists)) addBridge(member, other) } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index c98e231d434e..6dd6f6e4850a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -351,6 +351,10 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { assert(argss.isEmpty) } + private def canElideThis(tpe: ThisType): Boolean = + prefix.tpe == tpe && ctx.owner.isContainedIn(tpe.cls) || + tpe.cls.is(Package) + /** Populate `thisProxy` and `paramProxy` as follows: * * 1a. If given type refers to a static this, thisProxy binds it to corresponding global reference, @@ -363,9 +367,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { * and MethodParams, not TypeRefs or TermRefs. */ private def registerType(tpe: Type): Unit = tpe match { - case tpe: ThisType - if !ctx.owner.isContainedIn(tpe.cls) && !tpe.cls.is(Package) && - !thisProxy.contains(tpe.cls) => + case tpe: ThisType if !canElideThis(tpe) && !thisProxy.contains(tpe.cls) => val proxyName = s"${tpe.cls.name}_this".toTermName val proxyType = tpe.asSeenFrom(prefix.tpe, meth.owner) thisProxy(tpe.cls) = newSym(proxyName, EmptyFlags, proxyType).termRef diff --git a/tests/run/i2895.scala b/tests/run/i2895.scala new file mode 100644 index 000000000000..2bc2037ebaa7 --- /dev/null +++ b/tests/run/i2895.scala @@ -0,0 +1,17 @@ +object Foo extends (Int => Int) { + inline def apply(x: Int): Int = impl(x) + def impl(x: Int): Int = x + 1 +} + +object Test { + + def test(foo: Foo.type): Int = foo(41) + + def test2(f: Int => Int): Int = f(41) + + def main(args: Array[String]): Unit = { + assert(test(Foo) == 42) + assert(test2(Foo) == 42) + } + +} diff --git a/tests/run/i2895a.scala b/tests/run/i2895a.scala new file mode 100644 index 000000000000..72f6dd3d61db --- /dev/null +++ b/tests/run/i2895a.scala @@ -0,0 +1,26 @@ + +trait Foo[A <: Foo[A]] { + + def next: A + + inline final def once: A = next + + def once1: A = once + + def twice: A = once.once +} + +trait Bar extends Foo[Bar] + +case object Bar0 extends Bar { def next = Bar1 } +case object Bar1 extends Bar { def next = Bar2 } +case object Bar2 extends Bar { def next = this } + +object Test { + + def main(args: Array[String]): Unit = { + assert(Bar0.once.once.toString == "Bar2") + assert(Bar0.twice.toString == "Bar2") + } +} +