From bc108e92c1408cac20378802016637c640cc316f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 17 Sep 2017 13:00:42 +0200 Subject: [PATCH 01/11] Harden IDE: Surive checkNoLeaks assertion The problem is that the assertion in checkNoLeaks might be wrong if the widened type is erroneous. This happened during editing. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index a4fe66b932b2..4e3a400593ca 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -663,7 +663,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val ptDefined = isFullyDefined(pt, ForceDegree.none) if (ptDefined && !(avoidingType <:< pt)) avoidingType = pt val tree1 = ascribeType(tree, avoidingType) - assert(ptDefined || noLeaks(tree1), // `ptDefined` needed because of special case of anonymous classes + assert(ptDefined || noLeaks(tree1) || tree1.tpe.widen.isErroneous, + // `ptDefined` needed because of special case of anonymous classes i"leak: ${escapingRefs(tree1, localSyms).toList}%, % in $tree1") tree1 } From 05c44c02378fd822b8aa3156a8b1bec9f405cf81 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 24 Sep 2017 17:40:59 +0200 Subject: [PATCH 02/11] Harden ExpandPrivate assertion Died with an NPE instead of failing the assert --- compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index e5f34e60e2af..16d119035e0f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -89,8 +89,10 @@ class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { t (i < 0 || p1(i) == separatorChar) && (j < 0 || p1(j) == separatorChar) } - assert(isSimilar(d.symbol.sourceFile.path, ctx.source.file.path), - i"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.source.file}") + + assert(d.symbol.sourceFile != null && + isSimilar(d.symbol.sourceFile.path, ctx.source.file.path), + s"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.source.file}") d.ensureNotPrivate.installAfter(thisTransform) } From 29d85adfdff7a980f2b970927b27006b3df0e464 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 25 Sep 2017 14:09:10 +0200 Subject: [PATCH 03/11] Better support for private names --- .../dotty/tools/dotc/core/Denotations.scala | 23 ++-- .../dotty/tools/dotc/core/Designators.scala | 44 +++++++- .../src/dotty/tools/dotc/core/NameKinds.scala | 7 +- .../src/dotty/tools/dotc/core/NameOps.scala | 2 - .../dotty/tools/dotc/core/Substituters.scala | 2 +- .../src/dotty/tools/dotc/core/Symbols.scala | 16 ++- .../src/dotty/tools/dotc/core/Types.scala | 103 +++++++++++------- .../dotc/core/classfile/ClassfileParser.scala | 2 +- .../tools/dotc/core/tasty/TastyFormat.scala | 20 +++- .../tools/dotc/core/tasty/TreePickler.scala | 42 ++++--- .../tools/dotc/core/tasty/TreeUnpickler.scala | 28 ++++- .../dotc/transform/ParamForwarding.scala | 4 +- .../src/dotty/tools/dotc/typer/Checking.scala | 2 +- .../dotty/tools/dotc/typer/TypeAssigner.scala | 2 + 14 files changed, 211 insertions(+), 86 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index aded86d6975f..ab2282741d41 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -342,10 +342,10 @@ object Denotations { def mergeDenot(denot1: Denotation, denot2: SingleDenotation): Denotation = denot1 match { case denot1 @ MultiDenotation(denot11, denot12) => val d1 = mergeDenot(denot11, denot2) - if (d1.exists) denot1.derivedMultiDenotation(d1, denot12) + if (d1.exists) denot1.derivedUnionDenotation(d1, denot12) else { val d2 = mergeDenot(denot12, denot2) - if (d2.exists) denot1.derivedMultiDenotation(denot11, d2) + if (d2.exists) denot1.derivedUnionDenotation(denot11, d2) else NoDenotation } case denot1: SingleDenotation => @@ -532,11 +532,11 @@ object Denotations { else if (!that.exists) that else this match { case denot1 @ MultiDenotation(denot11, denot12) => - denot1.derivedMultiDenotation(denot11 | (that, pre), denot12 | (that, pre)) + denot1.derivedUnionDenotation(denot11 | (that, pre), denot12 | (that, pre)) case denot1: SingleDenotation => that match { case denot2 @ MultiDenotation(denot21, denot22) => - denot2.derivedMultiDenotation(this | (denot21, pre), this | (denot22, pre)) + denot2.derivedUnionDenotation(this | (denot21, pre), this | (denot22, pre)) case denot2: SingleDenotation => unionDenot(denot1, denot2) } @@ -558,9 +558,9 @@ object Denotations { final def isType = false final def signature(implicit ctx: Context) = Signature.OverloadedSignature def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): Denotation = - derivedMultiDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed)) + derivedUnionDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed)) def current(implicit ctx: Context): Denotation = - derivedMultiDenotation(denot1.current, denot2.current) + derivedUnionDenotation(denot1.current, denot2.current) def altsWith(p: Symbol => Boolean): List[SingleDenotation] = denot1.altsWith(p) ++ denot2.altsWith(p) def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = { @@ -580,12 +580,15 @@ object Denotations { val d2 = denot2 accessibleFrom (pre, superAccess) if (!d1.exists) d2 else if (!d2.exists) d1 - else derivedMultiDenotation(d1, d2) + else derivedUnionDenotation(d1, d2) } def mapInfo(f: Type => Type)(implicit ctx: Context): Denotation = - derivedMultiDenotation(denot1.mapInfo(f), denot2.mapInfo(f)) - def derivedMultiDenotation(d1: Denotation, d2: Denotation) = - if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2) + derivedUnionDenotation(denot1.mapInfo(f), denot2.mapInfo(f)) + def derivedUnionDenotation(d1: Denotation, d2: Denotation): Denotation = + if ((d1 eq denot1) && (d2 eq denot2)) this + else if (!d1.exists) d2 + else if (!d2.exists) d1 + else MultiDenotation(d1, d2) override def toString = alternatives.mkString(" ") private def multiHasNot(op: String): Nothing = diff --git a/compiler/src/dotty/tools/dotc/core/Designators.scala b/compiler/src/dotty/tools/dotc/core/Designators.scala index 73a4705fbb49..8be98755ae9e 100644 --- a/compiler/src/dotty/tools/dotc/core/Designators.scala +++ b/compiler/src/dotty/tools/dotc/core/Designators.scala @@ -3,6 +3,9 @@ package dotc package core import Names._ +import NameKinds.SignedName +import Types.{TypeRef, NameSpace, noNameSpace} +import Symbols.Symbol import Contexts.Context /** Defines a common superclass of Name and Symbol and its Term/Type variants @@ -10,7 +13,7 @@ import Contexts.Context */ object Designators { - abstract class Designator extends util.DotClass { + abstract class Designator extends util.DotClass { self => type ThisName <: Name @@ -23,8 +26,47 @@ object Designators { def asTerm(implicit ctx: Context): TermDesignator = unsupported("asTerm") def asType(implicit ctx: Context): TypeDesignator = unsupported("asType") + + def withNameSpace(space: NameSpace)(implicit ctx: Context): Designator { type ThisName = self.ThisName } = + if (space == noNameSpace) this + else localName(this.asInstanceOf[ThisName], space) + + /** Localize this name to the owner of `sym` if `sym` is private */ + def localizeIfPrivate(sym: Symbol)(implicit ctx: Context): Designator { type ThisName = self.ThisName } = + if (sym.isPrivate) withNameSpace(sym.owner.typeRef) else this + + def withSig(sig: Signature): Designator{ type ThisName = TermName } = + SignedName(this.asInstanceOf[TermName].exclude(SignedName), sig) } type TermDesignator = Designator { type ThisName = TermName } type TypeDesignator = Designator { type ThisName = TypeName } + + case class LocalName[N <: Name](name: N, nameSpace: TypeRef) extends Designator { + type ThisName = N + + override def isTerm(implicit ctx: Context) = name.isTermName + override def isType(implicit ctx: Context) = name.isTypeName + + override def asTerm(implicit ctx: Context): TermDesignator = { + name.asTermName + this.asInstanceOf[TermDesignator] + } + override def asType(implicit ctx: Context): TypeDesignator = { + name.asTypeName + this.asInstanceOf[TypeDesignator] + } + + override def withNameSpace(space: NameSpace)(implicit ctx: Context) = + name.withNameSpace(space).asInstanceOf[Designator { type ThisName = N }] + + override def withSig(sig: Signature) = + LocalName(name.withSig(sig).asInstanceOf[TermName], nameSpace) + } + + /** Introduced to overcome shortcoming with refined type inference of case classes: + * LocalName's result type is always Designator, without a refinement. + */ + def localName[N <: Name](name: N, nameSpace: TypeRef): Designator { type ThisName = N } = + LocalName(name, nameSpace).asInstanceOf[Designator { type ThisName = N }] } \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 89f907e8943f..5922a0a7b321 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -54,7 +54,8 @@ object NameKinds { def unmangle(name: SimpleName): TermName = name /** Turn a name of this kind consisting of an `underlying` prefix - * and the given `info` into a string. + * and the given `info` into a string. Used to turn structured into + * simple name. */ def mkString(underlying: TermName, info: ThisInfo): String @@ -120,7 +121,7 @@ object NameKinds { class QualifiedNameKind(tag: Int, val separator: String) extends NameKind(tag) { type ThisInfo = QualInfo - case class QualInfo(val name: SimpleName) extends Info with QualifiedInfo { + case class QualInfo(name: SimpleName) extends Info with QualifiedInfo { override def map(f: SimpleName => SimpleName): NameInfo = new QualInfo(f(name)) override def toString = s"$infoString $name" } @@ -363,7 +364,7 @@ object NameKinds { val ImplMethName = new SuffixNameKind(IMPLMETH, "$") /** A name together with a signature. Used in Tasty trees. */ - object SignedName extends NameKind(63) { + object SignedName extends NameKind(SIGNED) { case class SignedInfo(sig: Signature) extends Info { override def toString = s"$infoString $sig" diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 142dd0d1f6d9..5041c003bb92 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -311,7 +311,5 @@ object NameOps { case raw.BANG => UNARY_! case _ => name } - - def withSig(sig: Signature) = SignedName(name.exclude(SignedName), sig) } } diff --git a/compiler/src/dotty/tools/dotc/core/Substituters.scala b/compiler/src/dotty/tools/dotc/core/Substituters.scala index ce4d4337a1b3..b279afb4bd19 100644 --- a/compiler/src/dotty/tools/dotc/core/Substituters.scala +++ b/compiler/src/dotty/tools/dotc/core/Substituters.scala @@ -295,7 +295,7 @@ trait Substituters { this: Context => fs = fs.tail ts = ts.tail } - tp.newLikeThis(apply(tp.prefix)) + tp.withPrefix(apply(tp.prefix)) } catch { case ex: CyclicReference => tp.derivedSelect(apply(tp.prefix)) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index d68af9f1c8ca..78e3ceae1014 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -394,7 +394,7 @@ object Symbols { type ThisName <: Name - //assert(id != 4285) + //assert(id != 723) /** The last denotation of this symbol */ private[this] var lastDenot: SymDenotation = _ @@ -446,11 +446,23 @@ object Symbols { final def isClass: Boolean = isInstanceOf[ClassSymbol] final def asClass: ClassSymbol = asInstanceOf[ClassSymbol] + /** Test whether symbol is referenced symbolically. This + * conservatively returns `false` if symbol does not yet have a denotation + */ final def isReferencedSymbolically(implicit ctx: Context) = { val d = lastDenot d != null && (d.is(NonMember) || d.isTerm && ctx.phase.symbolicRefs) } + /** Test whether symbol is private. This + * conservatively returns `false` if symbol does not yet have a denotation, or denotation + * is a class that is not yet read. + */ + final def isPrivate(implicit ctx: Context) = { + val d = lastDenot + d != null && d.flagsUNSAFE.is(Private) + } + /** The symbol's signature if it is completed or a method, NotAMethod otherwise. */ final def signature(implicit ctx: Context) = if (lastDenot != null && (lastDenot.isCompleted || lastDenot.is(Method))) @@ -489,7 +501,7 @@ object Symbols { if (this is Module) this.moduleClass.validFor |= InitialPeriod } else this.owner.asClass.ensureFreshScopeAfter(phase) - if (!this.flagsUNSAFE.is(Private)) + if (!isPrivate) assert(phase.changesMembers, i"$this entered in ${this.owner} at undeclared phase $phase") entered } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index bd854af3810b..6fb8b4adfd66 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -823,7 +823,7 @@ object Types { (this eq thisResult) != (that eq thatResult) && (thisResult matchesLoosely thatResult) } - /** The basetype of this type with given class symbol, NoType is `base` is not a class. */ + /** The basetype of this type with given class symbol, NoType if `base` is not a class. */ final def baseType(base: Symbol)(implicit ctx: Context): Type = /*ctx.traceIndented(s"$this baseType $base")*/ /*>|>*/ track("base type") /*<|<*/ { base.denot match { case classd: ClassDenotation => classd.baseTypeOf(this) @@ -1480,6 +1480,9 @@ object Types { // --- NamedTypes ------------------------------------------------------------------ + type NameSpace = TypeRef /* | Null */ + @sharable val noNameSpace: NameSpace = null + /** A NamedType of the form Prefix # name */ abstract class NamedType extends CachedProxyType with ValueType { self => @@ -1497,18 +1500,23 @@ object Types { private[this] var myName: ThisName = _ private[this] var mySig: Signature = null + private[this] var myNameSpace: NameSpace = noNameSpace private[dotc] def init()(implicit ctx: Context): this.type = { - (designator: Designator) match { // dotty shortcoming: need the upcast + def decompose(designator: Designator): Unit = designator match { case DerivedName(underlying, info: SignedName.SignedInfo) => - myName = underlying.asInstanceOf[ThisName] mySig = info.sig assert(mySig ne Signature.OverloadedSignature) + decompose(underlying) case designator: Name => myName = designator.asInstanceOf[ThisName] case designator: Symbol => uncheckedSetSym(designator) + case LocalName(underlying, space) => + myNameSpace = space + decompose(underlying) } + decompose(designator) this } @@ -1522,6 +1530,8 @@ object Types { else if (isType || lastDenotation == null) Signature.NotAMethod else denot.signature + final def nameSpace: NameSpace = myNameSpace + private[this] var lastDenotation: Denotation = _ private[this] var lastSymbol: Symbol = _ private[this] var checkedPeriod = Nowhere @@ -1602,8 +1612,11 @@ object Types { case d: SymDenotation => if (hasFixedSym) d.current else if (d.validFor.runId == ctx.runId || ctx.stillValid(d)) - if (d.exists && prefix.isTightPrefix(d.owner) || d.isConstructor) d.current - else recomputeMember(d) // symbol could have been overridden, recompute membership + if (nameSpace != noNameSpace || + d.exists && 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 @@ -1685,15 +1698,22 @@ object Types { |period = ${ctx.phase} at run ${ctx.runId}""") } - private[dotc] def withDenot(denot: Denotation)(implicit ctx: Context): ThisType = - if (!hasFixedSym && - signature != denot.signature && - denot.signature.ne(Signature.OverloadedSignature)) - withSig(denot.signature).withDenot(denot).asInstanceOf[ThisType] + private[dotc] def withDenot(denot: Denotation)(implicit ctx: Context): ThisType = { + val adapted = + if (hasFixedSym) + this + else if (signature != denot.signature && denot.signature.ne(Signature.OverloadedSignature)) + withSig(denot.signature) + else if (denot.symbol.isPrivate) + withNameSpace(denot.symbol.owner.typeRef) + else + this + if (adapted ne this) adapted.withDenot(denot).asInstanceOf[ThisType] else { setDenot(denot) this } + } private[dotc] final def setDenot(denot: Denotation)(implicit ctx: Context): Unit = { if (Config.checkNoDoubleBindings) @@ -1727,10 +1747,10 @@ object Types { } private def withSig(sig: Signature)(implicit ctx: Context): NamedType = - TermRef(prefix, name.asTermName.withSig(sig)) + TermRef(prefix, designator.withSig(sig)) protected def loadDenot(implicit ctx: Context): Denotation = { - val d = asMemberOf(prefix, allowPrivate = true) + val d = asMemberOf(prefix, allowPrivate = false) // allowPrivate needed? if (d.exists || ctx.phaseId == FirstPhaseId || !lastDenotation.isInstanceOf[SymDenotation]) if (mySig != null) d.atSignature(mySig).checkUnique else d @@ -1745,8 +1765,9 @@ object Types { protected def asMemberOf(prefix: Type, allowPrivate: Boolean)(implicit ctx: Context): Denotation = if (name.is(ShadowedName)) prefix.nonPrivateMember(name.exclude(ShadowedName)) - else if (!allowPrivate) prefix.nonPrivateMember(name) - else prefix.member(name) + else if (nameSpace != noNameSpace) nameSpace.findMember(name, prefix, EmptyFlags) + else if (allowPrivate) prefix.member(name) + else prefix.nonPrivateMember(name) /** (1) Reduce a type-ref `W # X` or `W { ... } # U`, where `W` is a wildcard type * to an (unbounded) wildcard type. @@ -1769,7 +1790,6 @@ object Types { else denot.symbol - /** Retrieves currently valid symbol without necessarily updating denotation. * Assumes that symbols do not change between periods in the same run. * Used to get the class underlying a ThisType. @@ -1879,18 +1899,24 @@ object Types { val derived2 = derivedSelect(prefix.tp2) return prefix.derivedOrType(derived1, derived2) case _ => - newLikeThis(prefix) + withPrefix(prefix) } - else newLikeThis(prefix) + else withPrefix(prefix) } else prefix match { case _: WildcardType => WildcardType - case _ => newLikeThis(prefix) + case _ => withPrefix(prefix) } /** Create a NamedType of the same kind as this type, but with a new prefix. */ - def newLikeThis(prefix: Type)(implicit ctx: Context): NamedType + def withPrefix(prefix: Type)(implicit ctx: Context): NamedType + + /** Create a NamedType of the same kind as this type, but with a new namespace. + */ + def withNameSpace(nameSpace: NameSpace)(implicit ctx: Context): NamedType = + if (nameSpace == this.nameSpace) this + else NamedType(prefix, designator.withNameSpace(nameSpace)) /** Create a NamedType of the same kind as this type, but with a "inherited name". * This is necessary to in situations like the following: @@ -1916,9 +1942,9 @@ object Types { * the public name. */ def shadowed(implicit ctx: Context): NamedType = - designator match { - case designator: Symbol => this - case designator: Name => NamedType(prefix, designator.derived(ShadowedName)) + (designator: Designator) match { // Dotty deviation: need the widening + case LocalName(underlying, _) => NamedType(prefix, underlying) + case _ => this } override def equals(that: Any) = that match { @@ -1971,10 +1997,10 @@ object Types { } else candidate - def newLikeThis(prefix: Type)(implicit ctx: Context): NamedType = designator match { + def withPrefix(prefix: Type)(implicit ctx: Context): NamedType = designator match { case designator: TermSymbol => TermRef(prefix, designator) - case designator: TermName => + case _ => // If symbol exists, the new signature is the symbol's signature as seen // from the new prefix, modulo consistency val curSig = signature @@ -1983,13 +2009,13 @@ object Types { curSig else curSig.updateWith(symbol.info.asSeenFrom(prefix, symbol.owner).signature) - val candidate = + val designator1 = if (newSig ne curSig) { core.println(i"sig change at ${ctx.phase} for $this, pre = $prefix, sig: $curSig --> $newSig") - TermRef(prefix, name.withSig(newSig)) + designator.withSig(newSig) } - else TermRef(prefix, designator) - fixDenot(candidate, prefix) + else designator + fixDenot(TermRef(prefix, designator1), prefix) } override def shadowed(implicit ctx: Context): NamedType = @@ -2003,7 +2029,7 @@ object Types { override def underlying(implicit ctx: Context): Type = info - def newLikeThis(prefix: Type)(implicit ctx: Context): NamedType = + def withPrefix(prefix: Type)(implicit ctx: Context): NamedType = TypeRef(prefix, designator) } @@ -2022,12 +2048,12 @@ object Types { if (Config.checkUnerased) assert(!ctx.phase.erasedTypes) object NamedType { - def apply(prefix: Type, designator: Name)(implicit ctx: Context) = + def apply(prefix: Type, designator: Name)(implicit ctx: Context) = // ### needed? if (designator.isTermName) TermRef(prefix, designator.asTermName) else TypeRef(prefix, designator.asTypeName) - def apply(prefix: Type, sym: Symbol)(implicit ctx: Context) = - if (sym.isType) TypeRef(prefix, sym.asType) - else TermRef(prefix, sym.asTerm) + def apply(prefix: Type, designator: Designator)(implicit ctx: Context) = + if (designator.isType) TypeRef(prefix, designator.asType) + else TermRef(prefix, designator.asTerm) def apply(prefix: Type, designator: Name, denot: Denotation)(implicit ctx: Context) = if (designator.isTermName) TermRef(prefix, designator.asTermName, denot) else TypeRef(prefix, designator.asTypeName, denot) @@ -2052,7 +2078,8 @@ object Types { def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef = { if ((prefix eq NoPrefix) || denot.symbol.isReferencedSymbolically) apply(prefix, denot.symbol.asTerm) else denot match { - case denot: SingleDenotation => apply(prefix, name.withSig(denot.signature)) + case denot: SingleDenotation => + apply(prefix, name.withSig(denot.signature).localizeIfPrivate(denot.symbol)) case _ => apply(prefix, name) } } withDenot denot @@ -2064,7 +2091,7 @@ object Types { */ def withSym(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef = if ((prefix eq NoPrefix) || sym.isReferencedSymbolically) apply(prefix, sym) - else apply(prefix, name.withSig(sym.signature)).withSym(sym) + else apply(prefix, name.withSig(sym.signature).localizeIfPrivate(sym)).withSym(sym) def withSym(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef = withSym(prefix, sym, sym.name) @@ -2079,7 +2106,7 @@ object Types { /** Create a type ref with given name and initial denotation */ def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef = { if ((prefix eq NoPrefix) || denot.symbol.isReferencedSymbolically) apply(prefix, denot.symbol.asType) - else apply(prefix, name) + else apply(prefix, name.localizeIfPrivate(denot.symbol)) } withDenot denot /** Create a type ref referring to either a given symbol or its name. @@ -2089,7 +2116,7 @@ object Types { */ def withSym(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef = if ((prefix eq NoPrefix) || sym.isReferencedSymbolically) apply(prefix, sym) - else apply(prefix, name).withSym(sym) + else apply(prefix, name.localizeIfPrivate(sym)).withSym(sym) def withSym(prefix: Type, sym: TypeSymbol)(implicit ctx: Context): TypeRef = withSym(prefix, sym, sym.name) @@ -2169,7 +2196,7 @@ object Types { } def evaluating = computed && myRef == null override def underlying(implicit ctx: Context) = ref - override def toString = s"LazyRef(...)" + override def toString = s"LazyRef(${if (computed) myRef else "..."})" override def equals(other: Any) = this eq other.asInstanceOf[AnyRef] override def hashCode = System.identityHashCode(this) } diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index b0c5b722d281..d47d9f967303 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -300,7 +300,7 @@ class ClassfileParser( case 'L' => def processInner(tp: Type): Type = tp match { case tp: TypeRef if !(tp.symbol.owner is Flags.ModuleClass) => - TypeRef(processInner(tp.prefix.widen), tp.name) + TypeRef.withSym(processInner(tp.prefix.widen), tp.symbol.asType, tp.name) case _ => tp } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index e1547a958a59..5a619f581e48 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -44,7 +44,6 @@ Macro-format: PROTECTEDACCESSOR Length underlying_NameRef PROTECTEDSETTER Length underlying_NameRef INITIALIZER Length underlying_NameRef - SHADOWED Length underlying_NameRef AVOIDCLASH Length underlying_NameRef DIRECT Length underlying_NameRef FIELD Length underlying_NameRef @@ -127,6 +126,7 @@ Standard-Section: "ASTs" TopLevelStat* TERMREFdirect sym_ASTRef TERMREFsymbol sym_ASTRef qual_Type TERMREFpkg fullyQualified_NameRef + TERMREFin Length possiblySigned_NameRef qual_Type namespace_Type TERMREF possiblySigned_NameRef qual_Type THIS clsRef_Type RECthis recType_ASTRef @@ -151,7 +151,8 @@ Standard-Section: "ASTs" TopLevelStat* TYPEREFdirect sym_ASTRef TYPEREFsymbol sym_ASTRef qual_Type TYPEREFpkg fullyQualified_NameRef - TYPEREF possiblySigned_NameRef qual_Type + TYPEREFin Length NameRef qual_Type namespace_Type + TYPEREF NameRef qual_Type RECtype parent_Type TYPEALIAS alias_Type SUPERtype Length this_Type underlying_Type @@ -262,6 +263,7 @@ object TastyFormat { final val IMPLMETH = 64 // AST tags + // Cat. 1: tag final val UNITconst = 2 final val FALSEconst = 3 @@ -294,6 +296,8 @@ object TastyFormat { final val DEFAULTparameterized = 30 final val STABLE = 31 + // Cat. 2: tag Nat + final val SHARED = 64 final val TERMREFdirect = 65 final val TYPEREFdirect = 66 @@ -311,6 +315,8 @@ object TastyFormat { final val IMPORTED = 78 final val RENAMED = 79 + // Cat. 3: tag AST + final val THIS = 96 final val QUALTHIS = 97 final val CLASSconst = 98 @@ -325,6 +331,8 @@ object TastyFormat { final val TYPEALIAS = 107 final val SINGLETONtpt = 108 + // Cat. 4: tag Nat AST + final val IDENT = 112 final val IDENTtpt = 113 final val SELECT = 114 @@ -335,6 +343,8 @@ object TastyFormat { final val TYPEREF = 119 final val SELFDEF = 120 + // Cat. 5: tag Length ... + final val PACKAGE = 128 final val VALDEF = 129 final val DEFDEF = 130 @@ -382,6 +392,8 @@ object TastyFormat { final val PARAMtype = 174 final val ANNOTATION = 175 final val TYPEARGtype = 176 + final val TERMREFin = 177 + final val TYPEREFin = 178 final val firstSimpleTreeTag = UNITconst final val firstNatTreeTag = SHARED @@ -565,6 +577,8 @@ object TastyFormat { case SINGLETONtpt => "SINGLETONtpt" case SUPERtype => "SUPERtype" case TYPEARGtype => "TYPEARGtype" + case TERMREFin => "TERMREFin" + case TYPEREFin => "TYPEREFin" case REFINEDtype => "REFINEDtype" case REFINEDtpt => "REFINEDtpt" case APPLIEDtype => "APPLIEDtype" @@ -593,7 +607,7 @@ object TastyFormat { */ def numRefs(tag: Int) = tag match { case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND | - SELFDEF | REFINEDtype => 1 + SELFDEF | REFINEDtype | TERMREFin | TYPEREFin => 1 case RENAMED | PARAMtype => 2 case POLYtype | METHODtype | TYPELAMBDAtype => -1 case _ => 0 diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 96a44f638958..c80f43152ff2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -9,7 +9,7 @@ import TastyFormat._ import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._, StdNames.tpnme, NameOps._ import collection.mutable import typer.Inliner -import NameOps._, NameKinds._ +import NameOps._, NameKinds._, Designators._ import StdNames.nme import TastyBuffer._ import TypeApplications._ @@ -144,15 +144,19 @@ class TreePickler(pickler: TastyPickler) { pickleConstant(value) case tpe: NamedType => val sym = tpe.symbol + def pickleStdRef(name: Name) = { + writeByte(if (tpe.isType) TYPEREF else TERMREF) + pickleName(name); pickleType(tpe.prefix) + } + def pickleDirectRef() = { + writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) + pickleSymRef(sym) + } if (sym.is(Flags.Package)) { writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg) pickleName(sym.fullName) } - else if (tpe.prefix == NoPrefix) { - def pickleDirectRef() = { - writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) - pickleSymRef(sym) - } + else if (tpe.prefix == NoPrefix) if (sym is Flags.BindDefinedType) { registerDef(sym) writeByte(BIND) @@ -163,22 +167,24 @@ class TreePickler(pickler: TastyPickler) { } } else pickleDirectRef() - } else if (isLocallyDefined(sym)) { writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol) pickleSymRef(sym); pickleType(tpe.prefix) } - else { - val name = tpe.designator match { - case designator: Symbol => - assert(tpe.symbol.isClass && tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated) - // Note: vulnerability here, since Scala2x allows several classes with same name and prefix - designator.name - case designator: Name => - designator - } - writeByte(if (tpe.isType) TYPEREF else TERMREF) - pickleName(name); pickleType(tpe.prefix) + else tpe.designator match { + case sym: Symbol => + assert(tpe.symbol.isClass && tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated) + // Note: vulnerability here, since Scala2x allows several classes with same name and prefix + pickleStdRef(sym.name) + case name: Name => + pickleStdRef(name) + case LocalName(name, space) => + writeByte(if (tpe.isType) TYPEREFin else TERMREFin) + withLength { + pickleName(name) + pickleType(tpe.prefix) + pickleType(space) + } } case tpe: ThisType => if (tpe.cls.is(Flags.Package) && !tpe.cls.isEffectiveRoot) { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 029c4c106dc9..4f22845c9ed6 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -220,6 +220,16 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val result = (tag: @switch) match { + case TERMREFin => + var name = readName() + val prefix = readType() + val space = readType().asInstanceOf[TypeRef] + TermRef(prefix, name.withNameSpace(space)) + case TYPEREFin => + val name = readName().toTypeName + val prefix = readType() + val space = readType().asInstanceOf[TypeRef] + TypeRef(prefix, name.withNameSpace(space)) case REFINEDtype => var name: Name = readName() val parent = readType() @@ -710,7 +720,9 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val cls = ctx.owner.asClass val assumedSelfType = if (cls.is(Module) && cls.owner.isClass) - TermRef(cls.owner.thisType, cls.name.sourceModuleName.withSig(Signature.NotAMethod)) + TermRef( + cls.owner.thisType, + cls.name.sourceModuleName.withSig(Signature.NotAMethod).localizeIfPrivate(cls)) else NoType cls.info = new TempClassInfo(cls.owner.thisType, cls, cls.unforcedDecls, assumedSelfType) val localDummy = symbolAtCurrent() @@ -849,7 +861,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } } - def completeSelect(name: Name, tpf: Type => Type): Select = { + def completeSelect(name: Name, tpf: Type => NamedType): Select = { val localCtx = if (name == nme.CONSTRUCTOR) ctx.addMode(Mode.InSuperCall) else ctx val qual = readTerm()(localCtx) @@ -862,6 +874,12 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi (untpd.Ident(qual.name).withPos(qual.pos), qual.tpe.asInstanceOf[TypeRef]) } + def accessibleDenot(pre: Type, name: Name, sig: Signature) = { + val d = pre.member(name).atSignature(sig) + if (!d.symbol.exists || d.symbol.isAccessibleFrom(pre)) d + else pre.nonPrivateMember(name).atSignature(sig) + } + def readSimpleTerm(): Tree = tag match { case SHARED => forkAt(readAddr()).readTerm() @@ -870,15 +888,15 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case IDENTtpt => untpd.Ident(readName().toTypeName).withType(readType()) case SELECT => - def readRest(name: Name, sig: Signature) = - completeSelect(name, TermRef(_, name.asTermName.withSig(sig))) + def readRest(name: TermName, sig: Signature): Tree = + completeSelect(name, pre => TermRef(pre, name, accessibleDenot(pre, name, sig))) readName() match { case SignedName(name, sig) => readRest(name, sig) case name => readRest(name, Signature.NotAMethod) } case SELECTtpt => val name = readName().toTypeName - completeSelect(name, TypeRef(_, name)) + completeSelect(name, pre => TypeRef(pre, name, accessibleDenot(pre, name, Signature.NotAMethod))) case QUALTHIS => val (qual, tref) = readQualId() untpd.This(qual).withType(ThisType.raw(tref)) diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index fb1ae1cf6748..c153b9fa673a 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -96,7 +96,9 @@ class ParamForwarding(thisTransformer: DenotTransformer) { // It could be a param forwarder; adapt the signature val newSig = tpe.prefix.memberInfo(tpe.symbol).signature if (newSig == Signature.NotAMethod) tree - else tree.withType(TermRef(tpe.prefix, tpe.name.withSig(newSig))).asInstanceOf[T] + else tree.withType( + TermRef(tpe.prefix, tpe.name.withSig(newSig).localizeIfPrivate(tpe.symbol))) + .asInstanceOf[T] case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 3a143f826ea4..3c60db0e0ec1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -244,7 +244,7 @@ object Checking { locked += tp try checkInfo(tp.info) finally locked -= tp - if (pre1 eq pre) tp else tp.newLikeThis(pre1) + if (pre1 eq pre) tp else tp.withPrefix(pre1) } else tp } catch { diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 69bce45b1c3e..75242d9ac643 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -188,6 +188,7 @@ trait TypeAssigner { // an inherited non-private member with the same name and signature. val d2 = pre.nonPrivateMember(name) if (reallyExists(d2) && firstTry) + // test(NamedType(pre, name, d2), false) test(tpe.shadowed.withDenot(d2), false) else if (pre.derivesFrom(defn.DynamicClass)) { TryDynamicCallType @@ -350,6 +351,7 @@ trait TypeAssigner { else errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) case t => + println(i"bad tree: $fn, ${fn.uniqueId}: ${fn.tpe}") errorType(err.takesNoParamsStr(fn, ""), tree.pos) } tree.withType(ownType) From 622dfc24469b624872b2b9f5c551c735716b66ad Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 25 Sep 2017 19:08:07 +0200 Subject: [PATCH 04/11] Drop ShadowedName --- .../src/dotty/tools/dotc/core/NameKinds.scala | 1 - .../src/dotty/tools/dotc/core/StdNames.scala | 1 - .../src/dotty/tools/dotc/core/Types.scala | 36 ++++--------------- .../tools/dotc/core/tasty/TastyFormat.scala | 2 -- .../tools/dotc/core/tasty/TreePickler.scala | 8 ++--- .../tools/dotc/core/tasty/TreeUnpickler.scala | 3 +- .../dotty/tools/dotc/transform/Erasure.scala | 11 ++---- .../dotc/transform/ParamForwarding.scala | 2 +- .../dotty/tools/dotc/typer/TypeAssigner.scala | 3 +- 9 files changed, 14 insertions(+), 53 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 5922a0a7b321..b8ea00fa9fb3 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -350,7 +350,6 @@ object NameKinds { val SuperAccessorName = new PrefixNameKind(SUPERACCESSOR, "super$") val InitializerName = new PrefixNameKind(INITIALIZER, "initial$") - val ShadowedName = new PrefixNameKind(SHADOWED, "(shadowed)") val ProtectedAccessorName = new PrefixNameKind(PROTECTEDACCESSOR, "protected$") val ProtectedSetterName = new PrefixNameKind(PROTECTEDSETTER, "protected$set") // dubious encoding, kept for Scala2 compatibility val AvoidClashName = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$") diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index b4fd1efa745a..be886b2b3bd7 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -21,7 +21,6 @@ object StdNames { final val TRAIT_SETTER_SEPARATOR = "$_setter_$" final val SUPER_PREFIX = "super$" final val INITIALIZER_PREFIX = "initial$" - final val SHADOWED_PREFIX = "(shadowed)" final val AVOID_CLASH_SUFFIX = "$_avoid_name_clash_$" final val MODULE_SUFFIX = "$" final val NAME_JOIN = "$" diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 6fb8b4adfd66..0d76898e2824 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -7,7 +7,7 @@ import Symbols._ import Flags._ import Names._ import StdNames._, NameOps._ -import NameKinds.{ShadowedName, SkolemName, SignedName} +import NameKinds.{SkolemName, SignedName} import Scopes._ import Constants._ import Contexts._ @@ -1764,8 +1764,7 @@ object Types { def reloadDenot()(implicit ctx: Context) = setDenot(loadDenot) protected def asMemberOf(prefix: Type, allowPrivate: Boolean)(implicit ctx: Context): Denotation = - if (name.is(ShadowedName)) prefix.nonPrivateMember(name.exclude(ShadowedName)) - else if (nameSpace != noNameSpace) nameSpace.findMember(name, prefix, EmptyFlags) + if (nameSpace != noNameSpace) nameSpace.findMember(name, prefix, EmptyFlags) else if (allowPrivate) prefix.member(name) else prefix.nonPrivateMember(name) @@ -1918,31 +1917,10 @@ object Types { if (nameSpace == this.nameSpace) this else NamedType(prefix, designator.withNameSpace(nameSpace)) - /** Create a NamedType of the same kind as this type, but with a "inherited name". - * This is necessary to in situations like the following: - * - * class B { def m: T1 } - * class C extends B { private def m: T2; ... C.m } - * object C extends C - * object X { ... C.m } - * - * The two references of C.m in class C and object X refer to different - * definitions: The one in C refers to C#m whereas the one in X refers to B#m. - * But the type C.m must have only one denotation, so it can't refer to two - * members depending on context. - * - * In situations like this, the reference in X would get the type - * `.shadowed` to make clear that we mean the inherited member, not - * the private one. - * - * Note: An alternative, possibly more robust scheme would be to give - * private members special names. A private definition would have a special - * name (say m' in the example above), but would be entered in its enclosing - * under both private and public names, so it could still be found by looking up - * the public name. + /** Create a NamedType of the same kind as this type, but without a namespace */ - def shadowed(implicit ctx: Context): NamedType = - (designator: Designator) match { // Dotty deviation: need the widening + def withoutNameSpace(implicit ctx: Context): NamedType = + (designator: Designator) match { // Dotty deviation: need the widening case LocalName(underlying, _) => NamedType(prefix, underlying) case _ => this } @@ -2018,8 +1996,8 @@ object Types { fixDenot(TermRef(prefix, designator1), prefix) } - override def shadowed(implicit ctx: Context): NamedType = - fixDenot(super.shadowed.asInstanceOf[TermRef], prefix) + override def withoutNameSpace(implicit ctx: Context): NamedType = + fixDenot(super.withoutNameSpace.asInstanceOf[TermRef], prefix) } abstract case class TypeRef(override val prefix: Type, designator: TypeDesignator) extends NamedType { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 5a619f581e48..1725df947b48 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -249,7 +249,6 @@ object TastyFormat { final val PROTECTEDACCESSOR = 21 final val PROTECTEDSETTER = 22 final val INITIALIZER = 23 - final val SHADOWED = 24 final val AVOIDCLASH = 30 final val DIRECT = 31 final val FIELD = 32 @@ -468,7 +467,6 @@ object TastyFormat { case PROTECTEDACCESSOR => "PROTECTEDACCESSOR" case PROTECTEDSETTER => "PROTECTEDSETTER" case INITIALIZER => "INITIALIZER" - case SHADOWED => "SHADOWED" case AVOIDCLASH => "AVOIDCLASH" case DIRECT => "DIRECT" case FIELD => "FIELD" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index c80f43152ff2..8e018173c461 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -333,14 +333,10 @@ class TreePickler(pickler: TastyPickler) { } case Select(qual, name) => writeByte(if (name.isTypeName) SELECTtpt else SELECT) - val realName = tree.tpe match { - case tp: NamedType if tp.name.is(ShadowedName) => tp.name - case _ => name - } val sig = tree.tpe.signature pickleName( - if (name.isTypeName || sig == Signature.NotAMethod) realName - else SignedName(realName.toTermName, sig)) + if (name.isTypeName || sig == Signature.NotAMethod) name + else SignedName(name.toTermName, sig)) pickleTree(qual) case Apply(fun, args) => writeByte(APPLY) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 4f22845c9ed6..ed41e2f71e04 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -865,8 +865,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val localCtx = if (name == nme.CONSTRUCTOR) ctx.addMode(Mode.InSuperCall) else ctx val qual = readTerm()(localCtx) - val unshadowed = name.exclude(ShadowedName) - untpd.Select(qual, unshadowed).withType(tpf(qual.tpe.widenIfUnstable)) + untpd.Select(qual, name).withType(tpf(qual.tpe.widenIfUnstable)) } def readQualId(): (untpd.Ident, TypeRef) = { diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index ef839ea82578..4900fad30962 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -11,7 +11,6 @@ import core.Types._ import core.Names._ import core.StdNames._ import core.NameOps._ -import core.NameKinds.ShadowedName import core.Decorators._ import core.Constants._ import core.Definitions._ @@ -385,14 +384,8 @@ object Erasure { val sym = if (owner eq origSym.owner) origSym else owner.info.decl(origSym.name).symbol assert(sym.exists, origSym.showLocated) - def select(qual: Tree, sym: Symbol): Tree = { - val name = tree.typeOpt match { - case tp: NamedType if tp.name.is(ShadowedName) => sym.name.derived(ShadowedName) - case _ => sym.name - } - untpd.cpy.Select(tree)(qual, sym.name) - .withType(NamedType(qual.tpe, sym)) - } + def select(qual: Tree, sym: Symbol): Tree = + untpd.cpy.Select(tree)(qual, sym.name).withType(NamedType(qual.tpe, sym)) def selectArrayMember(qual: Tree, erasedPre: Type): Tree = if (erasedPre isRef defn.ObjectClass) diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index c153b9fa673a..4df698ed769b 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -72,7 +72,7 @@ class ParamForwarding(thisTransformer: DenotTransformer) { if (alias.owner != currentClass.superClass) // need to use shadowed in order not to accidentally address an // intervening private forwarder in the superclass - superAcc = superAcc.withType(superAcc.tpe.asInstanceOf[TermRef].shadowed) + superAcc = superAcc.withType(superAcc.tpe.asInstanceOf[TermRef].withoutNameSpace) typr.println(i"adding param forwarder $superAcc") DefDef(sym, superAcc.ensureConforms(sym.info.widen)) } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 75242d9ac643..a617546e37c3 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -188,8 +188,7 @@ trait TypeAssigner { // an inherited non-private member with the same name and signature. val d2 = pre.nonPrivateMember(name) if (reallyExists(d2) && firstTry) - // test(NamedType(pre, name, d2), false) - test(tpe.shadowed.withDenot(d2), false) + test(tpe.withoutNameSpace.withDenot(d2), false) else if (pre.derivesFrom(defn.DynamicClass)) { TryDynamicCallType } else { From aa0d76356020085b3b17fe9101b733e0293cfbcf Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Sep 2017 09:20:32 +0200 Subject: [PATCH 05/11] Cleanups --- compiler/src/dotty/tools/dotc/core/Types.scala | 5 +---- compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 0d76898e2824..f94ad56fc534 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1750,7 +1750,7 @@ object Types { TermRef(prefix, designator.withSig(sig)) protected def loadDenot(implicit ctx: Context): Denotation = { - val d = asMemberOf(prefix, allowPrivate = false) // allowPrivate needed? + val d = asMemberOf(prefix, allowPrivate = false) if (d.exists || ctx.phaseId == FirstPhaseId || !lastDenotation.isInstanceOf[SymDenotation]) if (mySig != null) d.atSignature(mySig).checkUnique else d @@ -2026,9 +2026,6 @@ object Types { if (Config.checkUnerased) assert(!ctx.phase.erasedTypes) object NamedType { - def apply(prefix: Type, designator: Name)(implicit ctx: Context) = // ### needed? - if (designator.isTermName) TermRef(prefix, designator.asTermName) - else TypeRef(prefix, designator.asTypeName) def apply(prefix: Type, designator: Designator)(implicit ctx: Context) = if (designator.isType) TypeRef(prefix, designator.asType) else TermRef(prefix, designator.asTerm) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index a617546e37c3..d8ba1b9d8bd5 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -350,7 +350,6 @@ trait TypeAssigner { else errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos) case t => - println(i"bad tree: $fn, ${fn.uniqueId}: ${fn.tpe}") errorType(err.takesNoParamsStr(fn, ""), tree.pos) } tree.withType(ownType) From c766aa42d3270ad6bc154a90080a3ac029807ec1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Sep 2017 13:49:11 +0200 Subject: [PATCH 06/11] Drop withoutNameSpace Can be replaced by withNameSpace(noNameSpace). --- compiler/src/dotty/tools/dotc/core/Types.scala | 11 ----------- .../dotty/tools/dotc/transform/ParamForwarding.scala | 3 ++- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f94ad56fc534..5b6ed30f58d7 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1917,14 +1917,6 @@ object Types { if (nameSpace == this.nameSpace) this else NamedType(prefix, designator.withNameSpace(nameSpace)) - /** Create a NamedType of the same kind as this type, but without a namespace - */ - def withoutNameSpace(implicit ctx: Context): NamedType = - (designator: Designator) match { // Dotty deviation: need the widening - case LocalName(underlying, _) => NamedType(prefix, underlying) - case _ => this - } - override def equals(that: Any) = that match { case that: NamedType => this.designator == that.designator && @@ -1995,9 +1987,6 @@ object Types { else designator fixDenot(TermRef(prefix, designator1), prefix) } - - override def withoutNameSpace(implicit ctx: Context): NamedType = - fixDenot(super.withoutNameSpace.asInstanceOf[TermRef], prefix) } abstract case class TypeRef(override val prefix: Type, designator: TypeDesignator) extends NamedType { diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index 4df698ed769b..9eaa407b765b 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -72,7 +72,8 @@ class ParamForwarding(thisTransformer: DenotTransformer) { if (alias.owner != currentClass.superClass) // need to use shadowed in order not to accidentally address an // intervening private forwarder in the superclass - superAcc = superAcc.withType(superAcc.tpe.asInstanceOf[TermRef].withoutNameSpace) + superAcc = superAcc.withType( + superAcc.tpe.asInstanceOf[TermRef].withNameSpace(noNameSpace)) typr.println(i"adding param forwarder $superAcc") DefDef(sym, superAcc.ensureConforms(sym.info.widen)) } diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index d8ba1b9d8bd5..93cb4093f68c 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -188,7 +188,7 @@ trait TypeAssigner { // an inherited non-private member with the same name and signature. val d2 = pre.nonPrivateMember(name) if (reallyExists(d2) && firstTry) - test(tpe.withoutNameSpace.withDenot(d2), false) + test(tpe.withNameSpace(noNameSpace).withDenot(d2), false) else if (pre.derivesFrom(defn.DynamicClass)) { TryDynamicCallType } else { From 56a4055e3c3b1b3bf5e13460dadcd819ab0d858d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Sep 2017 13:43:45 +0200 Subject: [PATCH 07/11] Allow OverloadedSignature in TermRefs We admit overloaded signatures in term refs. --- compiler/src/dotty/tools/dotc/core/Denotations.scala | 3 ++- compiler/src/dotty/tools/dotc/core/Types.scala | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index ab2282741d41..9efa9cfe9a79 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -558,7 +558,8 @@ object Denotations { final def isType = false final def signature(implicit ctx: Context) = Signature.OverloadedSignature def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): Denotation = - derivedUnionDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed)) + if (sig eq Signature.OverloadedSignature) this + else derivedUnionDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed)) def current(implicit ctx: Context): Denotation = derivedUnionDenotation(denot1.current, denot2.current) def altsWith(p: Symbol => Boolean): List[SingleDenotation] = diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5b6ed30f58d7..5bcbc249bd89 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1506,7 +1506,6 @@ object Types { def decompose(designator: Designator): Unit = designator match { case DerivedName(underlying, info: SignedName.SignedInfo) => mySig = info.sig - assert(mySig ne Signature.OverloadedSignature) decompose(underlying) case designator: Name => myName = designator.asInstanceOf[ThisName] @@ -1702,7 +1701,7 @@ object Types { val adapted = if (hasFixedSym) this - else if (signature != denot.signature && denot.signature.ne(Signature.OverloadedSignature)) + else if (signature != denot.signature) withSig(denot.signature) else if (denot.symbol.isPrivate) withNameSpace(denot.symbol.owner.typeRef) @@ -1752,7 +1751,7 @@ object Types { protected def loadDenot(implicit ctx: Context): Denotation = { val d = asMemberOf(prefix, allowPrivate = false) if (d.exists || ctx.phaseId == FirstPhaseId || !lastDenotation.isInstanceOf[SymDenotation]) - if (mySig != null) d.atSignature(mySig).checkUnique + if (mySig != null && mySig.ne(Signature.OverloadedSignature)) d.atSignature(mySig).checkUnique else d else { // name has changed; try load in earlier phase and make current val d = loadDenot(ctx.withPhase(ctx.phaseId - 1)).current From 5b384f00ccc58aae7b579a9af7ee3567a8be3e82 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Sep 2017 14:47:33 +0200 Subject: [PATCH 08/11] Don't use NotAMethod in SignedNames Instead, assume that an unsigned name means NotAMethod. --- compiler/src/dotty/tools/dotc/core/Designators.scala | 6 ++++-- compiler/src/dotty/tools/dotc/core/NameKinds.scala | 1 + compiler/src/dotty/tools/dotc/core/Types.scala | 11 ++++++----- .../dotty/tools/dotc/core/tasty/TastyUnpickler.scala | 4 ++-- .../src/dotty/tools/dotc/core/tasty/TreePickler.scala | 2 +- .../dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 4 +--- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- .../dotty/tools/dotc/transform/ParamForwarding.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Implicits.scala | 2 +- 9 files changed, 19 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Designators.scala b/compiler/src/dotty/tools/dotc/core/Designators.scala index 8be98755ae9e..f09394c0b869 100644 --- a/compiler/src/dotty/tools/dotc/core/Designators.scala +++ b/compiler/src/dotty/tools/dotc/core/Designators.scala @@ -35,8 +35,10 @@ object Designators { def localizeIfPrivate(sym: Symbol)(implicit ctx: Context): Designator { type ThisName = self.ThisName } = if (sym.isPrivate) withNameSpace(sym.owner.typeRef) else this - def withSig(sig: Signature): Designator{ type ThisName = TermName } = - SignedName(this.asInstanceOf[TermName].exclude(SignedName), sig) + def withSig(sig: Signature): Designator{ type ThisName = TermName } = { + val unsigned = this.asInstanceOf[TermName].exclude(SignedName) + if (sig eq Signature.NotAMethod) unsigned else SignedName(unsigned, sig) + } } type TermDesignator = Designator { type ThisName = TermName } diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index b8ea00fa9fb3..54729efcbcaa 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -366,6 +366,7 @@ object NameKinds { object SignedName extends NameKind(SIGNED) { case class SignedInfo(sig: Signature) extends Info { + assert(sig ne Signature.NotAMethod) override def toString = s"$infoString $sig" } type ThisInfo = SignedInfo diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5bcbc249bd89..a7adf70351e1 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1509,6 +1509,7 @@ object Types { decompose(underlying) case designator: Name => myName = designator.asInstanceOf[ThisName] + if (mySig == null) mySig = Signature.NotAMethod case designator: Symbol => uncheckedSetSym(designator) case LocalName(underlying, space) => @@ -1524,10 +1525,10 @@ object Types { myName } - final override def signature(implicit ctx: Context): Signature = - if (mySig != null) mySig - else if (isType || lastDenotation == null) Signature.NotAMethod - else denot.signature + final override def signature(implicit ctx: Context): Signature = { + if (mySig == null) mySig = denot.signature + mySig + } final def nameSpace: NameSpace = myNameSpace @@ -1974,7 +1975,7 @@ object Types { // from the new prefix, modulo consistency val curSig = signature val newSig = - if (curSig == Signature.NotAMethod || !symbol.exists) + if (curSig.eq(Signature.NotAMethod) || !symbol.exists) curSig else curSig.updateWith(symbol.info.asSeenFrom(prefix, symbol.owner).signature) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index 67f0c763755f..29d06408a6d5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -64,8 +64,8 @@ class TastyUnpickler(reader: TastyReader) { val result = readName().toTypeName val params = until(end)(readName().toTypeName) var sig = Signature(params, result) - if (sig == Signature.NotAMethod) sig = Signature.NotAMethod - SignedName(original, sig) + if (sig == Signature.NotAMethod) sig = Signature.NotAMethod // needed temporarily, as long as we read old tasty + original.withSig(sig).asInstanceOf[TermName] case _ => simpleNameKindOfTag(tag)(readName()) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 8e018173c461..4563ac84de1e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -335,7 +335,7 @@ class TreePickler(pickler: TastyPickler) { writeByte(if (name.isTypeName) SELECTtpt else SELECT) val sig = tree.tpe.signature pickleName( - if (name.isTypeName || sig == Signature.NotAMethod) name + if (sig eq Signature.NotAMethod) name else SignedName(name.toTermName, sig)) pickleTree(qual) case Apply(fun, args) => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index ed41e2f71e04..85d4ffb666eb 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -720,9 +720,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi val cls = ctx.owner.asClass val assumedSelfType = if (cls.is(Module) && cls.owner.isClass) - TermRef( - cls.owner.thisType, - cls.name.sourceModuleName.withSig(Signature.NotAMethod).localizeIfPrivate(cls)) + TermRef(cls.owner.thisType, cls.name.sourceModuleName.localizeIfPrivate(cls)) else NoType cls.info = new TempClassInfo(cls.owner.thisType, cls, cls.unforcedDecls, assumedSelfType) val localDummy = symbolAtCurrent() diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index f0346a17d37c..487d33f53bb5 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -705,7 +705,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas val pre = readTypeRef() val sym = readDisambiguatedSymbolRef(_.info.isParameterless) if (isLocal(sym) || (pre eq NoPrefix)) pre select sym - else TermRef(pre, sym.name.asTermName.withSig(Signature.NotAMethod)) // !!! should become redundant + else TermRef(pre, sym.name.asTermName) case SUPERtpe => val thistpe = readTypeRef() val supertpe = readTypeRef() diff --git a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala index 9eaa407b765b..33b7852ac0a7 100644 --- a/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala +++ b/compiler/src/dotty/tools/dotc/transform/ParamForwarding.scala @@ -93,10 +93,10 @@ class ParamForwarding(thisTransformer: DenotTransformer) { def adaptRef[T <: RefTree](tree: T)(implicit ctx: Context): T = tree.tpe match { case tpe: TermRef - if tpe.prefix.ne(NoPrefix) && tpe.signature == Signature.NotAMethod && tpe.symbol.is(Method) => + if tpe.prefix.ne(NoPrefix) && tpe.signature.eq(Signature.NotAMethod) && tpe.symbol.is(Method) => // It could be a param forwarder; adapt the signature val newSig = tpe.prefix.memberInfo(tpe.symbol).signature - if (newSig == Signature.NotAMethod) tree + if (newSig.eq(Signature.NotAMethod)) tree else tree.withType( TermRef(tpe.prefix, tpe.name.withSig(newSig).localizeIfPrivate(tpe.symbol))) .asInstanceOf[T] diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index c75b1897e5ad..a937aa418d3d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -432,7 +432,7 @@ trait ImplicitRunInfo { self: RunInfo => def addRef(companion: TermRef): Unit = { val compSym = companion.symbol if (compSym is Package) - addRef(TermRef(companion, nme.PACKAGE.withSig(Signature.NotAMethod))) + addRef(TermRef(companion, nme.PACKAGE)) else if (compSym.exists) comps += companion.asSeenFrom(pre, compSym.owner).asInstanceOf[TermRef] } From 71bf783a0620960e514eda218e2850083103e129 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Sep 2017 15:36:26 +0200 Subject: [PATCH 09/11] Clean up accesses to Scala-2 inner classes Since these can shadow each other, we need to refer to them by a name and a namespace. This is more solid than the system it replaces, which referred to such symbols symbplically but then fell back to the (unsafe) simple name on pickling. --- .../src/dotty/tools/dotc/core/tasty/TreePickler.scala | 11 ++--------- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 10 ++++++---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 4563ac84de1e..083f71009056 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -144,10 +144,6 @@ class TreePickler(pickler: TastyPickler) { pickleConstant(value) case tpe: NamedType => val sym = tpe.symbol - def pickleStdRef(name: Name) = { - writeByte(if (tpe.isType) TYPEREF else TERMREF) - pickleName(name); pickleType(tpe.prefix) - } def pickleDirectRef() = { writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) pickleSymRef(sym) @@ -172,12 +168,9 @@ class TreePickler(pickler: TastyPickler) { pickleSymRef(sym); pickleType(tpe.prefix) } else tpe.designator match { - case sym: Symbol => - assert(tpe.symbol.isClass && tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated) - // Note: vulnerability here, since Scala2x allows several classes with same name and prefix - pickleStdRef(sym.name) case name: Name => - pickleStdRef(name) + writeByte(if (tpe.isType) TYPEREF else TERMREF) + pickleName(name); pickleType(tpe.prefix) case LocalName(name, space) => writeByte(if (tpe.isType) TYPEREFin else TERMREFin) withLength { diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 487d33f53bb5..53e8e5ce56cc 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -733,14 +733,16 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas case _ => } val tycon = - if (sym.isClass && sym.is(Scala2x) && !sym.owner.is(Package)) - // use fixed sym for Scala 2 inner classes, because they might be shadowed - TypeRef(pre, sym.asType) + if (sym.isClass && sym.is(Scala2x) && sym.owner.isClass && !sym.owner.is(Package)) + // There can be multiple Scala2 inner classes with the same prefix and name; use a namespace + // to pick a particular one. + TypeRef(pre, sym.name.asTypeName.withNameSpace(sym.owner.typeRef)) else if (isLocal(sym) || pre == NoPrefix) { val pre1 = if ((pre eq NoPrefix) && (sym is TypeParam)) sym.owner.thisType else pre pre1 select sym } - else TypeRef(pre, sym.name.asTypeName) + else + TypeRef(pre, sym.name.asTypeName) val args = until(end, readTypeRef) if (sym == defn.ByNameParamClass2x) ExprType(args.head) else if (args.nonEmpty) tycon.safeAppliedTo(EtaExpandIfHK(sym.typeParams, args.map(translateTempPoly))) From a2a445f3b685f868f05d61fd76734d5bfc610b61 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 26 Sep 2017 19:57:34 +0200 Subject: [PATCH 10/11] Fix signature for hk type lambdas The had the same signature as polymorphic types, but being a type of types, they should have signature NotAMethod --- compiler/src/dotty/tools/dotc/core/Types.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index a7adf70351e1..de071d3fd1a0 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2465,7 +2465,7 @@ object Types { extends CachedProxyType with TermType with MethodicType { override def resultType(implicit ctx: Context): Type = resType override def underlying(implicit ctx: Context): Type = resType - protected def computeSignature(implicit ctx: Context): Signature = resultSignature + def computeSignature(implicit ctx: Context): Signature = resultSignature def derivedExprType(resType: Type)(implicit ctx: Context) = if (resType eq this.resType) this else ExprType(resType) override def computeHash = doHash(resType) @@ -2487,7 +2487,7 @@ object Types { * HKLambda | HKTermLambda | HKTypeLambda * MethodOrPoly | MethodType | PolyType */ - trait LambdaType extends BindingType with MethodicType { self => + trait LambdaType extends BindingType with TermType { self => type ThisName <: Name type PInfo <: Type type This <: LambdaType{type PInfo = self.PInfo} @@ -2517,8 +2517,6 @@ object Types { myParamRefs } - protected def computeSignature(implicit ctx: Context) = resultSignature - final def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type = if (isDependent) resultType.substParams(this, argTypes) else resultType @@ -2566,7 +2564,7 @@ object Types { } } - abstract class MethodOrPoly extends CachedGroundType with LambdaType with TermType { + abstract class MethodOrPoly extends CachedGroundType with LambdaType with MethodicType { final override def computeHash = doHash(paramNames, resType, paramInfos) // Defined here instead of in LambdaType for efficiency @@ -2691,7 +2689,7 @@ object Types { val resType = resultTypeExp(this) assert(resType.exists) - override def computeSignature(implicit ctx: Context): Signature = + def computeSignature(implicit ctx: Context): Signature = resultSignature.prepend(paramInfos, isJava) protected def prefixString = "MethodType" @@ -2895,6 +2893,8 @@ object Types { assert(resType.isInstanceOf[TermType], this) assert(paramNames.nonEmpty) + def computeSignature(implicit ctx: Context) = resultSignature + /** Merge nested polytypes into one polytype. nested polytypes are normally not supported * but can arise as temporary data structures. */ From 7f57ff3b85a6e616dc0bb4aeb310465c6f3aeb8a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 29 Sep 2017 18:04:48 +0200 Subject: [PATCH 11/11] Document LocalName --- compiler/src/dotty/tools/dotc/core/Designators.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/core/Designators.scala b/compiler/src/dotty/tools/dotc/core/Designators.scala index f09394c0b869..52c20bb0e3c4 100644 --- a/compiler/src/dotty/tools/dotc/core/Designators.scala +++ b/compiler/src/dotty/tools/dotc/core/Designators.scala @@ -44,6 +44,10 @@ object Designators { type TermDesignator = Designator { type ThisName = TermName } type TypeDesignator = Designator { type ThisName = TypeName } + /** Names that come with the namespace where they are defined. + * Used to give a stable reference to private names, and also to + * Scala 2x inner classes. + */ case class LocalName[N <: Name](name: N, nameSpace: TypeRef) extends Designator { type ThisName = N