Skip to content

Commit 4808d1d

Browse files
committed
Merge pull request #517 from dotty-staging/add/expand-privates
Expand private members if necessary
2 parents c834118 + 6ad6ca7 commit 4808d1d

12 files changed

+79
-43
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,12 @@ class Compiler {
6767
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
6868
new Flatten,
6969
new RestoreScopes),
70-
List(/*new PrivateToStatic,*/ new CollectEntryPoints, new LabelDefs, new ElimWildcardIdents, new TraitConstructors),
70+
List(/*new PrivateToStatic,*/
71+
new ExpandPrivate,
72+
new CollectEntryPoints,
73+
new LabelDefs,
74+
new ElimWildcardIdents,
75+
new TraitConstructors),
7176
List(new GenBCode)
7277
)
7378

src/dotty/tools/dotc/core/Flags.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,6 @@ object Flags {
367367
/** Symbol is defined in a super call */
368368
final val InSuperCall = commonFlag(46, "<in supercall>")
369369

370-
/** Symbol with private access is accessed outside its private scope */
371-
final val NotJavaPrivate = commonFlag(47, "<not-java-private>")
372-
373370
/** Denotation is in train of being loaded and completed, used to catch cyclic dependencies */
374371
final val Touched = commonFlag(48, "<touched>")
375372

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ object SymDenotations {
958958
*/
959959
final def accessBoundary(base: Symbol)(implicit ctx: Context): Symbol = {
960960
val fs = flags
961-
if (fs is (Private, butNot = NotJavaPrivate)) owner
961+
if (fs is Private) owner
962962
else if (fs is StaticProtected) defn.RootClass
963963
else if (privateWithin.exists && !ctx.phase.erasedTypes) privateWithin
964964
else if (fs is Protected) base
@@ -1049,6 +1049,18 @@ object SymDenotations {
10491049
*/
10501050
override def transformAfter(phase: DenotTransformer, f: SymDenotation => SymDenotation)(implicit ctx: Context): Unit =
10511051
super.transformAfter(phase, f)
1052+
1053+
/** If denotation is private, remove the Private flag and expand the name if necessary */
1054+
def ensureNotPrivate(implicit ctx: Context) =
1055+
if (is(Private))
1056+
copySymDenotation(
1057+
name =
1058+
if (is(ExpandedName) || isConstructor) this.name
1059+
else this.name.expandedName(initial.asSymDenotation.owner),
1060+
// need to use initial owner to disambiguate, as multiple private symbols with the same name
1061+
// might have been moved from different origins into the same class
1062+
initFlags = this.flags &~ Private | ExpandedName)
1063+
else this
10521064
}
10531065

10541066
/** The contents of a class definition during a period

src/dotty/tools/dotc/transform/Constructors.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
5656
private def mightBeDropped(sym: Symbol)(implicit ctx: Context) =
5757
sym.is(Private, butNot = KeeperFlags) && !sym.is(MutableParamAccessor)
5858

59-
private final val KeeperFlags = Method | Lazy | NotJavaPrivate
59+
private final val KeeperFlags = Method | Lazy
6060
private final val MutableParamAccessor = allOf(Mutable, ParamAccessor)
6161

6262
override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, IdentityDenotTransformer}
6+
import Contexts.Context
7+
import Symbols._
8+
import Scopes._
9+
import Flags._
10+
import StdNames._
11+
import SymDenotations._
12+
import Types._
13+
import collection.mutable
14+
import TreeTransforms._
15+
import Decorators._
16+
import ast.Trees._
17+
import TreeTransforms._
18+
19+
/** Make private term members that are accessed from another class
20+
* non-private by resetting the Private flag and expanding their name.
21+
*/
22+
class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
23+
import ast.tpd._
24+
25+
override def phaseName: String = "expandPrivate"
26+
27+
/** Make private terms accessed from different classes non-private.
28+
* Note: this happens also for accesses between class and linked module class.
29+
* If we change the scheme at one point to make static module class computations
30+
* static members of the companion class, we should tighten the condition below.
31+
*/
32+
private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) =
33+
if (d.is(PrivateTerm) && d.owner != ctx.owner.enclosingClass)
34+
d.ensureNotPrivate.installAfter(thisTransform)
35+
36+
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = {
37+
ensurePrivateAccessible(tree.symbol)
38+
tree
39+
}
40+
41+
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = {
42+
ensurePrivateAccessible(tree.symbol)
43+
tree
44+
}
45+
}

src/dotty/tools/dotc/transform/LambdaLift.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,10 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
290290
val (newOwner, maybeStatic) =
291291
if (lOwner is Package) (local.topLevelClass, JavaStatic)
292292
else (lOwner, EmptyFlags)
293-
val maybeNotJavaPrivate = if (calledFromInner(local)) NotJavaPrivate else EmptyFlags
294293
local.copySymDenotation(
295294
owner = newOwner,
296295
name = newName(local),
297-
initFlags = local.flags &~ InSuperCall | Private | maybeStatic | maybeNotJavaPrivate,
296+
initFlags = local.flags &~ InSuperCall | Private | maybeStatic,
298297
info = liftedInfo(local)).installAfter(thisTransform)
299298
if (local.isClass)
300299
for (member <- local.asClass.info.decls)

src/dotty/tools/dotc/transform/Mixin.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
7272

7373
override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation =
7474
if (sym.is(Accessor, butNot = Deferred) && sym.owner.is(Trait))
75-
sym.copySymDenotation(initFlags = sym.flags | Deferred)
75+
sym.copySymDenotation(initFlags = sym.flags | Deferred).ensureNotPrivate
7676
else
7777
sym
7878

src/dotty/tools/dotc/transform/PrivateToStatic.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform =>
3333
def shouldBeStatic(sd: SymDenotation)(implicit ctx: Context) =
3434
sd.current(ctx.withPhase(thisTransform)).asSymDenotation
3535
.is(PrivateMethod, butNot = Immovable) &&
36-
(sd.owner.is(Trait) || sd.is(NotJavaPrivate))
36+
sd.owner.is(Trait)
3737

3838
override def transformSym(sd: SymDenotation)(implicit ctx: Context): SymDenotation =
3939
if (shouldBeStatic(sd)) {

src/dotty/tools/dotc/transform/SuperAccessors.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
7575

7676
val superAcc = clazz.info.decl(supername).suchThat(_.signature == sym.signature).symbol orElse {
7777
ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz")
78-
val maybeDeferred = if (clazz is Trait) Deferred else EmptyFlags
78+
val deferredOrPrivate = if (clazz is Trait) Deferred else Private
7979
val acc = ctx.newSymbol(
80-
clazz, supername, SuperAccessor | Private | Artifact | Method | maybeDeferred,
80+
clazz, supername, SuperAccessor | Artifact | Method | deferredOrPrivate,
8181
sel.tpe.widenSingleton.ensureMethodic, coord = sym.coord).enteredAfter(thisTransformer)
8282
// Diagnostic for SI-7091
8383
if (!accDefs.contains(clazz))

src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ class TreeChecker extends Phase with SymTransformer {
8080
testDuplicate(sym, seenClasses, "class")
8181
}
8282

83+
if (sym.is(Method) && sym.is(Deferred) && sym.is(Private))
84+
assert(false, s"$sym is both Deferred and Private")
85+
8386
checkCompanion(symd)
8487

8588
symd

src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ object RefChecks {
362362

363363
def ignoreDeferred(member: SingleDenotation) =
364364
member.isType ||
365+
member.symbol.is(SuperAccessor) || // not yet synthesized
365366
member.symbol.is(JavaDefined) && hasJavaErasedOverriding(member.symbol)
366367

367368
// 2. Check that only abstract classes have deferred members
@@ -726,42 +727,14 @@ import RefChecks._
726727
* todo: But RefChecks is not done yet. It's still a somewhat dirty port from the Scala 2 version.
727728
* todo: move untrivial logic to their own mini-phases
728729
*/
729-
class RefChecks extends MiniPhase with SymTransformer { thisTransformer =>
730+
class RefChecks extends MiniPhase { thisTransformer =>
730731

731732
import tpd._
732733

733734
override def phaseName: String = "refchecks"
734735

735736
val treeTransform = new Transform(NoLevelInfo)
736737

737-
/** Ensure the following members are not private:
738-
* - term members of traits
739-
* - the primary constructor of a value class
740-
* - the parameter accessor of a value class
741-
*/
742-
override def transformSym(d: SymDenotation)(implicit ctx: Context) = {
743-
def mustBePublicInValueClass = d.isPrimaryConstructor || d.is(ParamAccessor)
744-
def mustBePublicInTrait = !d.is(Method) || d.isSetter || d.is(ParamAccessor)
745-
def mustBePublic = {
746-
val cls = d.owner
747-
(isDerivedValueClass(cls) && mustBePublicInValueClass ||
748-
cls.is(Trait) && mustBePublicInTrait)
749-
}
750-
if ((d is PrivateTerm) && mustBePublic) notPrivate(d) else d
751-
}
752-
753-
/** Make private terms accessed from different classes non-private.
754-
* Note: this happens also for accesses between class and linked module class.
755-
* If we change the scheme at one point to make static module class computations
756-
* static members of the companion class, we should tighten the condition below.
757-
*/
758-
private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) =
759-
if (d.is(PrivateTerm) && d.owner != ctx.owner.enclosingClass)
760-
notPrivate(d).installAfter(thisTransformer)
761-
762-
private def notPrivate(d: SymDenotation)(implicit ctx: Context) =
763-
d.copySymDenotation(initFlags = d.flags | NotJavaPrivate)
764-
765738
class Transform(currentLevel: RefChecks.OptLevelInfo = RefChecks.NoLevelInfo) extends TreeTransform {
766739
def phase = thisTransformer
767740

@@ -812,14 +785,12 @@ class RefChecks extends MiniPhase with SymTransformer { thisTransformer =>
812785

813786
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = {
814787
checkUndesiredProperties(tree.symbol, tree.pos)
815-
ensurePrivateAccessible(tree.symbol)
816788
currentLevel.enterReference(tree.symbol, tree.pos)
817789
tree
818790
}
819791

820792
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = {
821793
checkUndesiredProperties(tree.symbol, tree.pos)
822-
ensurePrivateAccessible(tree.symbol)
823794
tree
824795
}
825796

tests/pos/privates.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ trait Test {
66

77
private def bar() = foo()
88

9+
class Inner {
10+
foo()
11+
}
12+
913
}

0 commit comments

Comments
 (0)