Skip to content

Commit c18a4d0

Browse files
committed
Make patterns fail fast
1 parent d3b61dd commit c18a4d0

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
@@ -185,7 +185,7 @@ object QuoteMatcher {
185185
case _ => None
186186
end TypeTreeTypeTest
187187

188-
(scrutinee, pattern) match
188+
val res = (scrutinee, pattern) match
189189

190190
/* Term hole */
191191
// Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree
@@ -255,109 +255,148 @@ object QuoteMatcher {
255255
matched
256256

257257
/* Match application */
258-
case (Apply(fn1, args1), Apply(fn2, args2)) =>
259-
fn1 =?= fn2 &&& args1 =?= args2
258+
case (Apply(fn1, args1), _) =>
259+
pattern match
260+
case Apply(fn2, args2) =>
261+
fn1 =?= fn2 &&& args1 =?= args2
262+
case _ => notMatched
260263

261264
/* Match type application */
262-
case (TypeApply(fn1, args1), TypeApply(fn2, args2)) =>
263-
fn1 =?= fn2 &&& args1 =?= args2
265+
case (TypeApply(fn1, args1), _) =>
266+
pattern match
267+
case TypeApply(fn2, args2) =>
268+
fn1 =?= fn2 &&& args1 =?= args2
269+
case _ => notMatched
264270

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

277286
/* Match if */
278-
case (If(cond1, thenp1, elsep1), If(cond2, thenp2, elsep2)) =>
279-
cond1 =?= cond2 &&& thenp1 =?= thenp2 &&& elsep1 =?= elsep2
287+
case (If(cond1, thenp1, elsep1), _) =>
288+
pattern match
289+
case If(cond2, thenp2, elsep2) =>
290+
cond1 =?= cond2 &&& thenp1 =?= thenp2 &&& elsep1 =?= elsep2
291+
case _ => notMatched
280292

281293
/* Match while */
282-
case (WhileDo(cond1, body1), WhileDo(cond2, body2)) =>
283-
cond1 =?= cond2 &&& body1 =?= body2
294+
case (WhileDo(cond1, body1), _) =>
295+
pattern match
296+
case WhileDo(cond2, body2) => cond1 =?= cond2 &&& body1 =?= body2
297+
case _ => notMatched
284298

285299
/* Match assign */
286-
case (Assign(lhs1, rhs1), Assign(lhs2, rhs2)) =>
287-
lhs1 =?= lhs2 &&& rhs1 =?= rhs2
300+
case (Assign(lhs1, rhs1), _) =>
301+
pattern match
302+
case Assign(lhs2, rhs2) => lhs1 =?= lhs2 &&& rhs1 =?= rhs2
303+
case _ => notMatched
288304

289305
/* Match new */
290-
case (New(tpt1), New(tpt2)) if tpt1.tpe.typeSymbol == tpt2.tpe.typeSymbol =>
291-
matched
306+
case (New(tpt1), _) =>
307+
pattern match
308+
case New(tpt2) if tpt1.tpe.typeSymbol == tpt2.tpe.typeSymbol => matched
309+
case _ => notMatched
292310

293311
/* Match this */
294-
case (This(_), This(_)) if scrutinee.symbol == pattern.symbol =>
295-
matched
312+
case (This(_), _) =>
313+
pattern match
314+
case This(_) if scrutinee.symbol == pattern.symbol => matched
315+
case _ => notMatched
296316

297317
/* Match super */
298-
case (Super(qual1, mix1), Super(qual2, mix2)) if mix1 == mix2 =>
299-
qual1 =?= qual2
318+
case (Super(qual1, mix1), _) =>
319+
pattern match
320+
case Super(qual2, mix2) if mix1 == mix2 => qual1 =?= qual2
321+
case _ => notMatched
300322

301323
/* Match varargs */
302-
case (SeqLiteral(elems1, _), SeqLiteral(elems2, _)) if elems1.size == elems2.size =>
303-
elems1 =?= elems2
324+
case (SeqLiteral(elems1, _), _) =>
325+
pattern match
326+
case SeqLiteral(elems2, _) if elems1.size == elems2.size => elems1 =?= elems2
327+
case _ => notMatched
304328

305329
/* Match type */
306330
// TODO remove this?
307-
case (TypeTreeTypeTest(scrutinee), TypeTreeTypeTest(pattern)) if scrutinee.tpe <:< pattern.tpe =>
308-
matched
331+
case (TypeTreeTypeTest(scrutinee), _) =>
332+
pattern match
333+
case TypeTreeTypeTest(pattern) if scrutinee.tpe <:< pattern.tpe => matched
334+
case _ => notMatched
309335

310336
/* Match val */
311-
case (scrutinee @ ValDef(_, tpt1, _), pattern @ ValDef(_, tpt2, _)) if checkValFlags() =>
312-
def rhsEnv = summon[Env] + (scrutinee.symbol -> pattern.symbol)
313-
tpt1 =?= tpt2 &&& withEnv(rhsEnv)(scrutinee.rhs =?= pattern.rhs)
337+
case (scrutinee @ ValDef(_, tpt1, _), _) =>
338+
pattern match
339+
case pattern @ ValDef(_, tpt2, _) if checkValFlags() =>
340+
def rhsEnv = summon[Env] + (scrutinee.symbol -> pattern.symbol)
341+
tpt1 =?= tpt2 &&& withEnv(rhsEnv)(scrutinee.rhs =?= pattern.rhs)
342+
case _ => notMatched
314343

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

342377
// No Match
343378
case _ =>
344-
if (debug)
345-
val quotes = QuotesImpl()
346-
println(
347-
s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
348-
|Scrutinee
349-
| ${scrutinee.show}
350-
|did not match pattern
351-
| ${pattern.show}
352-
|
353-
|with environment: ${summon[Env]}
354-
|
355-
|Scrutinee: ${quotes.reflect.Printer.TreeStructure.show(scrutinee.asInstanceOf)}
356-
|Pattern: ${quotes.reflect.Printer.TreeStructure.show(pattern.asInstanceOf)}
357-
|
358-
|""".stripMargin)
359379
notMatched
360380

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

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

0 commit comments

Comments
 (0)