@@ -287,7 +287,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
287
287
)
288
288
} else {
289
289
assert(defn.isProductSubType(prev.tpe))
290
- Substitution (b, ref(prevSym))(next)
290
+ Block (
291
+ List (ValDef (prevSym, prev)),
292
+ Substitution (b, ref(prevSym))(next)
293
+ )
291
294
}
292
295
}
293
296
@@ -432,8 +435,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
432
435
val cond : Tree
433
436
val res : Tree
434
437
435
- lazy val nextBinder = freshSym(pos, nextBinderTp)
436
- lazy val localSubstitution = Substitution (List (prevBinder), List (ref(nextBinder)))
438
+ val nextBinder : Symbol
439
+ lazy val localSubstitution =
440
+ if (nextBinder ne prevBinder) Substitution (List (prevBinder), List (ref(nextBinder)))
441
+ else EmptySubstitution
437
442
438
443
def chainBefore (next : Tree )(casegen : Casegen ): Tree =
439
444
/* atPos(pos)(*/ casegen.flatMapCond(cond, res, nextBinder, substitution(next))// )
@@ -728,7 +733,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
728
733
729
734
val prevBinder = testedBinder
730
735
731
- override lazy val nextBinder = afterTest.asTerm
736
+ val nextBinder = afterTest.asTerm
732
737
733
738
def needsOuterTest (patType : Type , selType : Type , currentOwner : Symbol ) = {
734
739
// See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest`
@@ -823,13 +828,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
823
828
}
824
829
825
830
// need to substitute to deal with existential types -- TODO: deal with existentials better, don't substitute (see RichClass during quick.comp)
826
- case class EqualityTestTreeMaker (prevBinder : Symbol , patTree : Tree , override val pos : Position ) extends CondTreeMaker {
827
- val nextBinderTp = prevBinder.info.widen
831
+ case class EqualityTestTreeMaker (prevBinder : Symbol , subpatBinder : Symbol , patTree : Tree , override val pos : Position ) extends CondTreeMaker {
832
+ val nextBinderTp = patTree.tpe & prevBinder.info
833
+ val nextBinder = if (prevBinder eq subpatBinder) freshSym(pos, nextBinderTp) else subpatBinder
828
834
829
835
// NOTE: generate `patTree == patBinder`, since the extractor must be in control of the equals method (also, patBinder may be null)
830
836
// equals need not be well-behaved, so don't intersect with pattern's (stabilized) type (unlike MaybeBoundTyped's accumType, where it's required)
831
837
val cond = codegen._equals(patTree, prevBinder)
832
- val res = ref(prevBinder)
838
+ val res = ref(prevBinder).ensureConforms(nextBinderTp)
833
839
override def toString = " ET" + ((prevBinder.name, patTree))
834
840
}
835
841
@@ -1020,18 +1026,33 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1020
1026
}
1021
1027
}
1022
1028
1029
+ object SymbolAndValueBound {
1030
+ def unapply (tree : Tree ): Option [(Symbol , Tree )] = tree match {
1031
+ case SymbolBound (sym, ConstantPattern (const)) => Some (sym -> const)
1032
+ case _ => None
1033
+ }
1034
+ }
1035
+
1023
1036
object TypeBound {
1024
1037
def unapply (tree : Tree ): Option [Type ] = tree match {
1025
1038
case Typed (_, _) => Some (tree.typeOpt)
1026
1039
case _ => None
1027
1040
}
1028
1041
}
1029
1042
1043
+ object ConstantPattern {
1044
+ def unapply (tree : Tree ): Option [Tree ] = tree match {
1045
+ case Literal (Constant (_)) | Ident (_) | Select (_, _) | This (_) => Some (tree)
1046
+ case _ => None
1047
+ }
1048
+ }
1049
+
1030
1050
private def rebindTo (pattern : Tree ) = BoundTree (binder, pattern)
1031
1051
private def step (treeMakers : TreeMaker * )(subpatterns : BoundTree * ): TranslationStep = TranslationStep (treeMakers.toList, subpatterns.toList)
1032
1052
1033
1053
private def bindingStep (sub : Symbol , subpattern : Tree ) = step(SubstOnlyTreeMaker (sub, binder))(rebindTo(subpattern))
1034
- private def equalityTestStep () = step(EqualityTestTreeMaker (binder, tree, pos))()
1054
+ private def equalityTestStep (testedSymbol : Symbol , constantSymbol : Symbol , constant : Tree )
1055
+ = step(EqualityTestTreeMaker (testedSymbol, constantSymbol, constant, pos))()
1035
1056
private def typeTestStep (sub : Symbol , subPt : Type ) = step(TypeTestTreeMaker (sub, binder, subPt, sub.termRef)(pos))()
1036
1057
private def alternativesStep (alts : List [Tree ]) = step(AlternativesTreeMaker (binder, translatedAlts(alts), alts.head.pos))()
1037
1058
private def translatedAlts (alts : List [Tree ]) = alts map (alt => rebindTo(alt).translate())
@@ -1083,9 +1104,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1083
1104
case _ : UnApply | _ : Apply | Typed (_ : UnApply | _ : Apply , _) => extractorStep()
1084
1105
case SymbolAndTypeBound (sym, tpe) => typeTestStep(sym, tpe)
1085
1106
case TypeBound (tpe) => typeTestStep(binder, tpe)
1107
+ case SymbolAndValueBound (sym, const) => equalityTestStep(binder, sym, const)
1086
1108
case SymbolBound (sym, expr) => bindingStep(sym, expr)
1087
1109
case WildcardPattern () => noStep()
1088
- case Literal ( Constant (_)) | Ident (_) | Select (_, _) | This (_) => equalityTestStep()
1110
+ case ConstantPattern (const) => equalityTestStep(binder, binder, const )
1089
1111
case Alternative (alts) => alternativesStep(alts)
1090
1112
case _ => ctx.error(unsupportedPatternMsg, pos) ; noStep()
1091
1113
}
0 commit comments