Skip to content

Commit edfa025

Browse files
committed
Make patterns fail fast
1 parent dd7589c commit edfa025

File tree

1 file changed

+113
-74
lines changed

1 file changed

+113
-74
lines changed

compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala

Lines changed: 113 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ object QuoteMatcher {
181181
case _ => None
182182
end TypeTreeTypeTest
183183

184-
(scrutinee, pattern) match
184+
val res = (scrutinee, pattern) match
185185

186186
/* Term hole */
187187
// Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree
@@ -251,109 +251,148 @@ object QuoteMatcher {
251251
matched
252252

253253
/* Match application */
254-
case (Apply(fn1, args1), Apply(fn2, args2)) =>
255-
fn1 =?= fn2 &&& args1 =?= args2
254+
case (Apply(fn1, args1), _) =>
255+
pattern match
256+
case Apply(fn2, args2) =>
257+
fn1 =?= fn2 &&& args1 =?= args2
258+
case _ => notMatched
256259

257260
/* Match type application */
258-
case (TypeApply(fn1, args1), TypeApply(fn2, args2)) =>
259-
fn1 =?= fn2 &&& args1 =?= args2
261+
case (TypeApply(fn1, args1), _) =>
262+
pattern match
263+
case TypeApply(fn2, args2) =>
264+
fn1 =?= fn2 &&& args1 =?= args2
265+
case _ => notMatched
260266

261267
/* Match block */
262-
case (Block(stat1 :: stats1, expr1), Block(stat2 :: stats2, expr2)) =>
263-
val newEnv = (stat1, stat2) match {
264-
case (stat1: MemberDef, stat2: MemberDef) =>
265-
summon[Env] + (stat1.symbol -> stat2.symbol)
266-
case _ =>
267-
summon[Env]
268-
}
269-
withEnv(newEnv) {
270-
stat1 =?= stat2 &&& Block(stats1, expr1) =?= Block(stats2, expr2)
271-
}
268+
case (Block(stat1 :: stats1, expr1), _) =>
269+
pattern match
270+
case Block(stat2 :: stats2, expr2) =>
271+
val newEnv = (stat1, stat2) match {
272+
case (stat1: MemberDef, stat2: MemberDef) =>
273+
summon[Env] + (stat1.symbol -> stat2.symbol)
274+
case _ =>
275+
summon[Env]
276+
}
277+
withEnv(newEnv) {
278+
stat1 =?= stat2 &&& Block(stats1, expr1) =?= Block(stats2, expr2)
279+
}
280+
case _ => notMatched
272281

273282
/* Match if */
274-
case (If(cond1, thenp1, elsep1), If(cond2, thenp2, elsep2)) =>
275-
cond1 =?= cond2 &&& thenp1 =?= thenp2 &&& elsep1 =?= elsep2
283+
case (If(cond1, thenp1, elsep1), _) =>
284+
pattern match
285+
case If(cond2, thenp2, elsep2) =>
286+
cond1 =?= cond2 &&& thenp1 =?= thenp2 &&& elsep1 =?= elsep2
287+
case _ => notMatched
276288

277289
/* Match while */
278-
case (WhileDo(cond1, body1), WhileDo(cond2, body2)) =>
279-
cond1 =?= cond2 &&& body1 =?= body2
290+
case (WhileDo(cond1, body1), _) =>
291+
pattern match
292+
case WhileDo(cond2, body2) => cond1 =?= cond2 &&& body1 =?= body2
293+
case _ => notMatched
280294

281295
/* Match assign */
282-
case (Assign(lhs1, rhs1), Assign(lhs2, rhs2)) =>
283-
lhs1 =?= lhs2 &&& rhs1 =?= rhs2
296+
case (Assign(lhs1, rhs1), _) =>
297+
pattern match
298+
case Assign(lhs2, rhs2) => lhs1 =?= lhs2 &&& rhs1 =?= rhs2
299+
case _ => notMatched
284300

285301
/* Match new */
286-
case (New(tpt1), New(tpt2)) if tpt1.tpe.typeSymbol == tpt2.tpe.typeSymbol =>
287-
matched
302+
case (New(tpt1), _) =>
303+
pattern match
304+
case New(tpt2) if tpt1.tpe.typeSymbol == tpt2.tpe.typeSymbol => matched
305+
case _ => notMatched
288306

289307
/* Match this */
290-
case (This(_), This(_)) if scrutinee.symbol == pattern.symbol =>
291-
matched
308+
case (This(_), _) =>
309+
pattern match
310+
case This(_) if scrutinee.symbol == pattern.symbol => matched
311+
case _ => notMatched
292312

293313
/* Match super */
294-
case (Super(qual1, mix1), Super(qual2, mix2)) if mix1 == mix2 =>
295-
qual1 =?= qual2
314+
case (Super(qual1, mix1), _) =>
315+
pattern match
316+
case Super(qual2, mix2) if mix1 == mix2 => qual1 =?= qual2
317+
case _ => notMatched
296318

297319
/* Match varargs */
298-
case (SeqLiteral(elems1, _), SeqLiteral(elems2, _)) if elems1.size == elems2.size =>
299-
elems1 =?= elems2
320+
case (SeqLiteral(elems1, _), _) =>
321+
pattern match
322+
case SeqLiteral(elems2, _) if elems1.size == elems2.size => elems1 =?= elems2
323+
case _ => notMatched
300324

301325
/* Match type */
302326
// TODO remove this?
303-
case (TypeTreeTypeTest(scrutinee), TypeTreeTypeTest(pattern)) if scrutinee.tpe <:< pattern.tpe =>
304-
matched
327+
case (TypeTreeTypeTest(scrutinee), _) =>
328+
pattern match
329+
case TypeTreeTypeTest(pattern) if scrutinee.tpe <:< pattern.tpe => matched
330+
case _ => notMatched
305331

306332
/* Match val */
307-
case (scrutinee @ ValDef(_, tpt1, _), pattern @ ValDef(_, tpt2, _)) if checkValFlags() =>
308-
def rhsEnv = summon[Env] + (scrutinee.symbol -> pattern.symbol)
309-
tpt1 =?= tpt2 &&& withEnv(rhsEnv)(scrutinee.rhs =?= pattern.rhs)
333+
case (scrutinee @ ValDef(_, tpt1, _), _) =>
334+
pattern match
335+
case pattern @ ValDef(_, tpt2, _) if checkValFlags() =>
336+
def rhsEnv = summon[Env] + (scrutinee.symbol -> pattern.symbol)
337+
tpt1 =?= tpt2 &&& withEnv(rhsEnv)(scrutinee.rhs =?= pattern.rhs)
338+
case _ => notMatched
310339

311340
/* Match def */
312-
case (scrutinee @ DefDef(_, paramss1, tpt1, _), pattern @ DefDef(_, paramss2, tpt2, _)) =>
313-
def rhsEnv: Env =
314-
val paramSyms: List[(Symbol, Symbol)] =
315-
for
316-
(clause1, clause2) <- paramss1.zip(paramss2)
317-
(param1, param2) <- clause1.zip(clause2)
318-
yield
319-
param1.symbol -> param2.symbol
320-
val oldEnv: Env = summon[Env]
321-
val newEnv: List[(Symbol, Symbol)] = (scrutinee.symbol -> pattern.symbol) :: paramSyms
322-
oldEnv ++ newEnv
323-
324-
matchLists(paramss1, paramss2)(_ =?= _)
325-
&&& tpt1 =?= tpt2
326-
&&& withEnv(rhsEnv)(scrutinee.rhs =?= pattern.rhs)
327-
328-
case (Closure(_, _, tpt1), Closure(_, _, tpt2)) =>
329-
// TODO match tpt1 with tpt2?
330-
matched
331-
332-
case (NamedArg(name1, arg1), NamedArg(name2, arg2)) if name1 == name2 =>
333-
arg1 =?= arg2
334-
335-
case (EmptyTree, EmptyTree) =>
336-
matched
341+
case (scrutinee @ DefDef(_, paramss1, tpt1, _), _) =>
342+
pattern match
343+
case pattern @ DefDef(_, paramss2, tpt2, _) =>
344+
def rhsEnv: Env =
345+
val paramSyms: List[(Symbol, Symbol)] =
346+
for
347+
(clause1, clause2) <- paramss1.zip(paramss2)
348+
(param1, param2) <- clause1.zip(clause2)
349+
yield
350+
param1.symbol -> param2.symbol
351+
val oldEnv: Env = summon[Env]
352+
val newEnv: List[(Symbol, Symbol)] = (scrutinee.symbol -> pattern.symbol) :: paramSyms
353+
oldEnv ++ newEnv
354+
matchLists(paramss1, paramss2)(_ =?= _)
355+
&&& tpt1 =?= tpt2
356+
&&& withEnv(rhsEnv)(scrutinee.rhs =?= pattern.rhs)
357+
case _ => notMatched
358+
359+
case (Closure(_, _, tpt1), _) =>
360+
pattern match
361+
case Closure(_, _, tpt2) => matched // TODO match tpt1 with tpt2?
362+
case _ => notMatched
363+
364+
case (NamedArg(name1, arg1), _) =>
365+
pattern match
366+
case NamedArg(name2, arg2) if name1 == name2 => arg1 =?= arg2
367+
case _ => notMatched
368+
369+
case (EmptyTree, _) =>
370+
if pattern.isEmpty then matched
371+
else notMatched
337372

338373
// No Match
339374
case _ =>
340-
if (debug)
341-
val quotes = QuotesImpl()
342-
println(
343-
s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
344-
|Scrutinee
345-
| ${scrutinee.show}
346-
|did not match pattern
347-
| ${pattern.show}
348-
|
349-
|with environment: ${summon[Env]}
350-
|
351-
|Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)}
352-
|Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)}
353-
|
354-
|""".stripMargin)
355375
notMatched
356376

377+
if (debug && res == notMatched)
378+
val quotes = QuotesImpl()
379+
println(
380+
s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
381+
|Scrutinee
382+
| ${scrutinee.show}
383+
|did not match pattern
384+
| ${pattern.show}
385+
|
386+
|with environment: ${summon[Env]}
387+
|
388+
|Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)}
389+
|Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)}
390+
|
391+
|""".stripMargin)
392+
393+
res
394+
end =?=
395+
357396
end extension
358397

359398
/** Does the scrutinee symbol match the pattern symbol? It matches if:

0 commit comments

Comments
 (0)