@@ -1493,6 +1493,9 @@ object SymDenotations {
1493
1493
myMemberCache
1494
1494
}
1495
1495
1496
+ /** Hook to do a pre-enter test. Overridden in PackageDenotation */
1497
+ protected def proceedWithEnter (sym : Symbol , mscope : MutableScope )(implicit ctx : Context ): Boolean = true
1498
+
1496
1499
/** Enter a symbol in current scope, and future scopes of same denotation.
1497
1500
* Note: We require that this does not happen after the first time
1498
1501
* someone does a findMember on a subclass.
@@ -1510,19 +1513,13 @@ object SymDenotations {
1510
1513
scope
1511
1514
case _ => unforcedDecls.openForMutations
1512
1515
}
1513
- if (this is PackageClass ) {
1514
- val entry = mscope.lookupEntry(sym.name)
1515
- if (entry != null ) {
1516
- if (entry.sym == sym) return
1517
- mscope.unlink(entry)
1518
- entry.sym.denot = sym.denot // to avoid stale symbols
1516
+ if (proceedWithEnter(sym, mscope)) {
1517
+ enterNoReplace(sym, mscope)
1518
+ val nxt = this .nextInRun
1519
+ if (nxt.validFor.code > this .validFor.code) {
1520
+ this .nextInRun.asSymDenotation.asClass.enter(sym)
1519
1521
}
1520
1522
}
1521
- enterNoReplace(sym, mscope)
1522
- val nxt = this .nextInRun
1523
- if (nxt.validFor.code > this .validFor.code) {
1524
- this .nextInRun.asSymDenotation.asClass.enter(sym)
1525
- }
1526
1523
}
1527
1524
1528
1525
/** Enter a symbol in given `scope` without potentially replacing the old copy. */
@@ -1534,7 +1531,7 @@ object SymDenotations {
1534
1531
(scope ne this .unforcedDecls) ||
1535
1532
sym.hasAnnotation(defn.ScalaStaticAnnot ) ||
1536
1533
sym.name.isInlineAccessor ||
1537
- isUsecase)
1534
+ isUsecase, i " trying to enter $sym in $this , frozen = ${ this is Frozen } " )
1538
1535
1539
1536
scope.enter(sym)
1540
1537
@@ -1800,7 +1797,7 @@ object SymDenotations {
1800
1797
/** The denotation of a package class.
1801
1798
* It overrides ClassDenotation to take account of package objects when looking for members
1802
1799
*/
1803
- class PackageClassDenotation private [SymDenotations ] (
1800
+ final class PackageClassDenotation private [SymDenotations ] (
1804
1801
symbol : Symbol ,
1805
1802
ownerIfExists : Symbol ,
1806
1803
name : Name ,
@@ -1823,15 +1820,33 @@ object SymDenotations {
1823
1820
packageObjCache
1824
1821
}
1825
1822
1826
- /** Look first for members in package; if none are found look in package object */
1827
- override def computeNPMembersNamed (name : Name , inherited : Boolean )(implicit ctx : Context ): PreDenotation = {
1828
- val denots = super .computeNPMembersNamed(name, inherited)
1829
- if (denots.exists) denots
1830
- else packageObj.moduleClass.denot match {
1831
- case pcls : ClassDenotation => pcls.computeNPMembersNamed(name, inherited)
1832
- case _ => denots
1823
+ /** Looks in both the package object and the package for members. The precise algorithm
1824
+ * is as follows:
1825
+ *
1826
+ * If this is the scala package look in the package first, and if nothing is found
1827
+ * there, look in the package object second. Otherwise, look in the package object
1828
+ * first, and if nothing is found there, in the package second.
1829
+ *
1830
+ * The reason for the special treatment of the scala package is that if we
1831
+ * complete it too early, we freeze its superclass Any, so that no members can
1832
+ * be entered in it. As a consequence, there should be no entry in the scala package
1833
+ * object that hides a class or object in the scala package of the same name, because
1834
+ * the behavior would then be unintuitive for such members.
1835
+ */
1836
+ override def computeNPMembersNamed (name : Name , inherited : Boolean )(implicit ctx : Context ): PreDenotation =
1837
+ packageObj.moduleClass.denot match {
1838
+ case pcls : ClassDenotation if ! pcls.isCompleting =>
1839
+ if (symbol eq defn.ScalaPackageClass ) {
1840
+ val denots = super .computeNPMembersNamed(name, inherited)
1841
+ if (denots.exists) denots else pcls.computeNPMembersNamed(name, inherited)
1842
+ }
1843
+ else {
1844
+ val denots = pcls.computeNPMembersNamed(name, inherited)
1845
+ if (denots.exists) denots else super .computeNPMembersNamed(name, inherited)
1846
+ }
1847
+ case _ =>
1848
+ super .computeNPMembersNamed(name, inherited)
1833
1849
}
1834
- }
1835
1850
1836
1851
/** The union of the member names of the package and the package object */
1837
1852
override def memberNames (keepOnly : NameFilter )(implicit ctx : Context ): Set [Name ] = {
@@ -1841,6 +1856,21 @@ object SymDenotations {
1841
1856
case _ => ownNames
1842
1857
}
1843
1858
}
1859
+
1860
+ /** If another symbol with the same name is entered, unlink it,
1861
+ * and, if symbol is a package object, invalidate the packageObj cache.
1862
+ * @return `sym` is not already entered
1863
+ */
1864
+ override def proceedWithEnter (sym : Symbol , mscope : MutableScope )(implicit ctx : Context ): Boolean = {
1865
+ val entry = mscope.lookupEntry(sym.name)
1866
+ if (entry != null ) {
1867
+ if (entry.sym == sym) return false
1868
+ mscope.unlink(entry)
1869
+ entry.sym.denot = sym.denot // to avoid stale symbols
1870
+ if (sym.name == nme.PACKAGE ) packageObjRunId = NoRunId
1871
+ }
1872
+ true
1873
+ }
1844
1874
}
1845
1875
1846
1876
class NoDenotation extends SymDenotation (
0 commit comments