@@ -16,6 +16,7 @@ import NameKinds.{PatMatStdBinderName, PatMatAltsName, PatMatResultName}
1616import config .Printers .patmatch
1717import reporting .diagnostic .messages ._
1818import dotty .tools .dotc .ast ._
19+ import util .Property ._
1920
2021/** The pattern matching transform.
2122 * After this phase, the only Match nodes remaining in the code are simple switches
@@ -52,6 +53,8 @@ object PatternMatcher {
5253 /** Minimal number of cases to emit a switch */
5354 final val MinSwitchCases = 4
5455
56+ val TrustedTypeTestKey : Key [Unit ] = new StickyKey [Unit ]
57+
5558 /** Was symbol generated by pattern matcher? */
5659 def isPatmatGenerated (sym : Symbol )(implicit ctx : Context ): Boolean =
5760 sym.is(Synthetic ) && sym.name.is(PatMatStdBinderName )
@@ -153,24 +156,24 @@ object PatternMatcher {
153156
154157 /** The different kinds of tests */
155158 sealed abstract class Test
156- case class TypeTest (tpt : Tree ) extends Test { // scrutinee.isInstanceOf[tpt]
159+ case class TypeTest (tpt : Tree , trusted : Boolean ) extends Test { // scrutinee.isInstanceOf[tpt]
157160 override def equals (that : Any ): Boolean = that match {
158161 case that : TypeTest => this .tpt.tpe =:= that.tpt.tpe
159162 case _ => false
160163 }
161164 override def hashCode : Int = tpt.tpe.hash
162165 }
163- case class EqualTest (tree : Tree ) extends Test { // scrutinee == tree
166+ case class EqualTest (tree : Tree ) extends Test { // scrutinee == tree
164167 override def equals (that : Any ): Boolean = that match {
165168 case that : EqualTest => this .tree === that.tree
166169 case _ => false
167170 }
168171 override def hashCode : Int = tree.hash
169172 }
170- case class LengthTest (len : Int , exact : Boolean ) extends Test // scrutinee (== | >=) len
171- case object NonEmptyTest extends Test // !scrutinee.isEmpty
172- case object NonNullTest extends Test // scrutinee ne null
173- case object GuardTest extends Test // scrutinee
173+ case class LengthTest (len : Int , exact : Boolean ) extends Test // scrutinee (== | >=) len
174+ case object NonEmptyTest extends Test // !scrutinee.isEmpty
175+ case object NonNullTest extends Test // scrutinee ne null
176+ case object GuardTest extends Test // scrutinee
174177
175178 // ------- Generating plans from trees ------------------------
176179
@@ -352,7 +355,12 @@ object PatternMatcher {
352355 // begin patternPlan
353356 swapBind(tree) match {
354357 case Typed (pat, tpt) =>
355- TestPlan (TypeTest (tpt), scrutinee, tree.span,
358+ val isTrusted = pat match {
359+ case UnApply (extractor, _, _) =>
360+ extractor.symbol.is(Synthetic ) && extractor.symbol.owner.linkedClass.is(Case )
361+ case _ => false
362+ }
363+ TestPlan (TypeTest (tpt, isTrusted), scrutinee, tree.span,
356364 letAbstract(ref(scrutinee).cast(tpt.tpe)) { casted =>
357365 nonNull += casted
358366 patternPlan(casted, pat, onSuccess)
@@ -685,7 +693,7 @@ object PatternMatcher {
685693 .select(defn.Seq_length .matchingMember(scrutinee.tpe))
686694 .select(if (exact) defn.Int_== else defn.Int_>= )
687695 .appliedTo(Literal (Constant (len)))
688- case TypeTest (tpt) =>
696+ case TypeTest (tpt, trusted ) =>
689697 val expectedTp = tpt.tpe
690698
691699 // An outer test is needed in a situation like `case x: y.Inner => ...`
@@ -716,6 +724,7 @@ object PatternMatcher {
716724 scrutinee.isInstance(expectedTp) // will be translated to an equality test
717725 case _ =>
718726 val typeTest = scrutinee.select(defn.Any_typeTest ).appliedToType(expectedTp)
727+ if (trusted) typeTest.pushAttachment(TrustedTypeTestKey , ())
719728 if (outerTestNeeded) typeTest.and(outerTest) else typeTest
720729 }
721730 }
@@ -899,7 +908,7 @@ object PatternMatcher {
899908 val seen = mutable.Set [Int ]()
900909 def showTest (test : Test ) = test match {
901910 case EqualTest (tree) => i " EqualTest( $tree) "
902- case TypeTest (tpt) => i " TypeTest( $tpt) "
911+ case TypeTest (tpt, trusted ) => i " TypeTest( $tpt, trusted= $trusted ) "
903912 case _ => test.toString
904913 }
905914 def showPlan (plan : Plan ): Unit =
0 commit comments