Skip to content

Commit 190f34b

Browse files
authored
Merge pull request scala#5767 from milessabin/topic/i5766
Correct owner chains when mixing byname implicits and inlining
2 parents 36740bf + 98a4f14 commit 190f34b

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import core._
1010
import util.Spans._, Types._, Contexts._, Constants._, Names._, Flags._, NameOps._
1111
import Symbols._, StdNames._, Annotations._, Trees._, Symbols._
1212
import Decorators._, DenotTransformers._
13-
import collection.mutable
13+
import collection.{immutable, mutable}
1414
import util.{Property, SourceFile, NoSource}
1515
import NameKinds.{TempResultName, OuterSelectName}
1616
import typer.ConstFold
@@ -730,6 +730,25 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
730730
if (from == to) tree else loop(from, Nil, to :: Nil)
731731
}
732732

733+
/**
734+
* Set the owner of every definition in this tree which is not itself contained in this
735+
* tree to be `newowner`
736+
*/
737+
def changeNonLocalOwners(newOwner: Symbol)(implicit ctx: Context): Tree = {
738+
val ownerAcc = new TreeAccumulator[immutable.Set[Symbol]] {
739+
def apply(ss: immutable.Set[Symbol], tree: Tree)(implicit ctx: Context) = tree match {
740+
case tree: DefTree =>
741+
if (tree.symbol.exists) ss + tree.symbol.owner
742+
else ss
743+
case _ =>
744+
foldOver(ss, tree)
745+
}
746+
}
747+
val owners = ownerAcc(immutable.Set.empty[Symbol], tree).toList
748+
val newOwners = List.fill(owners.size)(newOwner)
749+
new TreeTypeMap(oldOwners = owners, newOwners = newOwners).apply(tree)
750+
}
751+
733752
/** After phase `trans`, set the owner of every definition in this tree that was formerly
734753
* owner by `from` to `to`.
735754
*/

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1577,7 +1577,7 @@ final class SearchRoot extends SearchHistory {
15771577
val nrhss = rhss.map(rhsMap(_))
15781578

15791579
val vdefs = (nsyms zip nrhss) map {
1580-
case (nsym, nrhs) => ValDef(nsym.asTerm, nrhs)
1580+
case (nsym, nrhs) => ValDef(nsym.asTerm, nrhs.changeNonLocalOwners(nsym))
15811581
}
15821582

15831583
val constr = ctx.newConstructor(classSym, Synthetic, Nil, Nil).entered

tests/pos/i5766.scala

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
object Test1 {
2+
trait Foo { def next: Foo }
3+
4+
inline implicit def foo(implicit loop: => Foo): Foo = new Foo { def next = loop }
5+
6+
def summon(implicit f: Foo) = ()
7+
summon
8+
}
9+
10+
object Test2 {
11+
trait Foo { def next: Bar }
12+
trait Bar { def next: Foo }
13+
14+
implicit def foo(implicit loop: => Bar): Foo = new Foo { def next = loop }
15+
inline implicit def bar(implicit loop: Foo): Bar = new Bar { def next = loop }
16+
17+
def summon(implicit f: Foo) = ()
18+
summon
19+
}
20+
21+
object Test3 {
22+
trait Foo { def next: Bar }
23+
trait Bar { def next: Baz }
24+
trait Baz { def next: Foo }
25+
26+
implicit def foo(implicit loop: Bar): Foo = new Foo { def next = loop }
27+
inline implicit def bar(implicit loop: Baz): Bar = new Bar { def next = loop }
28+
inline implicit def baz(implicit loop: => Foo): Baz = new Baz { def next = loop }
29+
30+
def summon(implicit f: Foo) = ()
31+
summon
32+
}

0 commit comments

Comments
 (0)