diff options
author | odersky <odersky@gmail.com> | 2017-04-09 17:04:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-09 17:04:57 +0200 |
commit | c82db74c97bec486f3da7cce3128b72711c8cbc3 (patch) | |
tree | 25d23bb6da4bef45a7b37b7f09fa17ee7a19b3c5 /compiler | |
parent | b8bb34dd0ea68cfed09ed54604f659a787037d2d (diff) | |
parent | a321a982a6ebdaaa924a2538866959abe0b9eb18 (diff) | |
download | dotty-c82db74c97bec486f3da7cce3128b72711c8cbc3.tar.gz dotty-c82db74c97bec486f3da7cce3128b72711c8cbc3.tar.bz2 dotty-c82db74c97bec486f3da7cce3128b72711c8cbc3.zip |
Merge pull request #2205 from dotty-staging/fix-#2220
Fix #2220: Change handling of package objects and tweak hk type inference
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 72 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 7 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Types.scala | 23 |
3 files changed, 70 insertions, 32 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 602848a50..6d1a006ed 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1493,6 +1493,9 @@ object SymDenotations { myMemberCache } + /** Hook to do a pre-enter test. Overridden in PackageDenotation */ + protected def proceedWithEnter(sym: Symbol, mscope: MutableScope)(implicit ctx: Context): Boolean = true + /** Enter a symbol in current scope, and future scopes of same denotation. * Note: We require that this does not happen after the first time * someone does a findMember on a subclass. @@ -1510,19 +1513,13 @@ object SymDenotations { scope case _ => unforcedDecls.openForMutations } - if (this is PackageClass) { - val entry = mscope.lookupEntry(sym.name) - if (entry != null) { - if (entry.sym == sym) return - mscope.unlink(entry) - entry.sym.denot = sym.denot // to avoid stale symbols + if (proceedWithEnter(sym, mscope)) { + enterNoReplace(sym, mscope) + val nxt = this.nextInRun + if (nxt.validFor.code > this.validFor.code) { + this.nextInRun.asSymDenotation.asClass.enter(sym) } } - enterNoReplace(sym, mscope) - val nxt = this.nextInRun - if (nxt.validFor.code > this.validFor.code) { - this.nextInRun.asSymDenotation.asClass.enter(sym) - } } /** Enter a symbol in given `scope` without potentially replacing the old copy. */ @@ -1534,7 +1531,7 @@ object SymDenotations { (scope ne this.unforcedDecls) || sym.hasAnnotation(defn.ScalaStaticAnnot) || sym.name.isInlineAccessor || - isUsecase) + isUsecase, i"trying to enter $sym in $this, frozen = ${this is Frozen}") scope.enter(sym) @@ -1800,7 +1797,7 @@ object SymDenotations { /** The denotation of a package class. * It overrides ClassDenotation to take account of package objects when looking for members */ - class PackageClassDenotation private[SymDenotations] ( + final class PackageClassDenotation private[SymDenotations] ( symbol: Symbol, ownerIfExists: Symbol, name: Name, @@ -1823,15 +1820,33 @@ object SymDenotations { packageObjCache } - /** Look first for members in package; if none are found look in package object */ - override def computeNPMembersNamed(name: Name, inherited: Boolean)(implicit ctx: Context): PreDenotation = { - val denots = super.computeNPMembersNamed(name, inherited) - if (denots.exists) denots - else packageObj.moduleClass.denot match { - case pcls: ClassDenotation => pcls.computeNPMembersNamed(name, inherited) - case _ => denots + /** Looks in both the package object and the package for members. The precise algorithm + * is as follows: + * + * If this is the scala package look in the package first, and if nothing is found + * there, look in the package object second. Otherwise, look in the package object + * first, and if nothing is found there, in the package second. + * + * The reason for the special treatment of the scala package is that if we + * complete it too early, we freeze its superclass Any, so that no members can + * be entered in it. As a consequence, there should be no entry in the scala package + * object that hides a class or object in the scala package of the same name, because + * the behavior would then be unintuitive for such members. + */ + override def computeNPMembersNamed(name: Name, inherited: Boolean)(implicit ctx: Context): PreDenotation = + packageObj.moduleClass.denot match { + case pcls: ClassDenotation if !pcls.isCompleting => + if (symbol eq defn.ScalaPackageClass) { + val denots = super.computeNPMembersNamed(name, inherited) + if (denots.exists) denots else pcls.computeNPMembersNamed(name, inherited) + } + else { + val denots = pcls.computeNPMembersNamed(name, inherited) + if (denots.exists) denots else super.computeNPMembersNamed(name, inherited) + } + case _ => + super.computeNPMembersNamed(name, inherited) } - } /** The union of the member names of the package and the package object */ override def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = { @@ -1841,6 +1856,21 @@ object SymDenotations { case _ => ownNames } } + + /** If another symbol with the same name is entered, unlink it, + * and, if symbol is a package object, invalidate the packageObj cache. + * @return `sym` is not already entered + */ + override def proceedWithEnter(sym: Symbol, mscope: MutableScope)(implicit ctx: Context): Boolean = { + val entry = mscope.lookupEntry(sym.name) + if (entry != null) { + if (entry.sym == sym) return false + mscope.unlink(entry) + entry.sym.denot = sym.denot // to avoid stale symbols + if (sym.name == nme.PACKAGE) packageObjRunId = NoRunId + } + true + } } class NoDenotation extends SymDenotation( diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index da6d63387..54b96a253 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -726,10 +726,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tycon2 match { case param2: TypeParamRef => - isMatchingApply(tp1) || { - if (canConstrain(param2)) canInstantiate(param2) - else compareLower(bounds(param2), tyconIsTypeRef = false) - } + isMatchingApply(tp1) || + canConstrain(param2) && canInstantiate(param2) || + compareLower(bounds(param2), tyconIsTypeRef = false) case tycon2: TypeRef => isMatchingApply(tp1) || compareLower(tycon2.info.bounds, tyconIsTypeRef = true) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 8ae3aa7ad..e7130ee2f 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1504,20 +1504,29 @@ object Types { case _ => NoType } assert( - (lastSymbol eq sym) || - (lastSymbol eq null) || { + (lastSymbol eq sym) + || + (lastSymbol eq null) + || { val lastDefRunId = lastDenotation match { case d: SymDenotation => d.validFor.runId case _ => lastSymbol.defRunId } (lastDefRunId != sym.defRunId) || (lastDefRunId == NoRunId) - } || - (lastSymbol.infoOrCompleter.isInstanceOf[ErrorType] || + } + || + lastSymbol.infoOrCompleter.isInstanceOf[ErrorType] + || + sym.isPackageObject // package objects can be visited before we get around to index them + || sym.owner != lastSymbol.owner && - (sym.owner.derivesFrom(lastSymbol.owner) || - selfTypeOf(sym).derivesFrom(lastSymbol.owner) || - selfTypeOf(lastSymbol).derivesFrom(sym.owner))), + (sym.owner.derivesFrom(lastSymbol.owner) + || + selfTypeOf(sym).derivesFrom(lastSymbol.owner) + || + selfTypeOf(lastSymbol).derivesFrom(sym.owner) + ), i"""data race? overwriting symbol of type $this, |long form = $toString of class $getClass, |last sym id = ${lastSymbol.id}, new sym id = ${sym.id}, |