@@ -198,6 +198,8 @@ object PatternMatcher {
198
198
case object NonNullTest extends Test // scrutinee ne null
199
199
case object GuardTest extends Test // scrutinee
200
200
201
+ val noLengthTest = LengthTest (0 , exact = false )
202
+
201
203
// ------- Generating plans from trees ------------------------
202
204
203
205
/** A set of variabes that are known to be not null */
@@ -291,12 +293,14 @@ object PatternMatcher {
291
293
/** Plan for matching the sequence in `seqSym` against sequence elements `args`.
292
294
* If `exact` is true, the sequence is not permitted to have any elements following `args`.
293
295
*/
294
- def matchElemsPlan (seqSym : Symbol , args : List [Tree ], exact : Boolean , onSuccess : Plan ) = {
295
- val selectors = args.indices.toList.map(idx =>
296
- ref(seqSym).select(defn.Seq_apply .matchingMember(seqSym.info)).appliedTo(Literal (Constant (idx))))
297
- TestPlan (LengthTest (args.length, exact), seqSym, seqSym.span,
298
- matchArgsPlan(selectors, args, onSuccess))
299
- }
296
+ def matchElemsPlan (seqSym : Symbol , args : List [Tree ], lengthTest : LengthTest , onSuccess : Plan ) =
297
+ val selectors = args.indices.toList.map: idx =>
298
+ ref(seqSym).select(defn.Seq_apply .matchingMember(seqSym.info)).appliedTo(Literal (Constant (idx)))
299
+ if lengthTest.len == 0 && lengthTest.exact == false then // redundant test
300
+ matchArgsPlan(selectors, args, onSuccess)
301
+ else
302
+ TestPlan (lengthTest, seqSym, seqSym.span,
303
+ matchArgsPlan(selectors, args, onSuccess))
300
304
301
305
/** Plan for matching the sequence in `getResult` against sequence elements
302
306
* `args`. Sequence elements may contain a varargs argument.
@@ -307,15 +311,13 @@ object PatternMatcher {
307
311
* generates code which is equivalent to:
308
312
*
309
313
* if lst != null then
310
- * if lst.lengthCompare >= 1 then
314
+ * if lst.lengthCompare >= 3 then
311
315
* if lst(0) == 1 then
312
316
* val x1 = lst.drop(1)
313
317
* val xs = x1.dropRight(2)
314
318
* val x2 = lst.takeRight(2)
315
- * if x2.lengthCompare >= 2 then
316
- * if x2(0) == 2 then
317
- * if x2(1) == 3 then
318
- * return[matchResult] ...
319
+ * if x2(0) == 2 && x2(1) == 3 then
320
+ * return[matchResult] ...
319
321
*/
320
322
def unapplySeqPlan (getResult : Symbol , args : List [Tree ]): Plan =
321
323
val (leading, varargAndRest) = args.span:
@@ -345,11 +347,13 @@ object PatternMatcher {
345
347
.appliedTo(Literal (Constant (trailing.length)))
346
348
val matchTrailing =
347
349
letAbstract(rest): trailingResult =>
348
- matchElemsPlan(trailingResult, trailing, exact = true , onSuccess)
350
+ matchElemsPlan(trailingResult, trailing, noLengthTest , onSuccess)
349
351
patternPlan(seqResult, arg, matchTrailing)
350
- matchElemsPlan(getResult, leading, exact = false , matchRemaining)
352
+ matchElemsPlan(getResult, leading,
353
+ LengthTest (leading.length + trailing.length, exact = false ),
354
+ matchRemaining)
351
355
case _ =>
352
- matchElemsPlan(getResult, args, exact = true , onSuccess)
356
+ matchElemsPlan(getResult, args, LengthTest (args.length, exact = true ) , onSuccess)
353
357
354
358
/** Plan for matching the sequence in `getResult`
355
359
*
@@ -518,7 +522,7 @@ object PatternMatcher {
518
522
case WildcardPattern () | This (_) =>
519
523
onSuccess
520
524
case SeqLiteral (pats, _) =>
521
- matchElemsPlan(scrutinee, pats, exact = true , onSuccess)
525
+ matchElemsPlan(scrutinee, pats, LengthTest (pats.length, exact = true ) , onSuccess)
522
526
case _ =>
523
527
TestPlan (EqualTest (tree), scrutinee, tree.span, onSuccess)
524
528
}
0 commit comments