@@ -26,6 +26,74 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
26
26
override def runsAfter : Set [Class [_ <: Phase ]] =
27
27
Set (classOf [InterceptedMethods ], classOf [Splitter ], classOf [ElimRepeated ])
28
28
29
+ /* Before transform checks: errors and warnings */
30
+
31
+ private def checkStats (trees : List [Tree ])(implicit ctx : Context ): Unit = ctx.owner match {
32
+ case cls : ClassSymbol if cls.classDenot.classSymbol.isPhantomClass =>
33
+ trees.foreach {
34
+ case _ : TypeDef => // OK
35
+ case _ : ValOrDefDef => // OK
36
+ case tree =>
37
+ ctx.error(s " Phantom classes can not have expressions in statement position. " , tree.pos)
38
+ }
39
+
40
+ case _ =>
41
+ def checkTree (tree : Tree , pos : Position ): Unit = tree match {
42
+ case _ : TypeDef => // OK
43
+ case _ : ValOrDefDef => // OK
44
+ case Apply (Select (_ : This , name), _) if name == nme.CONSTRUCTOR => // OK
45
+ case _ if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
46
+ ctx.error(s " Expression returning a phantom type can not be in statement position. " , pos)
47
+ case _ => // OK
48
+ }
49
+ trees.foreach(tree => checkTree(tree, tree.pos))
50
+ }
51
+
52
+ private def checkDefDef (ddef : DefDef )(implicit ctx : Context ): Unit = {
53
+ def valOrDefDefDeclKeyword (flags : FlagSet ): String = {
54
+ if (! flags.is(Flags .Accessor )) " def"
55
+ else if (flags.is(Flags .Mutable )) " var"
56
+ else if (flags.is(Flags .Lazy )) " lazy val"
57
+ else " val"
58
+ }
59
+
60
+ def classDeclKeyword (flags : FlagSet ): String = {
61
+ if (flags.is(Flags .Trait )) " trait"
62
+ else if (flags.is(Flags .Abstract )) " abstract class"
63
+ else " class"
64
+ }
65
+
66
+ val flags = ddef.symbol.flags
67
+ if (ddef.tpt.tpe.derivesFrom(defn.PhantomAnyClass )) {
68
+ if (flags.is(Flags .Mutable ) || flags.is(Flags .Lazy ))
69
+ ctx.error(s " Can not define ' ${valOrDefDefDeclKeyword(flags)}' with phantom type. " , ddef.pos)
70
+ } else if (ddef.name != nme.CONSTRUCTOR ) {
71
+ ddef.symbol.owner match {
72
+ case cls : ClassSymbol if cls.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
73
+ val defKey = valOrDefDefDeclKeyword(flags)
74
+ val classKey = classDeclKeyword(ddef.symbol.owner.flags)
75
+ ctx.error(s " Can not define ' $defKey' with non phantom type in a phantom ' $classKey'. " , ddef.pos)
76
+
77
+ case _ => // OK
78
+ }
79
+ }
80
+
81
+ for (vparams <- ddef.vparamss) {
82
+ val numPhantoms = vparams.count(_.tpt.typeOpt.derivesFrom(defn.PhantomAnyClass ))
83
+ if (numPhantoms != 0 && numPhantoms != vparams.size)
84
+ ctx.error(" Lists of parameters with runtime and phantom types are not allowed." , vparams.head.pos)
85
+ else if (ddef.name == nme.CONSTRUCTOR && numPhantoms != vparams.size) {
86
+ ctx.owner match {
87
+ case cls : ClassSymbol if cls.classDenot.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
88
+ ctx.error(" Phantom class constructors can not have non phantom parameters." , vparams.head.pos)
89
+ case _ =>
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ /* After transform checks */
96
+
29
97
/** Check what the phase achieves, to be called at any point after it is finished.
30
98
*/
31
99
override def checkPostCondition (tree : Tree )(implicit ctx : Context ): Unit = {
@@ -40,7 +108,7 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
40
108
super .checkPostCondition(tree)
41
109
}
42
110
43
- // Transform trees
111
+ /* Tree transform */
44
112
45
113
override def transformStats (trees : List [Tree ])(implicit ctx : Context , info : TransformerInfo ): List [Tree ] = {
46
114
checkStats(trees)
@@ -78,29 +146,10 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
78
146
}
79
147
80
148
override def transformDefDef (ddef : DefDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
81
- def filterPhantom (vparamss : List [List [ValDef ]]): List [List [ValDef ]] = {
82
- vparamss.filter { vparams =>
83
- val phantoms = vparams.filter(_.tpt.typeOpt.derivesFrom(defn.PhantomAnyClass ))
84
- if (phantoms.size != vparams.size) {
85
- if (phantoms.nonEmpty)
86
- ctx.error(" Lists of parameters with runtime and phantom types are not allowed." , vparams.head.pos)
87
- else if (ddef.name == nme.CONSTRUCTOR ) {
88
- ctx.owner match {
89
- case cls : ClassSymbol if cls.classDenot.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
90
- ctx.error(" Phantom class constructors can not have non phantom parameters." , vparams.head.pos)
91
- case _ =>
92
- }
93
- }
94
- }
95
-
96
- phantoms.isEmpty
97
- }
98
- }
99
- val newVparamss = filterPhantom(ddef.vparamss)
100
- val ddef1 =
101
- if (ddef.vparamss.length == newVparamss.length) ddef
102
- else cpy.DefDef (ddef)(vparamss = newVparamss)
103
- super .transformDefDef(ddef1)
149
+ checkDefDef(ddef)
150
+ val newVparamss = ddef.vparamss.map(_.filter(vparam => ! vparam.tpt.typeOpt.derivesFrom(defn.PhantomAnyClass )))
151
+ if (newVparamss == ddef.vparamss) ddef
152
+ else cpy.DefDef (ddef)(vparamss = newVparamss)
104
153
}
105
154
106
155
private def filterStats (trees : List [Tree ])(implicit ctx : Context ): List [Tree ] = {
@@ -111,60 +160,7 @@ class PhantomRefErasure extends MiniPhaseTransform with InfoTransformer {
111
160
flatStats.filter(! _.tpe.derivesFrom(defn.PhantomAnyClass ))
112
161
}
113
162
114
- private def checkStats (trees : List [Tree ])(implicit ctx : Context ): Unit = ctx.owner match {
115
- case cls : ClassSymbol if cls.classDenot.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
116
- trees.foreach {
117
- case tree : TypeDef => // OK
118
- case tree : ValDef => // OK
119
- case tree : DefDef => checkDefDef(tree)
120
- case tree =>
121
- ctx.error(s " Phantom classes can not have expressions in statement position. " , tree.pos)
122
- }
123
-
124
- case _ =>
125
- def checkTree (tree : Tree , pos : Position ): Unit = tree match {
126
- case _ : TypeDef => // OK
127
- case _ : ValDef => // OK
128
- case tree : DefDef => checkDefDef(tree)
129
- case Apply (Select (_ : This , name), _) if name == nme.CONSTRUCTOR => // OK
130
- case _ if tree.tpe.derivesFrom(defn.PhantomAnyClass ) =>
131
- ctx.error(s " Expression returning a phantom type can not be in statement position. " , pos)
132
- case _ =>
133
- }
134
- trees.foreach(tree => checkTree(tree, tree.pos))
135
- }
136
-
137
- private def checkDefDef (ddef : DefDef )(implicit ctx : Context ): Unit = {
138
- def valOrDefDefDeclKeyword (flags : FlagSet ): String = {
139
- if (! flags.is(Flags .Accessor )) " def"
140
- else if (flags.is(Flags .Mutable )) " var"
141
- else if (flags.is(Flags .Lazy )) " lazy val"
142
- else " val"
143
- }
144
-
145
- def classDeclKeyword (flags : FlagSet ): String = {
146
- if (flags.is(Flags .Trait )) " trait"
147
- else if (flags.is(Flags .Abstract )) " abstract class"
148
- else " class"
149
- }
150
-
151
- val flags = ddef.symbol.flags
152
- if (ddef.tpt.tpe.derivesFrom(defn.PhantomAnyClass )) {
153
- if (flags.is(Flags .Mutable ) || flags.is(Flags .Lazy ))
154
- ctx.error(s " Can not define ' ${valOrDefDefDeclKeyword(flags)}' with phantom type. " , ddef.pos)
155
- } else if (ddef.name != nme.CONSTRUCTOR ) {
156
- ddef.symbol.owner match {
157
- case cls : ClassSymbol if cls.classSymbol.derivesFrom(defn.PhantomAnyClass ) =>
158
- val defKey = valOrDefDefDeclKeyword(flags)
159
- val classKey = classDeclKeyword(ddef.symbol.owner.flags)
160
- ctx.error(s " Can not define ' $defKey' with non phantom type in a phantom ' $classKey'. " , ddef.pos)
161
-
162
- case _ => // OK
163
- }
164
- }
165
- }
166
-
167
- // Transform symbols
163
+ /* Symbol transform */
168
164
169
165
def transformInfo (tp : Type , sym : Symbol )(implicit ctx : Context ): Type = erasedPhantoms(tp)
170
166
0 commit comments