diff options
author | odersky <odersky@gmail.com> | 2015-05-05 11:27:30 +0200 |
---|---|---|
committer | odersky <odersky@gmail.com> | 2015-05-05 11:27:30 +0200 |
commit | 7129cbe60c062be49aef8c27da461a11416e189c (patch) | |
tree | 7866d26cedcffcaa175347d0e48613e470b3fb29 /src | |
parent | c4dba2420be56e628e37732a3369533951cc7ef1 (diff) | |
parent | 3edf285a48f4208b209571580f8aa418ca8a794f (diff) | |
download | dotty-7129cbe60c062be49aef8c27da461a11416e189c.tar.gz dotty-7129cbe60c062be49aef8c27da461a11416e189c.tar.bz2 dotty-7129cbe60c062be49aef8c27da461a11416e189c.zip |
Merge pull request #534 from dotty-staging/fix/computeDenot
Fix #518 - compute denotations
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 54 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/ExtensionMethods.scala | 3 |
3 files changed, 34 insertions, 24 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 784773fd3..c21620048 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -451,7 +451,6 @@ class Definitions { lazy val RootImports = List[Symbol](JavaLangPackageVal, ScalaPackageVal, ScalaPredefModule, DottyPredefModule) - lazy val overriddenBySynthetic = Set[Symbol](Any_equals, Any_hashCode, Any_toString, Product_canEqual) def isTupleType(tp: Type)(implicit ctx: Context) = { val arity = tp.dealias.argInfos.length arity <= MaxTupleArity && (tp isRef TupleClass(arity)) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 80cceed38..512ddc41a 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -126,6 +126,19 @@ object Types { false } + /** Does this type refer exactly to class symbol `sym`, instead of to a subclass of `sym`? + * Implemented like `isRef`, but follows more types: all type proxies as well as and- and or-types + */ + private[Types] def isTightPrefix(sym: Symbol)(implicit ctx: Context): Boolean = stripTypeVar match { + case tp: NamedType => tp.info.isTightPrefix(sym) + case tp: ClassInfo => tp.cls eq sym + case tp: Types.ThisType => tp.cls eq sym + case tp: TypeProxy => tp.underlying.isTightPrefix(sym) + case tp: AndType => tp.tp1.isTightPrefix(sym) && tp.tp2.isTightPrefix(sym) + case tp: OrType => tp.tp1.isTightPrefix(sym) || tp.tp2.isTightPrefix(sym) + case _ => false + } + /** Is this type an instance of a non-bottom subclass of the given class `cls`? */ final def derivesFrom(cls: Symbol)(implicit ctx: Context): Boolean = this match { case tp: TypeRef => @@ -1221,27 +1234,17 @@ object Types { val sym = lastSymbol if (sym == null) loadDenot else denotOfSym(sym) case d: SymDenotation => - if ( d.validFor.runId == ctx.runId - || ctx.stillValid(d) - || this.isInstanceOf[WithFixedSym]) d.current + if (this.isInstanceOf[WithFixedSym]) d.current + else if (d.validFor.runId == ctx.runId || ctx.stillValid(d)) + if (prefix.isTightPrefix(d.owner) || d.isConstructor) d.current + else recomputeMember(d) // symbol could have been overridden, recompute membership else { val newd = loadDenot if (newd.exists) newd else d.staleSymbolError } case d => - if (d.validFor.runId != ctx.period.runId) - loadDenot - // The following branch was used to avoid an assertErased error. - // It's idea was to void keeping non-sym denotations after erasure - // since they violate the assertErased contract. But the problem is - // that when seen again in an earlier phase the denotation is - // still seen as a SymDenotation, whereas it should be a SingleDenotation. - // That's why the branch is disabled. - // - // else if (ctx.erasedTypes && lastSymbol != null) - // denotOfSym(lastSymbol) - else - d.current + if (d.validFor.runId != ctx.period.runId) loadDenot + else d.current } if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot") else if (d.exists) { @@ -1250,7 +1253,10 @@ object Types { // phase but a defined denotation earlier (e.g. a TypeRef to an abstract type // is undefined after erasure.) We need to be able to do time travel back and // forth also in these cases. - setDenot(d) + + // Don't use setDenot here; double binding checks can give spurious failures after erasure + lastDenotation = d + lastSymbol = d.symbol checkedPeriod = ctx.period } d @@ -1258,6 +1264,14 @@ object Types { finally ctx.typerState.ephemeral |= savedEphemeral } + /** A member of `prefix` (disambiguated by `d.signature`) or, if none was found, `d.current`. */ + private def recomputeMember(d: SymDenotation)(implicit ctx: Context): Denotation = + asMemberOf(prefix) match { + case NoDenotation => d.current + case newd: SingleDenotation => newd + case newd => newd.atSignature(d.signature).orElse(d.current) + } + private def denotOfSym(sym: Symbol)(implicit ctx: Context): Denotation = { val d = sym.denot val owner = d.owner @@ -1276,11 +1290,9 @@ object Types { (lastDefRunId == NoRunId) } || (lastSymbol.infoOrCompleter == ErrorType || - defn.overriddenBySynthetic.contains(lastSymbol) - // for overriddenBySynthetic symbols a TermRef such as SomeCaseClass.this.hashCode - // might be rewritten from Object#hashCode to the hashCode generated at SyntheticMethods + sym.owner.derivesFrom(lastSymbol.owner) && sym.owner != lastSymbol.owner ), - s"data race? overwriting symbol of ${this.show} / $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id}") + s"data race? overwriting symbol of ${this.show} / $this / ${this.getClass} / ${lastSymbol.id} / ${sym.id} / ${sym.owner} / ${lastSymbol.owner} / ${ctx.phase}") protected def sig: Signature = Signature.NotAMethod diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala index b2f402bc5..009257dc0 100644 --- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -54,7 +54,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful ctx.atPhase(thisTransformer.next) { implicit ctx => // In Scala 2, extension methods are added before pickling so we should // not generate them again. - if (!(origClass is Scala2x)) { + if (!(origClass is Scala2x)) ctx.atPhase(thisTransformer) { implicit ctx => for (decl <- origClass.classInfo.decls) { if (isMethodWithExtension(decl)) decls1.enter(createExtensionMethod(decl, ref.symbol)) @@ -91,7 +91,6 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful else NoSymbol private def createExtensionMethod(imeth: Symbol, staticClass: Symbol)(implicit ctx: Context): TermSymbol = { - assert(ctx.phase == thisTransformer.next) val extensionName = extensionNames(imeth).head.toTermName val extensionMeth = ctx.newSymbol(staticClass, extensionName, imeth.flags | Final &~ (Override | Protected | AbsOverride), |