Skip to content

Commit 813b5f3

Browse files
committed
New phase: crossCastAnd.
This transform makes sure that all private member selections from AndTypes are performed from the first component of AndType. This is needed for correctness of erasure. See `tests/run/PrivateAnd.scala`
1 parent 30dc924 commit 813b5f3

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Compiler {
5252
List(new PatternMatcher,
5353
new ExplicitOuter,
5454
new ExplicitSelf,
55+
new CrossCastAnd,
5556
new Splitter),
5657
List(new VCInlineMethods,
5758
new SeqLiterals,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.ast.tpd
4+
import dotty.tools.dotc.core.Contexts.Context
5+
import dotty.tools.dotc.core.Flags
6+
import dotty.tools.dotc.core.Types.{NoType, Type, AndType}
7+
import dotty.tools.dotc.transform.TreeTransforms._
8+
import tpd._
9+
10+
import scala.collection.mutable.ListBuffer
11+
12+
13+
/**
14+
* This transform makes sure that all private member selections from
15+
* AndTypes are performed from the first component of AndType.
16+
* This is needed for correctness of erasure. See `tests/run/PrivateAnd.scala`
17+
*/
18+
class CrossCastAnd extends MiniPhaseTransform { thisTransform =>
19+
20+
override def phaseName: String = "crossCast"
21+
22+
override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
23+
if (tree.symbol.is(Flags.Private)) {
24+
// all private member selections have a symbol
25+
tree.qualifier.tpe.widen match {
26+
case t @ AndType(l, _) =>
27+
28+
// find a component of and type that owns the symbol
29+
def findType(tp: Type): Type = {
30+
tp match {
31+
case AndType(l, r) =>
32+
findType(l).orElse(findType(r))
33+
case t =>
34+
if (t.decl(tree.symbol.name).suchThat(_ == tree.symbol).exists)
35+
t
36+
else NoType
37+
}
38+
}
39+
40+
val tp = findType(t)
41+
if (l eq tp) tree
42+
else tree.qualifier.asInstance(AndType(tp, t)).select(tree.symbol)
43+
case _ => tree
44+
}
45+
}
46+
else tree
47+
}
48+
}

0 commit comments

Comments
 (0)