@@ -9,16 +9,15 @@ import core.Types._
9
9
import core .Decorators ._
10
10
import dotty .tools .dotc .ast .{Trees , tpd }
11
11
import ast .Trees ._
12
-
12
+ import dotty . tools . dotc . core . StdNames . _
13
13
import dotty .tools .dotc .core .Flags
14
14
import dotty .tools .dotc .transform .TreeTransforms .{MiniPhaseTransform , TransformerInfo , TreeTransform }
15
+ import dotty .tools .dotc .util .Positions .Position
15
16
16
17
import scala .annotation .tailrec
17
18
18
19
class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
19
- thisTransformer =>
20
-
21
- import dotty .tools .dotc .ast .tpd ._
20
+ import tpd ._
22
21
23
22
override def phaseName : String = " phantomRefErasure"
24
23
@@ -28,7 +27,7 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
28
27
29
28
/** Check what the phase achieves, to be called at any point after it is finished.
30
29
*/
31
- override def checkPostCondition (tree : tpd. Tree )(implicit ctx : Context ): Unit = {
30
+ override def checkPostCondition (tree : Tree )(implicit ctx : Context ): Unit = {
32
31
def assertNotPhantom (tpe : Type ): Unit =
33
32
assert(! tpe.derivesFrom(defn.PhantomAnyClass ), " All phantom type values should be erased in " + tree)
34
33
@@ -42,17 +41,32 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
42
41
43
42
// Transform trees
44
43
45
- override def transformStats (trees : List [tpd.Tree ])(implicit ctx : Context , info : TransformerInfo ): List [tpd.Tree ] = {
46
- trees.foreach {
47
- case tree @ Apply (fun, _) if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
48
- ctx.error(s " Functions returning a phantom type can not be in statement position. " , fun.pos)
49
- case tree @ TypeApply (fun, _) if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
50
- ctx.error(s " Functions returning a phantom type can not be in statement position. " , fun.pos)
51
- case tree : Select if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
52
- ctx.error(s " Fields containing a phantom type can not be accessed in statement position. " , tree.pos)
44
+ override def transformStats (trees : List [Tree ])(implicit ctx : Context , info : TransformerInfo ): List [Tree ] = {
45
+ ctx.owner match {
46
+ case cls : ClassSymbol if cls.classDenot.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
47
+ trees.foreach {
48
+ case tree : TypeDef =>
49
+ case tree : DefDef =>
50
+ case tree =>
51
+ ctx.error(s " Phantom classes can not have expressions in statement position. " , tree.pos)
52
+ }
53
53
case _ =>
54
+ trees.foreach {
55
+ case tree@ Apply (fun, _) =>
56
+ fun match {
57
+ case Select (_ : This , name) if name == nme.CONSTRUCTOR =>
58
+ case _ if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
59
+ ctx.error(s " Functions returning a phantom type can not be in statement position. " , fun.pos)
60
+ case _ =>
61
+ }
62
+ case tree@ TypeApply (fun, _) if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
63
+ ctx.error(s " Functions returning a phantom type can not be in statement position. " , fun.pos)
64
+ case tree : Select if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
65
+ ctx.error(s " Fields containing a phantom type can not be accessed in statement position. " , tree.pos)
66
+ case _ =>
67
+ }
54
68
}
55
- super .transformStats( trees)
69
+ trees
56
70
}
57
71
58
72
override def transformApply (tree : Apply )(implicit ctx : Context , info : TransformerInfo ): Tree = {
@@ -80,8 +94,18 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
80
94
def filterPhantom (vparamss : List [List [ValDef ]]): List [List [ValDef ]] = {
81
95
vparamss.filter { vparams =>
82
96
val phantoms = vparams.filter(_.tpt.typeOpt.derivesFrom(defn.PhantomAnyClass ))
83
- if (phantoms.nonEmpty && phantoms.size != vparams.size)
84
- ctx.error(" Lists of parameters with runtime and phantom types are not allowed." , vparams.head.pos)
97
+ if (phantoms.size != vparams.size) {
98
+ if (phantoms.nonEmpty)
99
+ ctx.error(" Lists of parameters with runtime and phantom types are not allowed." , vparams.head.pos)
100
+ else if (ddef.name == nme.CONSTRUCTOR ) {
101
+ ctx.owner match {
102
+ case cls : ClassSymbol if cls.classDenot.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
103
+ ctx.error(" Phantom class constructors can not have non phantom parameters." , vparams.head.pos)
104
+ case _ =>
105
+ }
106
+ }
107
+ }
108
+
85
109
phantoms.isEmpty
86
110
}
87
111
}
0 commit comments