Skip to content

Commit

Permalink
Merge pull request #1786 from retronym/ticket/6745-3
Browse files Browse the repository at this point in the history
SI-6745 Fix <init> lookup
  • Loading branch information
paulp committed Dec 26, 2012
2 parents b063de2 + 5b2990c commit 5b5635e
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 12 deletions.
45 changes: 33 additions & 12 deletions src/compiler/scala/tools/nsc/typechecker/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,12 @@ trait Contexts { self: Analyzer =>
case _ => LookupSucceeded(qual, sym)
}
)
def finishDefSym(sym: Symbol, pre0: Type): NameLookup =
if (requiresQualifier(sym))
finish(gen.mkAttributedQualifier(pre0), sym)
else
finish(EmptyTree, sym)

def isPackageOwnedInDifferentUnit(s: Symbol) = (
s.isDefinedInPackage && (
!currentRun.compiles(s)
Expand All @@ -816,17 +822,36 @@ trait Contexts { self: Analyzer =>

found1
}

def lookupInScope(scope: Scope) =
(scope lookupUnshadowedEntries name filter (e => qualifies(e.sym))).toList

def newOverloaded(owner: Symbol, pre: Type, entries: List[ScopeEntry]) =
logResult(s"!!! lookup overloaded")(owner.newOverloaded(pre, entries map (_.sym)))

// Constructor lookup should only look in the decls of the enclosing class
// not in the self-type, nor in the enclosing context, nor in imports (SI-4460, SI-6745)
if (name == nme.CONSTRUCTOR) return {
val enclClassSym = cx.enclClass.owner
val scope = cx.enclClass.prefix.baseType(enclClassSym).decls
val constructorSym = lookupInScope(scope) match {
case Nil => NoSymbol
case hd :: Nil => hd.sym
case entries => newOverloaded(enclClassSym, cx.enclClass.prefix, entries)
}
finishDefSym(constructorSym, cx.enclClass.prefix)
}

// cx.scope eq null arises during FixInvalidSyms in Duplicators
while (defSym == NoSymbol && (cx ne NoContext) && (cx.scope ne null)) {
pre = cx.enclClass.prefix
val entries = (cx.scope lookupUnshadowedEntries name filter (e => qualifies(e.sym))).toList
defSym = entries match {
case Nil => searchPrefix
case hd :: tl =>
pre = cx.enclClass.prefix
defSym = lookupInScope(cx.scope) match {
case Nil => searchPrefix
case entries @ (hd :: tl) =>
// we have a winner: record the symbol depth
symbolDepth = (cx.depth - cx.scope.nestingLevel) + hd.depth
if (tl.isEmpty) hd.sym
else logResult(s"!!! lookup overloaded")(cx.owner.newOverloaded(pre, entries map (_.sym)))
else newOverloaded(cx.owner, pre, entries)
}
if (!defSym.exists)
cx = cx.outer // push further outward
Expand Down Expand Up @@ -864,12 +889,8 @@ trait Contexts { self: Analyzer =>
}

// At this point only one or the other of defSym and impSym might be set.
if (defSym.exists) {
if (requiresQualifier(defSym))
finish(gen.mkAttributedQualifier(pre), defSym)
else
finish(EmptyTree, defSym)
}
if (defSym.exists)
finishDefSym(defSym, pre)
else if (impSym.exists) {
// We continue walking down the imports as long as the tail is non-empty, which gives us:
// imports == imp1 :: imp2 :: _
Expand Down
4 changes: 4 additions & 0 deletions test/files/neg/t4460a.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
t4460a.scala:6: error: called constructor's definition must precede calling constructor's definition
def this() = this() // was binding to Predef.<init> !!
^
one error found
7 changes: 7 additions & 0 deletions test/files/neg/t4460a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
trait A

class B(val x: Int) {
self: A =>

def this() = this() // was binding to Predef.<init> !!
}
4 changes: 4 additions & 0 deletions test/files/neg/t4460b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
t4460b.scala:7: error: called constructor's definition must precede calling constructor's definition
def this() = this() // was binding to Predef.<init> !!
^
one error found
9 changes: 9 additions & 0 deletions test/files/neg/t4460b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
trait A

class Outer() {
class B(val x: Int) {
self: A =>

def this() = this() // was binding to Predef.<init> !!
}
}
7 changes: 7 additions & 0 deletions test/files/neg/t4460c.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
t4460c.scala:4: error: overloaded method constructor B with alternatives:
(a: String)B <and>
(x: Int)B
cannot be applied to ()
def this(a: String) = this()
^
one error found
7 changes: 7 additions & 0 deletions test/files/neg/t4460c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class B(val x: Int) {
self: A =>

def this(a: String) = this()
}

class A()
4 changes: 4 additions & 0 deletions test/files/pos/t6745.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Bar(val i: Int) {
self: Any with AnyRef =>
def this() = this(0)
}

0 comments on commit 5b5635e

Please sign in to comment.