Skip to content

Commit f06be77

Browse files
1 parent f75caad commit f06be77

File tree

1 file changed

+2
-87
lines changed

1 file changed

+2
-87
lines changed

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

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -670,59 +670,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
670670
override def toString = "X" + ((extractor, nextBinder.name))
671671
}
672672

673-
/**
674-
* An optimized version of ExtractorTreeMaker for Products.
675-
* For now, this is hard-coded to case classes, and we simply extract the case class fields.
676-
*
677-
* The values for the subpatterns, as specified by the case class fields at the time of extraction,
678-
* are stored in local variables that re-use the symbols in `subPatBinders`.
679-
* This makes extractor patterns more debuggable (SI-5739) as well as
680-
* avoiding mutation after the pattern has been matched (SI-5158, SI-6070)
681-
*
682-
* TODO: make this user-definable as follows
683-
* When a companion object defines a method `def unapply_1(x: T): U_1`, but no `def unapply` or `def unapplySeq`,
684-
* the extractor is considered to match any non-null value of type T
685-
* the pattern is expected to have as many sub-patterns as there are `def unapply_I(x: T): U_I` methods,
686-
* and the type of the I'th sub-pattern is `U_I`.
687-
* The same exception for Seq patterns applies: if the last extractor is of type `Seq[U_N]`,
688-
* the pattern must have at least N arguments (exactly N if the last argument is annotated with `: _*`).
689-
* The arguments starting at N (and beyond) are taken from the sequence returned by apply_N,
690-
* and it is checked that the sequence has enough elements to provide values for all expected sub-patterns.
691-
*
692-
* For a case class C, the implementation is assumed to be `def unapply_I(x: C) = x._I`,
693-
* and the extractor call is inlined under that assumption.
694-
*/
695-
case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree])(
696-
val subPatBinders: List[Symbol],
697-
val subPatRefs: List[Tree],
698-
val mutableBinders: List[Symbol],
699-
binderKnownNonNull: Boolean,
700-
val ignoredSubPatBinders: Set[Symbol]
701-
) extends FunTreeMaker with PreserveSubPatBinders {
702-
703-
val nextBinder = prevBinder // just passing through
704-
705-
// mutable binders must be stored to avoid unsoundness or seeing mutation of fields after matching (SI-5158, SI-6070)
706-
def extraStoredBinders: Set[Symbol] = mutableBinders.toSet
707-
708-
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
709-
val nullCheck: Tree = ref(prevBinder).select(defn.Object_ne).appliedTo(Literal(Constant(null)))
710-
711-
val cond: Option[Tree] =
712-
if (binderKnownNonNull) extraCond
713-
else extraCond.map(nullCheck.select(defn.Boolean_&&).appliedTo).orElse(Some(nullCheck))
714-
715-
cond match {
716-
case Some(cond: Tree) =>
717-
casegen.ifThenElseZero(cond, bindSubPats(next))
718-
case _ =>
719-
bindSubPats(next)
720-
}
721-
}
722-
723-
override def toString = "P" + ((prevBinder.name, extraCond getOrElse "", introducedRebindings))
724-
}
725-
726673
object IrrefutableExtractorTreeMaker {
727674
// will an extractor with unapply method of methodtype `tp` always succeed?
728675
// note: this assumes the other side-conditions implied by the extractor are met
@@ -1397,15 +1344,11 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
13971344
// TODO: check unargs == args
13981345
def apply(tree: Tree, binder: Symbol): ExtractorCall = {
13991346
tree match {
1347+
case Typed(unapply, _) => apply(unapply, binder)
14001348
case UnApply(unfun, implicits, args) =>
14011349
val castedBinder = ref(binder).ensureConforms(tree.tpe)
14021350
val synth = if (implicits.isEmpty) unfun.appliedTo(castedBinder) else unfun.appliedTo(castedBinder).appliedToArgs(implicits)
1403-
new ExtractorCallRegular(alignPatterns(tree, synth.tpe), synth, args, synth.tpe) // extractor
1404-
case Typed(unapply@ UnApply(unfun, implicits, args), tpt) =>
1405-
val castedBinder = ref(binder).ensureConforms(unapply.tpe)
1406-
val synth = /*Typed(*/ if (implicits.isEmpty) unfun.appliedTo(castedBinder) else unfun.appliedTo(castedBinder).appliedToArgs(implicits) //, tpt)
1407-
new ExtractorCallRegular(alignPatterns(tree, synth.tpe), synth, args, synth.tpe) // extractor
1408-
case Apply(fun, args) => new ExtractorCallProd(alignPatterns(tree, tree.tpe), fun, args, fun.tpe) // case class
1351+
new ExtractorCallRegular(alignPatterns(tree, synth.tpe), synth, args, synth.tpe)
14091352
}
14101353
}
14111354
}
@@ -1549,34 +1492,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
15491492
else Some(expectedLength)
15501493
}
15511494

1552-
// TODO: to be called when there's a def unapplyProd(x: T): U
1553-
// U must have N members _1,..., _N -- the _i are type checked, call their type Ti,
1554-
// for now only used for case classes -- pretending there's an unapplyProd that's the identity (and don't call it)
1555-
class ExtractorCallProd(aligner: PatternAligned, val fun: Tree, val args: List[Tree], val resultType: Type) extends ExtractorCall(aligner) {
1556-
/** Create the TreeMaker that embodies this extractor call
1557-
*
1558-
* `binder` has been casted to `paramType` if necessary
1559-
* `binderKnownNonNull` indicates whether the cast implies `binder` cannot be null
1560-
* when `binderKnownNonNull` is `true`, `ProductExtractorTreeMaker` does not do a (redundant) null check on binder
1561-
*/
1562-
def treeMaker(binder: Symbol, binderKnownNonNull: Boolean, pos: Position, binderTypeTested: Type): TreeMaker = {
1563-
val paramAccessors = binder.caseAccessors
1564-
// binders corresponding to mutable fields should be stored (SI-5158, SI-6070)
1565-
// make an exception for classes under the scala package as they should be well-behaved,
1566-
// to optimize matching on List
1567-
val mutableBinders = (
1568-
if (//!binder.info.typeSymbol.hasTransOwner(ScalaPackageClass) // TODO: DDD ???
1569-
// &&
1570-
(paramAccessors exists (_.hasAltWith(x => x.symbol is Flags.Mutable))))
1571-
subPatBinders.zipWithIndex.collect{ case (binder, idx) if paramAccessors(idx).hasAltWith(x => x.symbol is Flags.Mutable) => binder }
1572-
else Nil
1573-
)
1574-
1575-
// checks binder ne null before chaining to the next extractor
1576-
ProductExtractorTreeMaker(binder, lengthGuard(binder))(subPatBinders, subPatRefs(binder), mutableBinders, binderKnownNonNull, ignoredSubPatBinders)
1577-
}
1578-
}
1579-
15801495
class ExtractorCallRegular(aligner: PatternAligned, extractorCallIncludingDummy: Tree, val args: List[Tree], val resultType: Type) extends ExtractorCall(aligner) {
15811496

15821497
/** Create the TreeMaker that embodies this extractor call

0 commit comments

Comments
 (0)