@@ -30,15 +30,19 @@ object PatMat {
30
30
31
31
val sanitize = new TypeMap {
32
32
def apply (t : Type ): Type = t.widenExpr match {
33
- case t : TermRef
34
- if patmatGenerated(t.symbol) || t.info.isInstanceOf [ExprType ] => apply(t.info)
33
+ case t : TermRef if patmatGenerated(t.symbol) =>
34
+ t.info.widenExpr match {
35
+ case t1 : TermRef => apply(t1)
36
+ case _ => t
37
+ }
35
38
case t => mapOver(t)
36
39
}
37
40
}
38
41
39
42
case class BinderInfo (rhs : Tree )
40
43
41
44
val binding = mutable.Map [Symbol , AnyRef /* Tree | Node*/ ]()
45
+ val nonNull = mutable.Set [Symbol ]()
42
46
43
47
def rhs (sym : Symbol ) = {
44
48
assert(! sym.is(Label ))
@@ -64,15 +68,14 @@ object PatMat {
64
68
}
65
69
66
70
def newLabel (body : Node ) = {
67
- val label = freshLabel(MethodType (Nil , sanitize(body.tpe) ))
71
+ val label = freshLabel(MethodType (Nil , resultType ))
68
72
binding(label) = body
69
73
label
70
74
}
71
75
72
76
private var nxId = 0
73
77
74
78
sealed abstract class Node {
75
- def tpe : Type
76
79
val id = nxId
77
80
nxId += 1
78
81
}
@@ -81,21 +84,14 @@ object PatMat {
81
84
def this (scrut : Symbol , ons : Node , onf : Node ) = this (ref(scrut), ons, onf)
82
85
def condition : Tree
83
86
def pos : Position
84
- val tpe =
85
- try sanitize(onSuccess.tpe | onFailure.tpe)
86
- catch {
87
- case ex : AssertionError =>
88
- println(i " cannot | $onSuccess: ${onSuccess.tpe} with $onFailure ${onFailure.tpe}" )
89
- throw ex
90
- }
91
87
}
92
88
93
- class UnApplyTest (scrut : Symbol , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
89
+ class NonEmptyTest (scrut : Symbol , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
94
90
def pos = scrut.pos
95
91
def condition = scrutinee
96
92
.select(nme.isEmpty, _.info.isParameterless)
97
93
.select(nme.UNARY_! , _.info.isParameterless)
98
- override def toString = i " UnApplyTest ( $scrutinee) "
94
+ override def toString = i " NonEmptyTest ( $scrutinee) "
99
95
}
100
96
101
97
class TypeTest (scrut : Symbol , tpt : Tree , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
@@ -145,18 +141,22 @@ object PatMat {
145
141
override def toString = i " EqualTest( $tree == $scrutinee) "
146
142
}
147
143
144
+ class NonNullTest (scrut : Symbol , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
145
+ def pos = scrut.pos
146
+ def condition = scrutinee.testNotNull
147
+ }
148
+
148
149
class LengthTest (scrut : Symbol , len : Int , exact : Boolean , ons : Node , onf : Node ) extends Test (scrut, ons, onf) {
149
150
def pos = scrut.pos
150
- def condition = scrutinee
151
- .select(defn.Any_!= )
152
- .appliedTo(Literal (Constant (null )))
153
- .select(defn.Boolean_&& )
154
- .appliedTo(
151
+ def condition = // scrutinee
152
+ // .select(defn.Any_!=)
153
+ // .appliedTo(Literal(Constant(null)))
154
+ // .and(
155
155
scrutinee
156
156
.select(defn.Seq_lengthCompare .matchingMember(scrutinee.tpe))
157
157
.appliedTo(Literal (Constant (len)))
158
158
.select(if (exact) defn.Int_== else defn.Int_>= )
159
- .appliedTo(Literal (Constant (0 ))))
159
+ .appliedTo(Literal (Constant (0 )))// )
160
160
override def toString =
161
161
i " Lengthtest( $scrutinee.length ${if (exact) " ==" else " >=" } $len) "
162
162
}
@@ -167,17 +167,11 @@ object PatMat {
167
167
override def toString = i " GuardTest( $scrutinee) "
168
168
}
169
169
170
- case class LetNode (sym : TermSymbol , var body : Node ) extends Node {
171
- val tpe = sanitize(body.tpe)
172
- }
170
+ case class LetNode (sym : TermSymbol , var body : Node ) extends Node
173
171
174
- case class BodyNode (var tree : Tree ) extends Node {
175
- val tpe = tree.tpe
176
- }
172
+ case class BodyNode (var tree : Tree ) extends Node
177
173
178
- case class CallNode (label : TermSymbol ) extends Node {
179
- val tpe = label.info.finalResultType
180
- }
174
+ case class CallNode (label : TermSymbol ) extends Node
181
175
182
176
/** A conservative approximation of which patterns do not discern anything.
183
177
* They are discarded during the translation.
@@ -205,8 +199,12 @@ object PatMat {
205
199
def isSyntheticScala2Unapply (sym : Symbol ) =
206
200
sym.is(SyntheticCase ) && sym.owner.is(Scala2x )
207
201
208
- def swapBind (tree : Tree ) = tree match {
209
- case Bind (name, Typed (pat, tpt)) => Typed (cpy.Bind (tree)(name, pat), tpt)
202
+ def swapBind (tree : Tree ): Tree = tree match {
203
+ case Bind (name, pat0) =>
204
+ swapBind(pat0) match {
205
+ case Typed (pat, tpt) => Typed (cpy.Bind (tree)(name, pat), tpt)
206
+ case _ => tree
207
+ }
210
208
case _ => tree
211
209
}
212
210
@@ -263,17 +261,19 @@ object PatMat {
263
261
}
264
262
else {
265
263
assert(isGetMatch(unapp.tpe))
266
- val get = ref(unappResult).select(nme.get, _.info.isParameterless)
267
- letAbstract(get) { getResult =>
264
+ val argsPlan = {
265
+ val get = ref(unappResult).select(nme.get, _.info.isParameterless)
268
266
if (isUnapplySeq)
269
- translateUnApplySeq(getResult, args)
270
- else {
271
- val selectors =
272
- if (args.tail.isEmpty) ref(getResult) :: Nil
273
- else productSelectors(get.tpe).map(ref(getResult).select(_))
274
- new UnApplyTest (unappResult, translateArgs(selectors, args, onSuccess), onFailure)
275
- }
267
+ letAbstract(get)(translateUnApplySeq(_, args))
268
+ else
269
+ letAbstract(get) { getResult =>
270
+ val selectors =
271
+ if (args.tail.isEmpty) ref(getResult) :: Nil
272
+ else productSelectors(get.tpe).map(ref(getResult).select(_))
273
+ translateArgs(selectors, args, onSuccess)
274
+ }
276
275
}
276
+ new NonEmptyTest (unappResult, argsPlan, onFailure)
277
277
}
278
278
}
279
279
}
@@ -282,14 +282,18 @@ object PatMat {
282
282
swapBind(tree) match {
283
283
case Typed (pat, tpt) =>
284
284
new TypeTest (scrutinee, tpt,
285
- letAbstract(ref(scrutinee).asInstance(tpt.tpe))(casted =>
286
- translatePattern(casted, pat, onSuccess, onFailure)),
285
+ letAbstract(ref(scrutinee).asInstance(tpt.tpe)) { casted =>
286
+ nonNull += casted
287
+ translatePattern(casted, pat, onSuccess, onFailure)
288
+ },
287
289
onFailure)
288
290
case UnApply (extractor, implicits, args) =>
289
291
val mt @ MethodType (_) = extractor.tpe.widen
290
292
var unapp = extractor.appliedTo(ref(scrutinee).ensureConforms(mt.paramInfos.head))
291
293
if (implicits.nonEmpty) unapp = unapp.appliedToArgs(implicits)
292
- translateUnApply(unapp, args)
294
+ val unapplyPlan = translateUnApply(unapp, args)
295
+ if (scrutinee.info.isNotNull || nonNull(scrutinee)) unapplyPlan
296
+ else new NonNullTest (scrutinee, unapplyPlan, onFailure)
293
297
case Bind (name, body) =>
294
298
val body1 = translatePattern(scrutinee, body, onSuccess, onFailure)
295
299
if (name == nme.WILDCARD ) body1
0 commit comments