Skip to content

Commit d9c2157

Browse files
committed
New miniphase: ExpandPrivate
A late miniphase which resets private flag of all members that are not accessed from within same class. Replaces logic in RefChecks. Doing this late has two advantages - we can use name expansion, because references are symbolic, so the names of symbols and references to them do not need to correspond anymore. - we can automatically correct for symbols moved in earlier phases (e.g. lifted out by LambdaLift).
1 parent a263b5f commit d9c2157

File tree

4 files changed

+60
-30
lines changed

4 files changed

+60
-30
lines changed

src/dotty/tools/dotc/Compiler.scala

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import DenotTransformers.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+
/** Makes private methods static, provided they not deferred, accessors, or static,
20+
* by rewriting a method `m` in class `C` as follows:
21+
*
22+
* private def m(ps) = e
23+
*
24+
* --> private static def($this: C, ps) = [this -> $this] e
25+
*/
26+
class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
27+
import ast.tpd._
28+
29+
override def phaseName: String = "expandPrivate"
30+
31+
/** Make private terms accessed from different classes non-private.
32+
* Note: this happens also for accesses between class and linked module class.
33+
* If we change the scheme at one point to make static module class computations
34+
* static members of the companion class, we should tighten the condition below.
35+
*/
36+
private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) =
37+
if (d.is(PrivateTerm) && d.owner != ctx.owner.enclosingClass)
38+
d.ensureNotPrivate.installAfter(thisTransform)
39+
40+
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = {
41+
ensurePrivateAccessible(tree.symbol)
42+
tree
43+
}
44+
45+
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = {
46+
ensurePrivateAccessible(tree.symbol)
47+
tree
48+
}
49+
}

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

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -726,40 +726,14 @@ import RefChecks._
726726
* todo: But RefChecks is not done yet. It's still a somewhat dirty port from the Scala 2 version.
727727
* todo: move untrivial logic to their own mini-phases
728728
*/
729-
class RefChecks extends MiniPhase with SymTransformer { thisTransformer =>
729+
class RefChecks extends MiniPhase { thisTransformer =>
730730

731731
import tpd._
732732

733733
override def phaseName: String = "refchecks"
734734

735735
val treeTransform = new Transform(NoLevelInfo)
736736

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 mustBePublic = {
745-
val cls = d.owner
746-
(isDerivedValueClass(cls) && mustBePublicInValueClass
747-
}
748-
if ((d is PrivateTerm) && mustBePublic) notPrivate(d) else d
749-
}
750-
751-
/** Make private terms accessed from different classes non-private.
752-
* Note: this happens also for accesses between class and linked module class.
753-
* If we change the scheme at one point to make static module class computations
754-
* static members of the companion class, we should tighten the condition below.
755-
*/
756-
private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) =
757-
if (d.is(PrivateTerm) && d.owner != ctx.owner.enclosingClass)
758-
notPrivate(d).installAfter(thisTransformer)
759-
760-
private def notPrivate(d: SymDenotation)(implicit ctx: Context) =
761-
d.copySymDenotation(initFlags = d.flags | NotJavaPrivate)
762-
763737
class Transform(currentLevel: RefChecks.OptLevelInfo = RefChecks.NoLevelInfo) extends TreeTransform {
764738
def phase = thisTransformer
765739

@@ -810,14 +784,12 @@ class RefChecks extends MiniPhase with SymTransformer { thisTransformer =>
810784

811785
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = {
812786
checkUndesiredProperties(tree.symbol, tree.pos)
813-
ensurePrivateAccessible(tree.symbol)
814787
currentLevel.enterReference(tree.symbol, tree.pos)
815788
tree
816789
}
817790

818791
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = {
819792
checkUndesiredProperties(tree.symbol, tree.pos)
820-
ensurePrivateAccessible(tree.symbol)
821793
tree
822794
}
823795

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)