@@ -48,9 +48,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
48
48
49
49
private var _id = 0 // left for debuging
50
50
51
- override def transformMatch (tree : tpd. Match )(implicit ctx : Context , info : TransformerInfo ): tpd. Tree = {
52
- val translated = new Translator ()(ctx).translator.translateMatch(tree)
53
- translated.ensureConforms(tree.tpe)
51
+ override def transformMatch (tree : Match )(implicit ctx : Context , info : TransformerInfo ): Tree = {
52
+ val translated = new Translator ()(ctx).translator.translateMatch(tree)
53
+ translated.ensureConforms(tree.tpe)
54
54
}
55
55
56
56
class Translator (implicit ctx : Context ) {
@@ -79,11 +79,18 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
79
79
def matcher (scrut : Tree , scrutSym : Symbol , restpe : Type )(cases : List [Casegen => Tree ], matchFailGen : Option [Symbol => Tree ]): Tree
80
80
81
81
// local / context-free
82
+
83
+ /* cast b to tp */
82
84
def _asInstanceOf (b : Symbol , tp : Type ): Tree
85
+ /* a check `checker` == binder */
83
86
def _equals (checker : Tree , binder : Symbol ): Tree
87
+ /* b.isIsInstanceOf[tp] */
84
88
def _isInstanceOf (b : Symbol , tp : Type ): Tree
89
+ /* tgt is expected to be a Seq, call tgt.drop(n) */
85
90
def drop (tgt : Tree )(n : Int ): Tree
91
+ /* tgt is expected to have method apply(int), call tgt.drop(i) */
86
92
def index (tgt : Tree )(i : Int ): Tree
93
+ /* make tree that accesses the i'th component of the tuple referenced by binder */
87
94
def tupleSel (binder : Symbol )(i : Int ): Tree
88
95
}
89
96
@@ -102,7 +109,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
102
109
def codegen : AbsCodegen
103
110
104
111
abstract class CommonCodegen extends AbsCodegen {
105
- def tupleSel (binder : Symbol )(i : Int ): Tree = ref(binder).select(nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder
112
+ def tupleSel (binder : Symbol )(i : Int ): Tree = ref(binder).select(nme.productAccessorName(i))
106
113
def index (tgt : Tree )(i : Int ): Tree = {
107
114
if (i > 0 ) tgt.select(defn.Seq_apply ).appliedTo(Literal (Constant (i)))
108
115
else tgt.select(defn.Seq_head ).appliedIfMethod
@@ -114,9 +121,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
114
121
// for name-based matching, but this was an expedient route for the basics.
115
122
def drop (tgt : Tree )(n : Int ): Tree = {
116
123
def callDirect = tgt.select(nme.drop).appliedTo(Literal (Constant (n)))
117
- def callRuntime = ref(ctx.definitions .traversableDropMethod).appliedTo(tgt, Literal (Constant (n)))
124
+ def callRuntime = ref(defn .traversableDropMethod).appliedTo(tgt, Literal (Constant (n)))
118
125
119
- def needsRuntime = ( tgt.tpe ne null ) && tgt.tpe.baseTypeRef(ctx.definitions. SeqType .classSymbol).member(nme.drop).exists /* typeOfMemberNamedDrop(tgt.tpe) == NoType*/
126
+ def needsRuntime = tgt.tpe derivesFrom defn. SeqClass /* typeOfMemberNamedDrop(tgt.tpe) == NoType*/
120
127
121
128
if (needsRuntime) callRuntime else callDirect
122
129
}
@@ -151,20 +158,18 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
151
158
var replaced = 0
152
159
val toAdapted = (from zip to) map {
153
160
case (orig, nw) =>
154
- nw.ensureConforms(AndType ( orig.info, nw.tpe) )
161
+ if ( nw.tpe <:< orig.info) nw else nw. ensureConforms(orig.info & nw.tpe)
155
162
}
156
163
157
- val identReplace : tpd.Tree => tpd.Tree = _ match {
158
- case t: Ident =>
164
+ val identReplace : Ident => Tree = { ident =>
159
165
def subst (from : List [Symbol ], to : List [Tree ]): Tree =
160
- if (from.isEmpty) t
161
- else if (t .symbol == from.head) {
166
+ if (from.isEmpty) ident
167
+ else if (ident .symbol == from.head) {
162
168
replaced += 1
163
169
to.head // typedIfOrigTyped(to.head.shallowDuplicate.setPos(tree.pos), tree.tpe)
164
170
}
165
171
else subst(from.tail, to.tail)
166
172
subst(from, toAdapted)
167
- case t => t
168
173
}
169
174
val start = System .currentTimeMillis()
170
175
val res = new tpd.TreeMap () {
@@ -226,7 +231,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
226
231
// must compute catchAll after caseLabels (side-effects nextCase)
227
232
// catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default)
228
233
// if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd
229
- val catchAllDef = matchFailGen.map { matchFailGen => matchFailGen (scrutSym)}
234
+ val catchAllDef = matchFailGen.map { _ (scrutSym)}
230
235
.getOrElse(Throw (New (defn.MatchErrorType , List (ref(scrutSym)))))
231
236
232
237
val matchFail = newSynthCaseLabel(ctx.freshName(" matchFail" ), MethodType (Nil , restpe))
@@ -278,7 +283,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
278
283
List (ValDef (prevSym, prev)),
279
284
// must be isEmpty and get as we don't control the target of the call (prev is an extractor call)
280
285
ifThenElseZero(
281
- ref(prevSym).select(nme.isDefined).select(ctx.definitions .Boolean_! ),
286
+ ref(prevSym).select(nme.isDefined).select(defn .Boolean_! ),
282
287
Substitution (b, prevValue)(next)
283
288
)
284
289
)
@@ -333,9 +338,11 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
333
338
def emitTypeSwitch (bindersAndCases : List [(Symbol , List [TreeMaker ])], pt : Type ): Option [List [CaseDef ]] =
334
339
None // todo
335
340
336
- abstract class TreeMaker {
341
+ abstract class TreeMaker {
337
342
def pos : Position
338
343
344
+ private [this ] var currSub : Substitution = null
345
+
339
346
/** captures the scope and the value of the bindings in patterns
340
347
* important *when* the substitution happens (can't accumulate and do at once after the full matcher has been constructed)
341
348
*/
@@ -352,7 +359,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
352
359
}
353
360
else currSub = outerSubst >> substitution
354
361
}
355
- private [this ] var currSub : Substitution = null
356
362
357
363
/** The substitution that specifies the trees that compute the values of the subpattern binders.
358
364
*
@@ -419,10 +425,13 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
419
425
// unless we're optimizing, emit local variable bindings for all subpatterns of extractor/case class patterns
420
426
protected val debugInfoEmitVars = true // !settings.optimise.value
421
427
428
+ /**
429
+ * Tree maker that captures sub pattern values during pattern match.
430
+ */
422
431
sealed trait PreserveSubPatBinders extends TreeMaker {
423
- val subPatBinders : List [Symbol ]
424
- val subPatRefs : List [Tree ]
425
- val ignoredSubPatBinders : Set [Symbol ]
432
+ val subPatBinders : List [Symbol ] // captured values
433
+ val subPatRefs : List [Tree ] // trees that will replace references to subPatBinders
434
+ val ignoredSubPatBinders : Set [Symbol ] // ignored as they aren't used in body of pattern
426
435
427
436
// unless `debugInfoEmitVars`, this set should contain the bare minimum for correctness
428
437
// mutable case class fields need to be stored regardless (SI-5158, SI-6070) -- see override in ProductExtractorTreeMaker
@@ -567,10 +576,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
567
576
def extraStoredBinders : Set [Symbol ] = mutableBinders.toSet
568
577
569
578
def chainBefore (next : Tree )(casegen : Casegen ): Tree = {
570
- val nullCheck : Tree = ref(prevBinder).select(ctx.definitions .Object_ne ).appliedTo(Literal (Constant (null )))
579
+ val nullCheck : Tree = ref(prevBinder).select(defn .Object_ne ).appliedTo(Literal (Constant (null )))
571
580
val cond : Option [Tree ] =
572
581
if (binderKnownNonNull) extraCond
573
- else extraCond.map(nullCheck.select(ctx.definitions .Boolean_&& ).appliedTo).orElse(Some (nullCheck))
582
+ else extraCond.map(nullCheck.select(defn .Boolean_&& ).appliedTo).orElse(Some (nullCheck))
574
583
575
584
cond match {
576
585
case Some (cond : Tree ) =>
@@ -621,12 +630,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
621
630
object treeCondStrategy extends TypeTestCondStrategy {
622
631
type Result = Tree
623
632
624
- def and (a : Result , b : Result ): Result = a.select(ctx.definitions .Boolean_&& ).appliedTo(b)
633
+ def and (a : Result , b : Result ): Result = a.select(defn .Boolean_&& ).appliedTo(b)
625
634
def tru = Literal (Constant (true ))
626
635
def typeTest (testedBinder : Symbol , expectedTp : Type ) = codegen._isInstanceOf(testedBinder, expectedTp)
627
- def nonNullTest (testedBinder : Symbol ) = ref(testedBinder).select(ctx.definitions .Object_ne ).appliedTo(Literal (Constant (null )))
636
+ def nonNullTest (testedBinder : Symbol ) = ref(testedBinder).select(defn .Object_ne ).appliedTo(Literal (Constant (null )))
628
637
def equalsTest (pat : Tree , testedBinder : Symbol ) = codegen._equals(pat, testedBinder)
629
- def eqTest (pat : Tree , testedBinder : Symbol ) = ref(testedBinder).select(ctx.definitions .Object_eq ).appliedTo(pat)
638
+ def eqTest (pat : Tree , testedBinder : Symbol ) = ref(testedBinder).select(defn .Object_eq ).appliedTo(pat)
630
639
631
640
def outerTest (testedBinder : Symbol , expectedTp : Type ): Tree = {
632
641
val expectedOuter = expectedTp.normalizedPrefix match {
@@ -641,7 +650,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
641
650
642
651
val expectedClass = expectedTp.dealias.classSymbol.asClass
643
652
ExplicitOuter .ensureOuterAccessors(expectedClass)
644
- codegen._asInstanceOf(testedBinder, expectedTp).select(ExplicitOuter .outerAccessor(expectedClass)).select(ctx.definitions .Object_eq ).appliedTo(expectedOuter)
653
+ codegen._asInstanceOf(testedBinder, expectedTp).select(ExplicitOuter .outerAccessor(expectedClass)).select(defn .Object_eq ).appliedTo(expectedOuter)
645
654
}
646
655
}
647
656
@@ -738,10 +747,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
738
747
739
748
def testedWide = testedBinder.info.widen
740
749
def expectedWide = expectedTp.widen
741
- def isAnyRef = testedWide <:< ctx.definitions .AnyRefType
750
+ def isAnyRef = testedWide <:< defn .AnyRefType
742
751
def isAsExpected = testedWide <:< expectedTp
743
- def isExpectedPrimitiveType = isAsExpected && ctx.definitions .ScalaValueClasses .contains(expectedTp.classSymbol)
744
- def isExpectedReferenceType = isAsExpected && (expectedTp <:< ctx.definitions .AnyRefType )
752
+ def isExpectedPrimitiveType = isAsExpected && defn .ScalaValueClasses .contains(expectedTp.classSymbol)
753
+ def isExpectedReferenceType = isAsExpected && (expectedTp <:< defn .AnyRefType )
745
754
def mkNullTest = nonNullTest(testedBinder)
746
755
def mkOuterTest = outerTest(testedBinder, expectedTp)
747
756
def mkTypeTest = typeTest(testedBinder, expectedWide)
@@ -823,7 +832,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
823
832
((casegen : Casegen ) => combineExtractors(altTreeMakers :+ TrivialTreeMaker (casegen.one(Literal (Constant (true )))))(casegen))
824
833
)
825
834
826
- val findAltMatcher = codegenAlt.matcher(EmptyTree , NoSymbol , ctx.definitions .BooleanType )(combinedAlts, Some ((x : Symbol ) => Literal (Constant (false ))))
835
+ val findAltMatcher = codegenAlt.matcher(EmptyTree , NoSymbol , defn .BooleanType )(combinedAlts, Some ((x : Symbol ) => Literal (Constant (false ))))
827
836
codegenAlt.ifThenElseZero(findAltMatcher, substitution(next))
828
837
}
829
838
}
@@ -935,8 +944,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
935
944
def isBackquoted (x : Ident ) = x.isInstanceOf [BackquotedIdent ]
936
945
937
946
def isVarPattern (pat : Tree ): Boolean = pat match {
938
- case x : Ident => ! isBackquoted(x) && nme.isVariableName(x.name)
939
- case _ => false
947
+ case x : BackquotedIdent => false
948
+ case x : Ident => nme.isVariableName(x.name)
949
+ case _ => false
940
950
}
941
951
942
952
/** A conservative approximation of which patterns do not discern anything.
@@ -970,27 +980,17 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
970
980
}
971
981
}
972
982
973
- // Always map repeated params to sequences
974
- private def setVarInfo (sym : Symbol , info : Type ) = {
975
- // setInfo debug.patmatResult(s"changing ${sym.defString} to")(repeatedToSeq(info))
976
- // if(info!= NoType && !(sym.info =:= info))
977
- // assert(false, "bug in porting pattern matcher")
978
- ctx.debuglog(s " scalac would be resetting info of $sym from ${sym.info} to $info" )
979
- sym
980
- }
981
-
982
-
983
983
def newBoundTree (tree : Tree , pt : Type ): BoundTree = tree match {
984
984
case SymbolBound (sym, Typed (subpat, tpe)) => BoundTree (freshSym(tree.pos, pt, prefix = " pi" ), tree)
985
- case SymbolBound (sym, expr) => BoundTree (setVarInfo( sym, pt) , expr)
985
+ case SymbolBound (sym, expr) => BoundTree (sym, expr)
986
986
case _ => BoundTree (freshSym(tree.pos, pt, prefix = " p" ), tree)
987
987
}
988
988
989
989
final case class BoundTree (binder : Symbol , tree : Tree ) {
990
990
private lazy val extractor = ExtractorCall (tree, binder)
991
991
992
992
def pos = tree.pos
993
- def tpe = binder.info.dealias.widen // the type of the variable bound to the pattern
993
+ def tpe = binder.info.widenDealias
994
994
def pt = unbound match {
995
995
// case Star(tpt) => this glbWith seqType(tpt.tpe) dd todo:
996
996
case TypeBound (tpe) => tpe
@@ -1009,7 +1009,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1009
1009
1010
1010
object TypeBound {
1011
1011
def unapply (tree : Tree ): Option [Type ] = tree match {
1012
- case Typed (_, _) if tree.tpe != null = > Some (tree.tpe )
1012
+ case Typed (_, _) = > Some (tree.typeOpt )
1013
1013
case _ => None
1014
1014
}
1015
1015
}
@@ -1046,7 +1046,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1046
1046
// TODO: paramType may contain unbound type params (run/t2800, run/t3530)
1047
1047
val makers = (
1048
1048
// Statically conforms to paramType
1049
- if (this ensureConformsTo paramType) treeMaker(binder, false , pos, tpe) :: Nil
1049
+ if (tpe <:< paramType) treeMaker(binder, false , pos, tpe) :: Nil
1050
1050
else typeTest :: extraction :: Nil
1051
1051
)
1052
1052
step(makers : _* )(extractor.subBoundTrees: _* )
@@ -1078,20 +1078,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1078
1078
}
1079
1079
def translate (): List [TreeMaker ] = nextStep() merge (_.translate())
1080
1080
1081
- private def setInfo (paramType : Type ): Boolean = {
1082
- setVarInfo(binder, paramType)
1083
- true
1084
- }
1085
- // If <:< but not =:=, no type test needed, but the tree maker relies on the binder having
1086
- // exactly paramType (and not just some type compatible with it.) SI-6624 shows this is necessary
1087
- // because apparently patBinder may have an unfortunate type (.decls don't have the case field
1088
- // accessors) TODO: get to the bottom of this -- I assume it happens when type checking
1089
- // infers a weird type for an unapply call. By going back to the parameterType for the
1090
- // extractor call we get a saner type, so let's just do that for now.
1091
- def ensureConformsTo (paramType : Type ): Boolean = (
1092
- (tpe =:= paramType)
1093
- || (tpe <:< paramType) && setInfo(paramType)
1094
- )
1095
1081
1096
1082
private def concreteType = tpe.bounds.hi
1097
1083
private def unbound = unbind(tree)
@@ -1131,16 +1117,11 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1131
1117
isDefaultCase(cdef)
1132
1118
}
1133
1119
1134
- def isNonBottomSubClass (thiz : Symbol , that : Symbol )(implicit ctx : Context ): Boolean = (
1135
- (thiz eq that) || thiz.isError || that.isError ||
1136
- thiz.info.baseClasses.contains(that)
1137
- )
1138
-
1139
1120
private def isSimpleThrowable (tp : Type )(implicit ctx : Context ): Boolean = tp match {
1140
1121
case tp @ TypeRef (pre, _) =>
1141
1122
val sym = tp.symbol
1142
1123
(pre == NoPrefix || pre.widen.typeSymbol.isStatic) &&
1143
- (isNonBottomSubClass( sym, ctx.definitions .ThrowableClass )) && /* bq */ ! (sym is Flags .Trait )
1124
+ (sym.derivesFrom(defn .ThrowableClass )) && /* bq */ ! (sym is Flags .Trait )
1144
1125
case _ =>
1145
1126
false
1146
1127
}
@@ -1209,7 +1190,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1209
1190
val bindersAndCases = caseDefs map { caseDef =>
1210
1191
// generate a fresh symbol for each case, hoping we'll end up emitting a type-switch (we don't have a global scrut there)
1211
1192
// if we fail to emit a fine-grained switch, have to do translateCase again with a single scrutSym (TODO: uniformize substitution on treemakers so we can avoid this)
1212
- val caseScrutSym = freshSym(pos, pureType(ctx.definitions .ThrowableType))
1193
+ val caseScrutSym = freshSym(pos, pureType(defn .ThrowableType))
1213
1194
(caseScrutSym, propagateSubstitution(translateCase(caseScrutSym, pt)(caseDef), EmptySubstitution))
1214
1195
}
1215
1196
@@ -1219,10 +1200,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1219
1200
}
1220
1201
1221
1202
val catches = if (swatches.nonEmpty) swatches else {
1222
- val scrutSym = freshSym(pos, pureType(ctx.definitions .ThrowableType))
1203
+ val scrutSym = freshSym(pos, pureType(defn .ThrowableType))
1223
1204
val casesNoSubstOnly = caseDefs map { caseDef => (propagateSubstitution(translateCase(scrutSym, pt)(caseDef), EmptySubstitution))}
1224
1205
1225
- val exSym = freshSym(pos, pureType(ctx.definitions .ThrowableType), "ex")
1206
+ val exSym = freshSym(pos, pureType(defn .ThrowableType), "ex")
1226
1207
1227
1208
List(
1228
1209
CaseDef(
@@ -1233,7 +1214,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1233
1214
)
1234
1215
}
1235
1216
1236
- /* typer.typedCases(*/ catches/* , ctx.definitions .ThrowableType, WildcardType)*/
1217
+ /* typer.typedCases(*/ catches/* , defn .ThrowableType, WildcardType)*/
1237
1218
}*/
1238
1219
1239
1220
/** The translation of `pat if guard => body` has two aspects:
@@ -1811,15 +1792,15 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1811
1792
1812
1793
// println(s"${_id}unapplyArgs(${result.widen}")
1813
1794
val expanded : List [Type ] = /* (
1814
- if (result =:= ctx.definitions .BooleanType) Nil
1795
+ if (result =:= defn .BooleanType) Nil
1815
1796
else if(defn.isProductSubType(result)) productSelectorTypes(result)
1816
1797
else if(result.classSymbol is Flags.CaseClass) result.decls.filter(x => x.is(Flags.CaseAccessor) && x.is(Flags.Method)).map(_.info).toList
1817
1798
else result.select(nme.get) :: Nil
1818
1799
)*/
1819
1800
if ((extractorMemberType(resultType, nme.isDefined) isRef defn.BooleanClass ) && resultOfGet.exists)
1820
1801
getUnapplySelectors(resultOfGet, args)
1821
1802
else if (defn.isProductSubType(resultType)) productSelectorTypes(resultType)
1822
- else if (resultType =:= ctx.definitions .BooleanType ) Nil
1803
+ else if (resultType =:= defn .BooleanType ) Nil
1823
1804
else {
1824
1805
ctx.error(i " invalid return type in Unapply node: $resultType" )
1825
1806
Nil
@@ -1836,7 +1817,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
1836
1817
/** Converts a T => (A, B, C) extractor to a T => ((A, B, CC)) extractor.
1837
1818
*/
1838
1819
def tupleExtractor (extractor : Extractor ): Extractor =
1839
- extractor.copy(fixed = ctx.definitions .tupleType(extractor.fixed) :: Nil )
1820
+ extractor.copy(fixed = defn .tupleType(extractor.fixed) :: Nil )
1840
1821
1841
1822
private def validateAligned (tree : Tree , aligned : Aligned ): Aligned = {
1842
1823
import aligned ._
0 commit comments