@@ -758,14 +758,10 @@ trait Contexts { self: Analyzer =>
758758 def lookupSymbol (name : Name , qualifies : Symbol => Boolean ): NameLookup = {
759759 var lookupError : NameLookup = null // set to non-null if a definite error is encountered
760760 var inaccessible : NameLookup = null // records inaccessible symbol for error reporting in case none is found
761- var defEntry : ScopeEntry = null // the scope entry of defSym, if defined in a local scope
762761 var defSym : Symbol = NoSymbol // the directly found symbol
763762 var pre : Type = NoPrefix // the prefix type of defSym, if a class member
764- var cx : Context = this
765- var needsQualifier = false // working around package object overloading bug
766-
767- def defEntrySymbol = if (defEntry eq null ) NoSymbol else defEntry.sym
768- def localScopeDepth = if (defEntry eq null ) 0 else cx.scope.nestingLevel - defEntry.owner.nestingLevel
763+ var cx : Context = this // the context under consideration
764+ var symbolDepth : Int = - 1 // the depth of the directly found symbol
769765
770766 def finish (qual : Tree , sym : Symbol ): NameLookup = (
771767 if (lookupError ne null ) lookupError
@@ -781,31 +777,14 @@ trait Contexts { self: Analyzer =>
781777 || unit.exists && s.sourceFile != unit.source.file
782778 )
783779 )
784- def requiresQualifier (s : Symbol ) = needsQualifier || (
780+ def requiresQualifier (s : Symbol ) = (
785781 s.owner.isClass
786782 && ! s.owner.isPackageClass
787783 && ! s.isTypeParameterOrSkolem
788784 )
789785 def lookupInPrefix (name : Name ) = pre member name filter qualifies
790786 def accessibleInPrefix (s : Symbol ) = isAccessible(s, pre, superAccess = false )
791787
792- def correctForPackageObject (sym : Symbol ): Symbol = {
793- if (sym.isTerm && isInPackageObject(sym, pre.typeSymbol)) {
794- val sym1 = lookupInPrefix(sym.name)
795- if ((sym1 eq NoSymbol ) || (sym eq sym1)) sym else {
796- needsQualifier = true
797- log(s """
798- | !!! Overloaded package object member resolved incorrectly.
799- | prefix: $pre
800- | Discarded: ${sym.defString}
801- | Using: ${sym1.defString}
802- """ .stripMargin)
803- sym1
804- }
805- }
806- else sym
807- }
808-
809788 def searchPrefix = {
810789 cx = cx.enclClass
811790 val found0 = lookupInPrefix(name)
@@ -817,31 +796,35 @@ trait Contexts { self: Analyzer =>
817796 }
818797 // cx.scope eq null arises during FixInvalidSyms in Duplicators
819798 while (defSym == NoSymbol && (cx ne NoContext ) && (cx.scope ne null )) {
820- pre = cx.enclClass.prefix
821- // !!! FIXME. This call to lookupEntry is at the root of all the
822- // bad behavior with overloading in package objects. lookupEntry
823- // just takes the first symbol it finds in scope, ignoring the rest.
824- // When a selection on a package object arrives here, the first
825- // overload is always chosen. "correctForPackageObject" exists to
826- // undo that decision. Obviously it would be better not to do it in
827- // the first place; however other things seem to be tied to obtaining
828- // that ScopeEntry, specifically calculating the nesting depth.
829- defEntry = cx.scope lookupEntry name
830- defSym = defEntrySymbol filter qualifies map correctForPackageObject orElse searchPrefix
799+ pre = cx.enclClass.prefix
800+ val entries = (cx.scope lookupUnshadowedEntries name filter (e => qualifies(e.sym))).toList
801+ defSym = entries match {
802+ case Nil => searchPrefix
803+ case hd :: tl =>
804+ // we have a winner: record the symbol depth
805+ symbolDepth = (cx.depth - cx.scope.nestingLevel) + hd.depth
806+ if (tl.isEmpty) hd.sym
807+ else logResult(s " !!! lookup overloaded " )(cx.owner.newOverloaded(pre, entries map (_.sym)))
808+ }
831809 if (! defSym.exists)
832- cx = cx.outer
810+ cx = cx.outer // push further outward
833811 }
812+ if (symbolDepth < 0 )
813+ symbolDepth = cx.depth
834814
835- val symbolDepth = cx.depth - localScopeDepth
836815 var impSym : Symbol = NoSymbol
837- var imports = Context .this .imports // impSym != NoSymbol => it is imported from imports.head
816+ var imports = Context .this .imports
838817 def imp1 = imports.head
818+ def imp2 = imports.tail.head
819+ def imp1Explicit = imp1 isExplicitImport name
820+ def imp2Explicit = imp2 isExplicitImport name
839821
840822 while (! qualifies(impSym) && imports.nonEmpty && imp1.depth > symbolDepth) {
841823 impSym = importedAccessibleSymbol(imp1, name)
842824 if (! impSym.exists)
843825 imports = imports.tail
844826 }
827+
845828 if (defSym.exists && impSym.exists) {
846829 // imported symbols take precedence over package-owned symbols in different compilation units.
847830 if (isPackageOwnedInDifferentUnit(defSym))
@@ -862,40 +845,33 @@ trait Contexts { self: Analyzer =>
862845 finish(EmptyTree , defSym)
863846 }
864847 else if (impSym.exists) {
865- // Imports against which we will test impSym for any ambiguities
866- var importsTail = imports.tail
867- val imp1Explicit = imp1 isExplicitImport name
868- def imp2 = importsTail.head
869- def sameDepth = imp1.depth == imp2.depth
870- def isDone = importsTail.isEmpty || imp1Explicit && ! sameDepth
871-
848+ def sameDepth = imp1.depth == imp2.depth
849+ def needsCheck = if (sameDepth) imp1Explicit == imp2Explicit else imp1Explicit || imp2Explicit
850+ def isDone = imports.tail.isEmpty || (! sameDepth && imp1Explicit)
851+ def ambiguous = needsCheck && isAmbiguousImport(imp1, imp2, name) && {
852+ lookupError = ambiguousImports(imp1, imp2)
853+ true
854+ }
855+ // Ambiguity check between imports.
856+ // The same name imported again is potentially ambiguous if the name is:
857+ // - after explicit import, explicitly imported again at the same or lower depth
858+ // - after explicit import, wildcard imported at lower depth
859+ // - after wildcard import, wildcard imported at the same depth
860+ // Under all such conditions isAmbiguousImport is called, which will
861+ // examine the imports in case they are importing the same thing; if that
862+ // can't be established conclusively, an error is issued.
872863 while (lookupError == null && ! isDone) {
873864 val other = importedAccessibleSymbol(imp2, name)
874- // Ambiguity check between imports.
875- // The same name imported again is potentially ambiguous if the name is:
876- // - after explicit import, explicitly imported again at the same or lower depth
877- // - after explicit import, wildcard imported at lower depth
878- // - after wildcard import, wildcard imported at the same depth
879- // Under all such conditions isAmbiguousImport is called, which will
880- // examine the imports in case they are importing the same thing; if that
881- // can't be established conclusively, an error is issued.
882- if (qualifies(other)) {
883- val imp2Explicit = imp2 isExplicitImport name
884- val needsCheck = (
885- if (sameDepth) imp1Explicit == imp2Explicit
886- else imp1Explicit || imp2Explicit
887- )
888- log(s " Import ambiguity: imp1= $imp1, imp2= $imp2, sameDepth= $sameDepth, needsCheck= $needsCheck" )
889- if (needsCheck && isAmbiguousImport(imp1, imp2, name))
890- lookupError = ambiguousImports(imp1, imp2)
891- else if (imp2Explicit) {
892- // if we weren't ambiguous and imp2 is explicit, imp2 replaces imp1
893- // as the current winner.
894- impSym = other
895- imports = importsTail
896- }
865+ // if the competing import is unambiguous and explicit, it is the new winner.
866+ val isNewWinner = qualifies(other) && ! ambiguous && imp2Explicit
867+ // imports is imp1 :: imp2 :: rest.
868+ // If there is a new winner, it is imp2, and imports drops imp1.
869+ // If there is not, imp1 is still the winner, and it drops imp2.
870+ if (isNewWinner) {
871+ impSym = other
872+ imports = imports.tail
897873 }
898- importsTail = importsTail .tail
874+ else imports = imp1 :: imports.tail .tail
899875 }
900876 // optimization: don't write out package prefixes
901877 finish(resetPos(imp1.qual.duplicate), impSym)
0 commit comments