Skip to content

Commit c82db74

Browse files
authored
Merge pull request #2205 from dotty-staging/fix-#2220
Fix #2220: Change handling of package objects and tweak hk type inference
2 parents b8bb34d + a321a98 commit c82db74

File tree

5 files changed

+80
-32
lines changed

5 files changed

+80
-32
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,9 @@ object SymDenotations {
14931493
myMemberCache
14941494
}
14951495

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+
14961499
/** Enter a symbol in current scope, and future scopes of same denotation.
14971500
* Note: We require that this does not happen after the first time
14981501
* someone does a findMember on a subclass.
@@ -1510,19 +1513,13 @@ object SymDenotations {
15101513
scope
15111514
case _ => unforcedDecls.openForMutations
15121515
}
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)
15191521
}
15201522
}
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-
}
15261523
}
15271524

15281525
/** Enter a symbol in given `scope` without potentially replacing the old copy. */
@@ -1534,7 +1531,7 @@ object SymDenotations {
15341531
(scope ne this.unforcedDecls) ||
15351532
sym.hasAnnotation(defn.ScalaStaticAnnot) ||
15361533
sym.name.isInlineAccessor ||
1537-
isUsecase)
1534+
isUsecase, i"trying to enter $sym in $this, frozen = ${this is Frozen}")
15381535

15391536
scope.enter(sym)
15401537

@@ -1800,7 +1797,7 @@ object SymDenotations {
18001797
/** The denotation of a package class.
18011798
* It overrides ClassDenotation to take account of package objects when looking for members
18021799
*/
1803-
class PackageClassDenotation private[SymDenotations] (
1800+
final class PackageClassDenotation private[SymDenotations] (
18041801
symbol: Symbol,
18051802
ownerIfExists: Symbol,
18061803
name: Name,
@@ -1823,15 +1820,33 @@ object SymDenotations {
18231820
packageObjCache
18241821
}
18251822

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)
18331849
}
1834-
}
18351850

18361851
/** The union of the member names of the package and the package object */
18371852
override def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = {
@@ -1841,6 +1856,21 @@ object SymDenotations {
18411856
case _ => ownNames
18421857
}
18431858
}
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+
}
18441874
}
18451875

18461876
class NoDenotation extends SymDenotation(

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -726,10 +726,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
726726

727727
tycon2 match {
728728
case param2: TypeParamRef =>
729-
isMatchingApply(tp1) || {
730-
if (canConstrain(param2)) canInstantiate(param2)
731-
else compareLower(bounds(param2), tyconIsTypeRef = false)
732-
}
729+
isMatchingApply(tp1) ||
730+
canConstrain(param2) && canInstantiate(param2) ||
731+
compareLower(bounds(param2), tyconIsTypeRef = false)
733732
case tycon2: TypeRef =>
734733
isMatchingApply(tp1) ||
735734
compareLower(tycon2.info.bounds, tyconIsTypeRef = true)

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,20 +1504,29 @@ object Types {
15041504
case _ => NoType
15051505
}
15061506
assert(
1507-
(lastSymbol eq sym) ||
1508-
(lastSymbol eq null) || {
1507+
(lastSymbol eq sym)
1508+
||
1509+
(lastSymbol eq null)
1510+
|| {
15091511
val lastDefRunId = lastDenotation match {
15101512
case d: SymDenotation => d.validFor.runId
15111513
case _ => lastSymbol.defRunId
15121514
}
15131515
(lastDefRunId != sym.defRunId) ||
15141516
(lastDefRunId == NoRunId)
1515-
} ||
1516-
(lastSymbol.infoOrCompleter.isInstanceOf[ErrorType] ||
1517+
}
1518+
||
1519+
lastSymbol.infoOrCompleter.isInstanceOf[ErrorType]
1520+
||
1521+
sym.isPackageObject // package objects can be visited before we get around to index them
1522+
||
15171523
sym.owner != lastSymbol.owner &&
1518-
(sym.owner.derivesFrom(lastSymbol.owner) ||
1519-
selfTypeOf(sym).derivesFrom(lastSymbol.owner) ||
1520-
selfTypeOf(lastSymbol).derivesFrom(sym.owner))),
1524+
(sym.owner.derivesFrom(lastSymbol.owner)
1525+
||
1526+
selfTypeOf(sym).derivesFrom(lastSymbol.owner)
1527+
||
1528+
selfTypeOf(lastSymbol).derivesFrom(sym.owner)
1529+
),
15211530
i"""data race? overwriting symbol of type $this,
15221531
|long form = $toString of class $getClass,
15231532
|last sym id = ${lastSymbol.id}, new sym id = ${sym.id},

tests/pos/i2200/Hello.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package bar
2+
import scala.language.higherKinds
3+
class Fix[F[_]](unfix: F[Fix[F]])
4+
object DocTree {
5+
def docTree(s: StreamTree[DocTree]): DocTree = new Fix(s: StreamTree[DocTree])
6+
}

tests/pos/i2200/package.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package object bar {
2+
type StreamTree[T] = Stream[Int]
3+
type DocTree = Fix[StreamTree]
4+
}

0 commit comments

Comments
 (0)