Skip to content

SI-10154 Fix implicit search regression for term-owned objects #5654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,8 @@ trait Contexts { self: Analyzer =>
}

final def lookupCompanionOf(original: Symbol): Symbol = {
Copy link
Contributor

@adriaanm adriaanm Jan 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My head started spinning with indirection, so I figure I'll rubber-duck-review this by doing some inlining...

I tried to push all logic into lookupCompanionOf:

final def lookupCompanionOf(original: Symbol): Symbol =
  if (original == NoSymbol) NoSymbol else { // can we collapse the next few lines by using original.exists in the condition here?
    original.failIfStub()

    if (original.needsFlatClasses) original.info // use initialize() ?
    val flatOwnerInfo = original.owner.rawInfo

    // can we find it using the owner structure -- i.e., is it a member of some other symbol?
    val member =
      original match {
        case mcs: ModuleClassSymbol if mcs.module ne null => mcs.module
        case _ =>
          flatOwnerInfo.decl(original.name.companionName).suchThat(sym =>
            sym != original && (if (original.isClass) sym.isModule else sym.isClass) && sym.isCoDefinedWith(original)
          )
      }

    // can we decide which branch to take here directly rather than by trying the search?
    // i.e., is it a term-owned symbol??
    if (member == NoSymbol) 
      lookupScopeEntry(original) match {
        case null => NoSymbol
        case entry => entry.owner.lookupCompanion(original)
      }
    else member
  }

Copy link
Member Author

@retronym retronym Jan 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we decide which branch to take here directly rather than by trying the search? i.e., is it a term-owned symbol??

I think we also get into this code path for class-owned symbols where the class info is incomplete. So the check would need to be something like owner.isTerm || !owner.hasCompleteInfo

lookupScopeEntry(original) match {
if (original.isModuleClass) original.sourceModule
else lookupScopeEntry(original) match {
case null => NoSymbol
case entry => entry.owner.lookupCompanion(original)
}
Expand Down
11 changes: 11 additions & 0 deletions test/files/pos/t10154.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
trait Bar2[T]

object Test2 {
def wrap {
object Foo {
implicit def fooBar: Bar2[Foo.type] = ???
}

implicitly[Bar2[Foo.type]]
}
}
16 changes: 16 additions & 0 deletions test/files/pos/t10154b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import scala.language.existentials

class Bar[T]
class Test {
def method = {
object Foo {
implicit def x: Bar[Foo.type] = new Bar[Foo.type]
}
type T = Foo.type

{
object Foo
implicitly[Bar[T]]
}
}
}