Skip to content

Commit 250418e

Browse files
committed
New phase: PrivateToStatic
Make private methods in traits static, so that we do not need to give a default for them.
1 parent d907f26 commit 250418e

File tree

8 files changed

+197
-4
lines changed

8 files changed

+197
-4
lines changed

src/dotty/tools/dotc/Compiler.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ class Compiler {
5757
new Constructors),
5858
List(new LambdaLift,
5959
new Flatten,
60-
new RestoreScopes)
60+
new RestoreScopes),
61+
List(new PrivateToStatic)
6162
)
6263

6364
var runId = 1

src/dotty/tools/dotc/ast/tpd.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
263263
case _ =>
264264
false
265265
}
266-
try test
266+
try test || tp.symbol.is(JavaStatic)
267267
catch { // See remark in SymDenotations#accessWithin
268268
case ex: NotDefinedHere => test(ctx.addMode(Mode.FutureDefsOK))
269269
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ object Flags {
512512
/** Labeled `private` or `final` */
513513
final val PrivateOrFinal = Private | Final
514514

515+
/** A private method */
516+
final val PrivateMethod = allOf(Private, Method)
517+
515518
/** A type parameter with synthesized name */
516519
final val ExpandedTypeParam = allOf(ExpandedName, TypeParam)
517520

src/dotty/tools/dotc/printing/RefinedPrinter.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
3636
override def nameString(name: Name): String = name.decode.toString
3737

3838
override protected def simpleNameString(sym: Symbol): String =
39-
sym.originalName.decode.toString
39+
sym.name.decode.toString
4040

4141
override protected def fullNameOwner(sym: Symbol) = {
4242
val owner = super.fullNameOwner(sym)
@@ -222,7 +222,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
222222
"`" ~ toText(id.name) ~ "`"
223223
case Ident(name) =>
224224
tree.typeOpt match {
225-
case tp: NamedType if name != nme.WILDCARD => toTextPrefix(tp.prefix) ~ selectionString(tp)
225+
case tp: NamedType if name != nme.WILDCARD =>
226+
val pre = if (tp.symbol is JavaStatic) tp.prefix.widen else tp.prefix
227+
toTextPrefix(pre) ~ selectionString(tp)
226228
case _ => toText(name)
227229
}
228230
case tree @ Select(qual, name) =>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import DenotTransformers.SymTransformer
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.TransformerInfo
18+
19+
/** The preceding lambda lift and flatten phases move symbols to different scopes
20+
* and rename them. This miniphase cleans up afterwards and makes sure that all
21+
* class scopes contain the symbols defined in them.
22+
*/
23+
class PrivateToStatic extends MiniPhase with SymTransformer { thisTransform =>
24+
import ast.tpd._
25+
override def phaseName = "privateToStatic"
26+
override def relaxedTyping = true
27+
28+
private val Immovable = Deferred | Accessor | JavaStatic
29+
30+
def shouldBeStatic(sd: SymDenotation)(implicit ctx: Context) =
31+
sd.current(ctx.withPhase(thisTransform)).asInstanceOf[SymDenotation]
32+
.is(PrivateMethod, butNot = Immovable) &&
33+
(sd.owner.is(Trait) || sd.is(NotJavaPrivate))
34+
35+
override def transformSym(sd: SymDenotation)(implicit ctx: Context): SymDenotation =
36+
if (shouldBeStatic(sd)) {
37+
val mt @ MethodType(pnames, ptypes) = sd.info
38+
sd.copySymDenotation(
39+
initFlags = sd.flags | JavaStatic,
40+
info = MethodType(nme.SELF :: pnames, sd.owner.thisType :: ptypes, mt.resultType))
41+
}
42+
else sd
43+
44+
val treeTransform = new Transform(NoSymbol)
45+
46+
class Transform(thisParam: Symbol) extends TreeTransform {
47+
def phase = thisTransform
48+
override def treeTransformPhase = thisTransform.next
49+
50+
override def prepareForDefDef(tree: DefDef)(implicit ctx: Context) =
51+
if (shouldBeStatic(tree.symbol)) {
52+
val selfParam = ctx.newSymbol(tree.symbol, nme.SELF, Param, tree.symbol.owner.thisType, coord = tree.pos)
53+
new Transform(selfParam)
54+
}
55+
else this
56+
57+
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo) =
58+
if (shouldBeStatic(tree.symbol)) {
59+
val thisParamDef = ValDef(thisParam.asTerm)
60+
val vparams :: Nil = tree.vparamss
61+
cpy.DefDef(tree)(
62+
mods = tree.mods | JavaStatic,
63+
vparamss = (thisParamDef :: vparams) :: Nil)
64+
}
65+
else tree
66+
67+
override def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo) =
68+
if (shouldBeStatic(ctx.owner.enclosingMethod)) ref(thisParam).withPos(tree.pos)
69+
else tree
70+
71+
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo) =
72+
tree.fun match {
73+
case fun @ Select(qual, name) if shouldBeStatic(fun.symbol) =>
74+
println(i"mapping $tree to ${cpy.Ident(fun)(name)} (${qual :: tree.args}%, %)")
75+
cpy.Apply(tree)(ref(fun.symbol).withPos(fun.pos), qual :: tree.args)
76+
case _ =>
77+
tree
78+
}
79+
80+
override def transformClosure(tree: Closure)(implicit ctx: Context, info: TransformerInfo) =
81+
tree.meth match {
82+
case meth @ Select(qual, name) if shouldBeStatic(meth.symbol) =>
83+
cpy.Closure(tree)(
84+
env = qual :: tree.env,
85+
meth = ref(meth.symbol).withPos(meth.pos))
86+
case _ =>
87+
tree
88+
}
89+
}
90+
}

