Skip to content

Commit

Permalink
Merge pull request scala#5767 from milessabin/topic/i5766
Browse files Browse the repository at this point in the history
Correct owner chains when mixing byname implicits and inlining
  • Loading branch information
milessabin authored Jan 29, 2019
2 parents 36740bf + 98a4f14 commit 190f34b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
21 changes: 20 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import core._
import util.Spans._, Types._, Contexts._, Constants._, Names._, Flags._, NameOps._
import Symbols._, StdNames._, Annotations._, Trees._, Symbols._
import Decorators._, DenotTransformers._
import collection.mutable
import collection.{immutable, mutable}
import util.{Property, SourceFile, NoSource}
import NameKinds.{TempResultName, OuterSelectName}
import typer.ConstFold
Expand Down Expand Up @@ -730,6 +730,25 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
if (from == to) tree else loop(from, Nil, to :: Nil)
}

/**
* Set the owner of every definition in this tree which is not itself contained in this
* tree to be `newowner`
*/
def changeNonLocalOwners(newOwner: Symbol)(implicit ctx: Context): Tree = {
val ownerAcc = new TreeAccumulator[immutable.Set[Symbol]] {
def apply(ss: immutable.Set[Symbol], tree: Tree)(implicit ctx: Context) = tree match {
case tree: DefTree =>
if (tree.symbol.exists) ss + tree.symbol.owner
else ss
case _ =>
foldOver(ss, tree)
}
}
val owners = ownerAcc(immutable.Set.empty[Symbol], tree).toList
val newOwners = List.fill(owners.size)(newOwner)
new TreeTypeMap(oldOwners = owners, newOwners = newOwners).apply(tree)
}

/** After phase `trans`, set the owner of every definition in this tree that was formerly
* owner by `from` to `to`.
*/
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1577,7 +1577,7 @@ final class SearchRoot extends SearchHistory {
val nrhss = rhss.map(rhsMap(_))

val vdefs = (nsyms zip nrhss) map {
case (nsym, nrhs) => ValDef(nsym.asTerm, nrhs)
case (nsym, nrhs) => ValDef(nsym.asTerm, nrhs.changeNonLocalOwners(nsym))
}

val constr = ctx.newConstructor(classSym, Synthetic, Nil, Nil).entered
Expand Down
32 changes: 32 additions & 0 deletions tests/pos/i5766.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
object Test1 {
trait Foo { def next: Foo }

inline implicit def foo(implicit loop: => Foo): Foo = new Foo { def next = loop }

def summon(implicit f: Foo) = ()
summon
}

object Test2 {
trait Foo { def next: Bar }
trait Bar { def next: Foo }

implicit def foo(implicit loop: => Bar): Foo = new Foo { def next = loop }
inline implicit def bar(implicit loop: Foo): Bar = new Bar { def next = loop }

def summon(implicit f: Foo) = ()
summon
}

object Test3 {
trait Foo { def next: Bar }
trait Bar { def next: Baz }
trait Baz { def next: Foo }

implicit def foo(implicit loop: Bar): Foo = new Foo { def next = loop }
inline implicit def bar(implicit loop: Baz): Bar = new Bar { def next = loop }
inline implicit def baz(implicit loop: => Foo): Baz = new Baz { def next = loop }

def summon(implicit f: Foo) = ()
summon
}

0 comments on commit 190f34b

Please sign in to comment.