Skip to content

Commit 58b5203

Browse files
authored
Merge pull request #3167 from dotty-staging/change-private-refs
More robust way to refer to private definitions in types
2 parents 626ebf2 + 7f57ff3 commit 58b5203

21 files changed

+242
-166
lines changed

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,10 @@ object Denotations {
342342
def mergeDenot(denot1: Denotation, denot2: SingleDenotation): Denotation = denot1 match {
343343
case denot1 @ MultiDenotation(denot11, denot12) =>
344344
val d1 = mergeDenot(denot11, denot2)
345-
if (d1.exists) denot1.derivedMultiDenotation(d1, denot12)
345+
if (d1.exists) denot1.derivedUnionDenotation(d1, denot12)
346346
else {
347347
val d2 = mergeDenot(denot12, denot2)
348-
if (d2.exists) denot1.derivedMultiDenotation(denot11, d2)
348+
if (d2.exists) denot1.derivedUnionDenotation(denot11, d2)
349349
else NoDenotation
350350
}
351351
case denot1: SingleDenotation =>
@@ -532,11 +532,11 @@ object Denotations {
532532
else if (!that.exists) that
533533
else this match {
534534
case denot1 @ MultiDenotation(denot11, denot12) =>
535-
denot1.derivedMultiDenotation(denot11 | (that, pre), denot12 | (that, pre))
535+
denot1.derivedUnionDenotation(denot11 | (that, pre), denot12 | (that, pre))
536536
case denot1: SingleDenotation =>
537537
that match {
538538
case denot2 @ MultiDenotation(denot21, denot22) =>
539-
denot2.derivedMultiDenotation(this | (denot21, pre), this | (denot22, pre))
539+
denot2.derivedUnionDenotation(this | (denot21, pre), this | (denot22, pre))
540540
case denot2: SingleDenotation =>
541541
unionDenot(denot1, denot2)
542542
}
@@ -558,9 +558,10 @@ object Denotations {
558558
final def isType = false
559559
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
560560
def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): Denotation =
561-
derivedMultiDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
561+
if (sig eq Signature.OverloadedSignature) this
562+
else derivedUnionDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
562563
def current(implicit ctx: Context): Denotation =
563-
derivedMultiDenotation(denot1.current, denot2.current)
564+
derivedUnionDenotation(denot1.current, denot2.current)
564565
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
565566
denot1.altsWith(p) ++ denot2.altsWith(p)
566567
def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = {
@@ -580,12 +581,15 @@ object Denotations {
580581
val d2 = denot2 accessibleFrom (pre, superAccess)
581582
if (!d1.exists) d2
582583
else if (!d2.exists) d1
583-
else derivedMultiDenotation(d1, d2)
584+
else derivedUnionDenotation(d1, d2)
584585
}
585586
def mapInfo(f: Type => Type)(implicit ctx: Context): Denotation =
586-
derivedMultiDenotation(denot1.mapInfo(f), denot2.mapInfo(f))
587-
def derivedMultiDenotation(d1: Denotation, d2: Denotation) =
588-
if ((d1 eq denot1) && (d2 eq denot2)) this else MultiDenotation(d1, d2)
587+
derivedUnionDenotation(denot1.mapInfo(f), denot2.mapInfo(f))
588+
def derivedUnionDenotation(d1: Denotation, d2: Denotation): Denotation =
589+
if ((d1 eq denot1) && (d2 eq denot2)) this
590+
else if (!d1.exists) d2
591+
else if (!d2.exists) d1
592+
else MultiDenotation(d1, d2)
589593
override def toString = alternatives.mkString(" <and> ")
590594

591595
private def multiHasNot(op: String): Nothing =

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

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ package dotc
33
package core
44

55
import Names._
6+
import NameKinds.SignedName
7+
import Types.{TypeRef, NameSpace, noNameSpace}
8+
import Symbols.Symbol
69
import Contexts.Context
710

811
/** Defines a common superclass of Name and Symbol and its Term/Type variants
912
* Designators are used in reference type to identity what is referred to.
1013
*/
1114
object Designators {
1215

13-
abstract class Designator extends util.DotClass {
16+
abstract class Designator extends util.DotClass { self =>
1417

1518
type ThisName <: Name
1619

@@ -23,8 +26,53 @@ object Designators {
2326

2427
def asTerm(implicit ctx: Context): TermDesignator = unsupported("asTerm")
2528
def asType(implicit ctx: Context): TypeDesignator = unsupported("asType")
29+
30+
def withNameSpace(space: NameSpace)(implicit ctx: Context): Designator { type ThisName = self.ThisName } =
31+
if (space == noNameSpace) this
32+
else localName(this.asInstanceOf[ThisName], space)
33+
34+
/** Localize this name to the owner of `sym` if `sym` is private */
35+
def localizeIfPrivate(sym: Symbol)(implicit ctx: Context): Designator { type ThisName = self.ThisName } =
36+
if (sym.isPrivate) withNameSpace(sym.owner.typeRef) else this
37+
38+
def withSig(sig: Signature): Designator{ type ThisName = TermName } = {
39+
val unsigned = this.asInstanceOf[TermName].exclude(SignedName)
40+
if (sig eq Signature.NotAMethod) unsigned else SignedName(unsigned, sig)
41+
}
2642
}
2743

2844
type TermDesignator = Designator { type ThisName = TermName }
2945
type TypeDesignator = Designator { type ThisName = TypeName }
46+
47+
/** Names that come with the namespace where they are defined.
48+
* Used to give a stable reference to private names, and also to
49+
* Scala 2x inner classes.
50+
*/
51+
case class LocalName[N <: Name](name: N, nameSpace: TypeRef) extends Designator {
52+
type ThisName = N
53+
54+
override def isTerm(implicit ctx: Context) = name.isTermName
55+
override def isType(implicit ctx: Context) = name.isTypeName
56+
57+
override def asTerm(implicit ctx: Context): TermDesignator = {
58+
name.asTermName
59+
this.asInstanceOf[TermDesignator]
60+
}
61+
override def asType(implicit ctx: Context): TypeDesignator = {
62+
name.asTypeName
63+
this.asInstanceOf[TypeDesignator]
64+
}
65+
66+
override def withNameSpace(space: NameSpace)(implicit ctx: Context) =
67+
name.withNameSpace(space).asInstanceOf[Designator { type ThisName = N }]
68+
69+
override def withSig(sig: Signature) =
70+
LocalName(name.withSig(sig).asInstanceOf[TermName], nameSpace)
71+
}
72+
73+
/** Introduced to overcome shortcoming with refined type inference of case classes:
74+
* LocalName's result type is always Designator, without a refinement.
75+
*/
76+
def localName[N <: Name](name: N, nameSpace: TypeRef): Designator { type ThisName = N } =
77+
LocalName(name, nameSpace).asInstanceOf[Designator { type ThisName = N }]
3078
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ object NameKinds {
5454
def unmangle(name: SimpleName): TermName = name
5555

5656
/** Turn a name of this kind consisting of an `underlying` prefix
57-
* and the given `info` into a string.
57+
* and the given `info` into a string. Used to turn structured into
58+
* simple name.
5859
*/
5960
def mkString(underlying: TermName, info: ThisInfo): String
6061

@@ -120,7 +121,7 @@ object NameKinds {
120121
class QualifiedNameKind(tag: Int, val separator: String)
121122
extends NameKind(tag) {
122123
type ThisInfo = QualInfo
123-
case class QualInfo(val name: SimpleName) extends Info with QualifiedInfo {
124+
case class QualInfo(name: SimpleName) extends Info with QualifiedInfo {
124125
override def map(f: SimpleName => SimpleName): NameInfo = new QualInfo(f(name))
125126
override def toString = s"$infoString $name"
126127
}
@@ -349,7 +350,6 @@ object NameKinds {
349350

350351
val SuperAccessorName = new PrefixNameKind(SUPERACCESSOR, "super$")
351352
val InitializerName = new PrefixNameKind(INITIALIZER, "initial$")
352-
val ShadowedName = new PrefixNameKind(SHADOWED, "(shadowed)")
353353
val ProtectedAccessorName = new PrefixNameKind(PROTECTEDACCESSOR, "protected$")
354354
val ProtectedSetterName = new PrefixNameKind(PROTECTEDSETTER, "protected$set") // dubious encoding, kept for Scala2 compatibility
355355
val AvoidClashName = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
@@ -363,9 +363,10 @@ object NameKinds {
363363
val ImplMethName = new SuffixNameKind(IMPLMETH, "$")
364364

365365
/** A name together with a signature. Used in Tasty trees. */
366-
object SignedName extends NameKind(63) {
366+
object SignedName extends NameKind(SIGNED) {
367367

368368
case class SignedInfo(sig: Signature) extends Info {
369+
assert(sig ne Signature.NotAMethod)
369370
override def toString = s"$infoString $sig"
370371
}
371372
type ThisInfo = SignedInfo

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,5 @@ object NameOps {
311311
case raw.BANG => UNARY_!
312312
case _ => name
313313
}
314-
315-
def withSig(sig: Signature) = SignedName(name.exclude(SignedName), sig)
316314
}
317315
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ object StdNames {
2121
final val TRAIT_SETTER_SEPARATOR = "$_setter_$"
2222
final val SUPER_PREFIX = "super$"
2323
final val INITIALIZER_PREFIX = "initial$"
24-
final val SHADOWED_PREFIX = "(shadowed)"
2524
final val AVOID_CLASH_SUFFIX = "$_avoid_name_clash_$"
2625
final val MODULE_SUFFIX = "$"
2726
final val NAME_JOIN = "$"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ trait Substituters { this: Context =>
295295
fs = fs.tail
296296
ts = ts.tail
297297
}
298-
tp.newLikeThis(apply(tp.prefix))
298+
tp.withPrefix(apply(tp.prefix))
299299
}
300300
catch {
301301
case ex: CyclicReference => tp.derivedSelect(apply(tp.prefix))

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ object Symbols {
394394

395395
type ThisName <: Name
396396

397-
//assert(id != 4285)
397+
//assert(id != 723)
398398

399399
/** The last denotation of this symbol */
400400
private[this] var lastDenot: SymDenotation = _
@@ -446,11 +446,23 @@ object Symbols {
446446
final def isClass: Boolean = isInstanceOf[ClassSymbol]
447447
final def asClass: ClassSymbol = asInstanceOf[ClassSymbol]
448448

449+
/** Test whether symbol is referenced symbolically. This
450+
* conservatively returns `false` if symbol does not yet have a denotation
451+
*/
449452
final def isReferencedSymbolically(implicit ctx: Context) = {
450453
val d = lastDenot
451454
d != null && (d.is(NonMember) || d.isTerm && ctx.phase.symbolicRefs)
452455
}
453456

457+
/** Test whether symbol is private. This
458+
* conservatively returns `false` if symbol does not yet have a denotation, or denotation
459+
* is a class that is not yet read.
460+
*/
461+
final def isPrivate(implicit ctx: Context) = {
462+
val d = lastDenot
463+
d != null && d.flagsUNSAFE.is(Private)
464+
}
465+
454466
/** The symbol's signature if it is completed or a method, NotAMethod otherwise. */
455467
final def signature(implicit ctx: Context) =
456468
if (lastDenot != null && (lastDenot.isCompleted || lastDenot.is(Method)))
@@ -489,7 +501,7 @@ object Symbols {
489501
if (this is Module) this.moduleClass.validFor |= InitialPeriod
490502
}
491503
else this.owner.asClass.ensureFreshScopeAfter(phase)
492-
if (!this.flagsUNSAFE.is(Private))
504+
if (!isPrivate)
493505
assert(phase.changesMembers, i"$this entered in ${this.owner} at undeclared phase $phase")
494506
entered
495507
}

0 commit comments

Comments
 (0)