Skip to content

Commit b2aa27e

Browse files
committed
Fixes to pattern matcher
1 parent 886b2a1 commit b2aa27e

File tree

1 file changed

+49
-49
lines changed

1 file changed

+49
-49
lines changed

compiler/src/dotty/tools/dotc/transform/PatMat.scala

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import config.Printers.patmatch
1818
object PatMat {
1919
import ast.tpd._
2020

21+
final val selfCheck = true
22+
2123
abstract class Node
2224

2325
class Translator(implicit ctx: Context) {
@@ -142,22 +144,17 @@ object PatMat {
142144
val tpe = label.info.finalResultType
143145
}
144146

145-
def isVarPattern(pat: Tree): Boolean = pat match {
146-
case x: BackquotedIdent => false
147-
case x: Ident => x.name.isVariableName
148-
case _ => false
149-
}
150-
151147
/** A conservative approximation of which patterns do not discern anything.
152148
* They are discarded during the translation.
153149
*/
154150
object WildcardPattern {
155151
def unapply(pat: Tree): Boolean = pat match {
156152
case Typed(_, tpt) if tpt.tpe.isRepeatedParam => true
157153
case Bind(nme.WILDCARD, WildcardPattern()) => true // don't skip when binding an interesting symbol!
158-
case t if (isWildcardArg(t)) => true
159-
case x: Ident => isVarPattern(x)
160-
case Alternative(ps) => ps forall unapply
154+
case t if isWildcardArg(t) => true
155+
case x: BackquotedIdent => false
156+
case x: Ident => x.name.isVariableName
157+
case Alternative(ps) => ps.forall(unapply)
161158
case EmptyTree => true
162159
case _ => false
163160
}
@@ -189,12 +186,12 @@ object PatMat {
189186
case Nil => onSuccess
190187
}
191188

192-
def translateElems(seqSym: Symbol, args: List[Tree], exact: Boolean, onSuccess: Node) = {
193-
val selectors = args.indices.toList.map(idx =>
194-
ref(seqSym).select(nme.apply).appliedTo(Literal(Constant(idx))))
195-
new LengthTest(seqSym, args.length, exact,
196-
translateArgs(selectors, args, onSuccess), onFailure)
197-
}
189+
def translateElems(seqSym: Symbol, args: List[Tree], exact: Boolean, onSuccess: Node) = {
190+
val selectors = args.indices.toList.map(idx =>
191+
ref(seqSym).select(nme.apply).appliedTo(Literal(Constant(idx))))
192+
new LengthTest(seqSym, args.length, exact,
193+
translateArgs(selectors, args, onSuccess), onFailure)
194+
}
198195

199196
def translateUnApplySeq(getResult: Symbol, args: List[Tree]): Node = args.lastOption match {
200197
case Some(VarArgPattern(arg)) =>
@@ -215,25 +212,25 @@ object PatMat {
215212
}
216213

217214
def translateUnApply(unapp: Tree, args: List[Tree]): Node = {
218-
def caseClass = unapp.symbol.owner.linkedClass
219-
lazy val caseAccessors = caseClass.caseAccessors.filter(_.is(Method))
220-
if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length)
221-
translateArgs(caseAccessors.map(ref(scrutinee).select(_)), args, onSuccess)
222-
else if (unapp.tpe.isRef(defn.BooleanClass))
223-
new GuardTest(unapp, onSuccess, onFailure)
224-
else {
225-
letAbstract(unapp) { unappResult =>
226-
val isUnapplySeq = unapp.symbol.name == nme.unapplySeq
227-
if (isProductMatch(unapp.tpe.widen, args.length) && !isUnapplySeq) {
228-
val selectors = productSelectors(unapp.tpe).take(args.length)
229-
.map(ref(unappResult).select(_))
230-
translateArgs(selectors, args, onSuccess)
231-
}
232-
else {
233-
assert(isGetMatch(unapp.tpe))
234-
val get = ref(unappResult).select(nme.get, _.info.isParameterless)
235-
letAbstract(get) { getResult =>
236-
if (isUnapplySeq)
215+
def caseClass = unapp.symbol.owner.linkedClass
216+
lazy val caseAccessors = caseClass.caseAccessors.filter(_.is(Method))
217+
if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length)
218+
translateArgs(caseAccessors.map(ref(scrutinee).select(_)), args, onSuccess)
219+
else if (unapp.tpe.isRef(defn.BooleanClass))
220+
new GuardTest(unapp, onSuccess, onFailure)
221+
else {
222+
letAbstract(unapp) { unappResult =>
223+
val isUnapplySeq = unapp.symbol.name == nme.unapplySeq
224+
if (isProductMatch(unapp.tpe.widen, args.length) && !isUnapplySeq) {
225+
val selectors = productSelectors(unapp.tpe).take(args.length)
226+
.map(ref(unappResult).select(_))
227+
translateArgs(selectors, args, onSuccess)
228+
}
229+
else {
230+
assert(isGetMatch(unapp.tpe))
231+
val get = ref(unappResult).select(nme.get, _.info.isParameterless)
232+
letAbstract(get) { getResult =>
233+
if (isUnapplySeq)
237234
translateUnApplySeq(getResult, args)
238235
else {
239236
val selectors =
@@ -254,7 +251,8 @@ object PatMat {
254251
translatePattern(casted, pat, onSuccess, onFailure)),
255252
onFailure)
256253
case UnApply(extractor, implicits, args) =>
257-
var unapp = extractor.appliedTo(ref(scrutinee))
254+
val mt @ MethodType(_) = extractor.tpe.widen
255+
var unapp = extractor.appliedTo(ref(scrutinee).ensureConforms(mt.paramInfos.head))
258256
if (implicits.nonEmpty) unapp = unapp.appliedToArgs(implicits)
259257
translateUnApply(unapp, args)
260258
case Bind(name, body) =>
@@ -376,20 +374,22 @@ object PatMat {
376374
val seen = mutable.Set[Int]()
377375

378376
def emit(node: Node): Tree = {
379-
assert(node.isInstanceOf[CallNode] || !seen.contains(node.id), node.id)
380-
seen += node.id
377+
if (selfCheck) {
378+
assert(node.isInstanceOf[CallNode] || !emitted.contains(node.id), node.id)
379+
emitted += node.id
380+
}
381381
node match {
382-
case node: Test =>
383-
If(node.condition, emit(node.onSuccess), emit(node.onFailure)).withPos(node.pos)
384-
case node @ LetNode(sym, body) =>
385-
val symDef =
386-
if (sym.is(Label)) DefDef(sym, emit(labelled(sym)))
387-
else ValDef(sym, rhs(sym).ensureConforms(sym.info))
388-
seq(symDef :: Nil, emit(body))
389-
case BodyNode(tree) =>
390-
tree
391-
case CallNode(label) =>
392-
ref(label).ensureApplied
382+
case node: Test =>
383+
If(node.condition, emit(node.onSuccess), emit(node.onFailure)).withPos(node.pos)
384+
case node @ LetNode(sym, body) =>
385+
val symDef =
386+
if (sym.is(Label)) DefDef(sym, emit(labelled(sym)))
387+
else ValDef(sym, rhs(sym).ensureConforms(sym.info))
388+
seq(symDef :: Nil, emit(body))
389+
case BodyNode(tree) =>
390+
tree
391+
case CallNode(label) =>
392+
ref(label).ensureApplied
393393
}
394394
}
395395

@@ -455,7 +455,7 @@ class PatMat extends MiniPhaseTransform {
455455
// check exhaustivity and unreachability
456456
val engine = new patmat.SpaceEngine
457457

458-
if (engine.checkable(tree) && false) {
458+
if (engine.checkable(tree)) {
459459
engine.checkExhaustivity(tree)
460460
engine.checkRedundancy(tree)
461461
}

0 commit comments

Comments
 (0)