@@ -48,9 +48,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
4848
4949 private var _id = 0 // left for debuging
5050
51+ // TODO: tpd._ is imported. Why not write (tree: Match)? (Same for the other occurrences of tpd below).
5152 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)
53+ val translated = new Translator ()(ctx).translator.translateMatch(tree)
54+ translated.ensureConforms(tree.tpe)
5455 }
5556
5657 class Translator (implicit ctx : Context ) {
@@ -79,6 +80,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
7980 def matcher (scrut : Tree , scrutSym : Symbol , restpe : Type )(cases : List [Casegen => Tree ], matchFailGen : Option [Symbol => Tree ]): Tree
8081
8182 // local / context-free
83+ // TODO Would be good to have some comments what these methods do
8284 def _asInstanceOf (b : Symbol , tp : Type ): Tree
8385 def _equals (checker : Tree , binder : Symbol ): Tree
8486 def _isInstanceOf (b : Symbol , tp : Type ): Tree
@@ -91,6 +93,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
9193 trait Casegen extends AbsCodegen {
9294 def one (res : Tree ): Tree
9395
96+ // TODO Would be good to have also some comments what these methods do
9497 def flatMap (prev : Tree , b : Symbol , next : Tree ): Tree
9598 def flatMapCond (cond : Tree , res : Tree , nextBinder : Symbol , next : Tree ): Tree
9699 def flatMapGuard (cond : Tree , next : Tree ): Tree
@@ -102,7 +105,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
102105 def codegen : AbsCodegen
103106
104107 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
108+ 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 // TODO move that comment to tupleSel in the base class
106109 def index (tgt : Tree )(i : Int ): Tree = {
107110 if (i > 0 ) tgt.select(defn.Seq_apply ).appliedTo(Literal (Constant (i)))
108111 else tgt.select(defn.Seq_head ).appliedToNone
@@ -114,9 +117,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
114117 // for name-based matching, but this was an expedient route for the basics.
115118 def drop (tgt : Tree )(n : Int ): Tree = {
116119 def callDirect = tgt.select(nme.drop).appliedTo(Literal (Constant (n)))
117- def callRuntime = ref(ctx.definitions.traversableDropMethod).appliedTo(tgt, Literal (Constant (n)))
120+ def callRuntime = ref(defn.traversableDropMethod).appliedTo(tgt, Literal (Constant (n)))
121+ // TODO: Replace ctx.definitions elsewhere with just `defn`.
118122
119- def needsRuntime = (tgt.tpe ne null ) && tgt.tpe.baseTypeRef(ctx.definitions.SeqType .classSymbol).member(nme.drop).exists /* typeOfMemberNamedDrop(tgt.tpe) == NoType*/
123+ def needsRuntime = /* Useless test: this is always true (tgt.tpe ne null) && */
124+ tgt.tpe.baseTypeRef(defn.SeqClass ).member(nme.drop).exists /* typeOfMemberNamedDrop(tgt.tpe) == NoType*/
125+ // TODO: I think the test above is the same as simply
126+ // tgt.tpe derivesFrom defn.SeqClass
127+ // If it derives from SeqClass, it will surely have a drop method, no?
120128
121129 if (needsRuntime) callRuntime else callDirect
122130 }
@@ -135,7 +143,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
135143 def apply (from : Symbol , to : Tree ) = new Substitution (List (from), List (to))
136144 // requires sameLength(from, to)
137145 def apply (from : List [Symbol ], to : List [Tree ]) =
138- if (from nonEmpty) new Substitution (from, to) else EmptySubstitution
146+ if (from. nonEmpty) new Substitution (from, to) else EmptySubstitution
139147 }
140148
141149 class Substitution (val from : List [Symbol ], val to : List [Tree ]) {
@@ -149,12 +157,18 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
149157 else*/
150158
151159 var replaced = 0
152- val toAdapted = (from zip to) map {
153- case (orig, nw) =>
154- nw.ensureConforms(AndType (orig.info, nw.tpe))
160+
161+ // val toAdapted = (from zip to) map {
162+ // case (orig, nw) =>
163+ // nw.ensureConforms(AndType(orig.info, nw.tpe))
164+ // TODO: Use orig.info & nw.tpe instead of the AndType. The former will do simplifications, the latter will not.
165+ // But since this seems to be performance sensitive, we should use the code below.
166+ // }
167+ val toAdapted = to.zipWithConserve(from) { (nw, orig) =>
168+ if (nw.tpe <:< orig.info) nw else nw.ensureConforms(orig.info & nw.tpe)
155169 }
156170
157- val identReplace : tpd.Tree => tpd.Tree = _ match {
171+ val identReplace : tpd.Tree => tpd.Tree = _ match { // TODO: Make identReplace a tpd.Ident => tpd.Tree
158172 case t: Ident =>
159173 def subst (from : List [Symbol ], to : List [Tree ]): Tree =
160174 if (from.isEmpty) t
@@ -226,7 +240,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
226240 // must compute catchAll after caseLabels (side-effects nextCase)
227241 // catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default)
228242 // 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)}
243+ val catchAllDef = matchFailGen.map(_( scrutSym))
230244 .getOrElse(Throw (New (defn.MatchErrorType , List (ref(scrutSym)))))
231245
232246 val matchFail = newSynthCaseLabel(ctx.freshName(" matchFail" ), MethodType (Nil , restpe))
@@ -333,9 +347,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
333347 def emitTypeSwitch (bindersAndCases : List [(Symbol , List [TreeMaker ])], pt : Type ): Option [List [CaseDef ]] =
334348 None // todo
335349
350+ // TODO Would be good to have some explanation here what a TreeMaker is. What's it for? What are its attributes?
336351 abstract class TreeMaker {
337352 def pos : Position
338353
354+ private [this ] var currSub : Substitution = null
355+
339356 /** captures the scope and the value of the bindings in patterns
340357 * important *when* the substitution happens (can't accumulate and do at once after the full matcher has been constructed)
341358 */
@@ -352,7 +369,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
352369 }
353370 else currSub = outerSubst >> substitution
354371 }
355- private [this ] var currSub : Substitution = null
356372
357373 /** The substitution that specifies the trees that compute the values of the subpattern binders.
358374 *
@@ -419,6 +435,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
419435 // unless we're optimizing, emit local variable bindings for all subpatterns of extractor/case class patterns
420436 protected val debugInfoEmitVars = true // !settings.optimise.value
421437
438+ // TODO Explain what this is for, similarly to what's done for ExtractorTreeMaker
422439 sealed trait PreserveSubPatBinders extends TreeMaker {
423440 val subPatBinders : List [Symbol ]
424441 val subPatRefs : List [Tree ]
@@ -932,15 +949,24 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
932949
933950 trait MatchTranslator extends TreeMakers with ScalacPatternExpanders {
934951
952+ /* I think the commented out code
935953 def isBackquoted(x: Ident) = x.isInstanceOf[BackquotedIdent]
936954
937955 def isVarPattern(pat: Tree): Boolean = pat match {
938956 case x: Ident => !isBackquoted(x) && nme.isVariableName(x.name)
939957 case _ => false
940958 }
959+ is better written like this:
960+ */
961+ def isVarPattern (pat : Tree ): Boolean = pat match {
962+ case x : BackquotedIdent => false
963+ case x : Ident => nme.isVariableName(x.name)
964+ case _ => false
965+ }
941966
942967 /** A conservative approximation of which patterns do not discern anything.
943968 * They are discarded during the translation.
969+ * TODO: Why is x a wildcard pattern but x @ _ is not?
944970 */
945971 object WildcardPattern {
946972 def unapply (pat : Tree ): Boolean = pat match {
@@ -971,6 +997,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
971997 }
972998
973999 // Always map repeated params to sequences
1000+ // TODO But repeated params don't exist where PM is running. Why the method?
9741001 private def setVarInfo (sym : Symbol , info : Type ) = {
9751002 // setInfo debug.patmatResult(s"changing ${sym.defString} to")(repeatedToSeq(info))
9761003// if(info!= NoType && !(sym.info =:= info))
@@ -986,11 +1013,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
9861013 case _ => BoundTree (freshSym(tree.pos, pt, prefix = " p" ), tree)
9871014 }
9881015
1016+ // TODO: Again would be nice to document what this class is for.
9891017 final case class BoundTree (binder : Symbol , tree : Tree ) {
9901018 private lazy val extractor = ExtractorCall (tree, binder)
9911019
9921020 def pos = tree.pos
993- def tpe = binder.info.dealias.widen // the type of the variable bound to the pattern
1021+ def tpe = binder.info.widenDealias // the type of the variable bound to the pattern
9941022 def pt = unbound match {
9951023 // case Star(tpt) => this glbWith seqType(tpt.tpe) dd todo:
9961024 case TypeBound (tpe) => tpe
@@ -1010,6 +1038,9 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
10101038 object TypeBound {
10111039 def unapply (tree : Tree ): Option [Type ] = tree match {
10121040 case Typed (_, _) if tree.tpe != null => Some (tree.tpe)
1041+ // Should be: if tree.hasType (tree.tpe is always != null, where a tree is untyped, you'd get an exception when calling .tpe)
1042+ // But probably it's better to do without the extractor altogether. tree.typeOpt fulfils the same fucntion, and
1043+ // is more efficient.
10131044 case _ => None
10141045 }
10151046 }
@@ -1088,6 +1119,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
10881119 // accessors) TODO: get to the bottom of this -- I assume it happens when type checking
10891120 // infers a weird type for an unapply call. By going back to the parameterType for the
10901121 // extractor call we get a saner type, so let's just do that for now.
1122+ // TODO: This is now just a more convoluted and cumbersome version of tpd.ensureConforms. We should use the latter.
1123+ // All setInfo defs and calls can be dropped.
10911124 def ensureConformsTo (paramType : Type ): Boolean = (
10921125 (tpe =:= paramType)
10931126 || (tpe <:< paramType) && setInfo(paramType)
@@ -1116,7 +1149,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
11161149
11171150 def elimAnonymousClass (t : Type ) = t match {
11181151 case t: TypeRef if t.symbol.isAnonymousClass =>
1119- t.symbol.asClass.typeRef.asSeenFrom(t.prefix, t.symbol.owner)
1152+ val res =
1153+ t.symbol.asClass.typeRef.asSeenFrom(t.prefix, t.symbol.owner)
1154+ // what does this do? Is this not always the same as `t` itself?
1155+ // It is in our test runs. See assertion below which never fires.
1156+ assert(res =:= t)
1157+ res
11201158 case _ =>
11211159 t
11221160 }
@@ -1131,6 +1169,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
11311169 isDefaultCase(cdef)
11321170 }
11331171
1172+ // TODO: This method is redundant. Use thiz.derivesFrom(that) instead.
11341173 def isNonBottomSubClass (thiz : Symbol , that : Symbol )(implicit ctx : Context ): Boolean = (
11351174 (thiz eq that) || thiz.isError || that.isError ||
11361175 thiz.info.baseClasses.contains(that)
@@ -1612,7 +1651,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
16121651 * arbitrary types here, and NoPattern and NoType arbitrary values.
16131652 */
16141653 def NoPattern : Pattern
1615- def NoType : Type
1654+ def NoType : Type // TODO Why parameterize over NoType? It looks like it is always core.Types.NoType.
16161655
16171656 /** It's not optimal that we're carrying both sequence and repeated
16181657 * type here, but the implementation requires more unraveling before
0 commit comments