tests/pos/CoderTrait.scala

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import collection.mutable.HashMap
2+
3+
trait CoderTrait {
4+
5+
val words: List[String]
6+
7+
(2 -> "ABC", new ArrowAssoc('3') -> "DEF")
8+
9+
private val mnemonics = Map(
10+
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
11+
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
12+
13+
14+
('1', "1") match {
15+
case (digit, str) => true
16+
case _ => false
17+
}
18+
19+
/** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
20+
private val charCode0: Map[Char, Char] = mnemonics withFilter {
21+
case (digit, str) => true
22+
case _ => false
23+
} flatMap { x$1 =>
24+
x$1 match {
25+
case (digit, str) => str map (ltr => ltr -> digit)
26+
}
27+
}
28+
29+
private val charCode: Map[Char, Char] =
30+
for ((digit, str) <- mnemonics; ltr <- str) yield ltr -> digit
31+
32+
/** Maps a word to the digit string it can represent */
33+
private def wordCode(word: String): String = word map charCode
34+
35+
/** A map from digit strings to the words that represent them */
36+
private val wordsForNum: Map[String, List[String]] =
37+
words groupBy wordCode withDefaultValue Nil
38+
39+
/** All ways to encode a number as a list of words */
40+
def encode(number: String): Set[List[String]] =
41+
if (number.isEmpty) Set(Nil)
42+
else {
43+
for {
44+
splitPoint <- 1 to number.length
45+
word <- wordsForNum(number take splitPoint)
46+
rest <- encode(number drop splitPoint)
47+
} yield word :: rest
48+
}.toSet
49+
50+
/** Maps a number to a list of all word phrases that can represent it */
51+
def translate(number: String): Set[String] = encode(number) map (_ mkString " ")
52+
53+
}
54+
55+
object Coder {
56+
def main(args : Array[String]) : Unit = {
57+
val coder = new CoderTrait {
58+
val words = List("Scala", "sobls", "Python", "Ruby", "C", "A", "rocks", "sucks", "works", "Racka")
59+
}
60+
// println(coder.wordsForNum)
61+
println(coder.translate("7225276257"))
62+
}
63+
}

tests/pos/privates.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
trait Test {
2+
3+
private val x = 2
4+
5+
private def foo() = x * x
6+
7+
private def bar() = foo()
8+
9+
}

tests/pos/traits.scala

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
trait B {
2+
3+
val z: Int
4+
5+
}
6+
7+
trait T {
8+
9+
var x = 2
10+
11+
private var xp = 2
12+
13+
val y = 3
14+
15+
private val yp = 3
16+
17+
val z = 4
18+
19+
x = 4
20+
21+
xp = 4
22+
23+
}
24+
25+
class C extends T

0 commit comments

Comments
 (0)