@@ -2,6 +2,8 @@ package dotty.tools
2
2
package dotc
3
3
package core
4
4
5
+ import java .util as ju
6
+
5
7
import Symbols ._
6
8
import Flags ._
7
9
import Names ._
@@ -5077,6 +5079,7 @@ object Types {
5077
5079
case SubTypeTest (origMatchCase : Type , pattern : Type , body : Type )
5078
5080
case SpeccedPatMat (origMatchCase : HKTypeLambda , captureCount : Int , pattern : MatchTypeCasePattern , body : Type )
5079
5081
case LegacyPatMat (origMatchCase : HKTypeLambda )
5082
+ case MissingCaptures (origMatchCase : HKTypeLambda , missing : ju.BitSet )
5080
5083
5081
5084
def origMatchCase : Type
5082
5085
end MatchTypeCaseSpec
@@ -5086,16 +5089,45 @@ object Types {
5086
5089
cas match
5087
5090
case cas : HKTypeLambda =>
5088
5091
val defn .MatchCase (pat, body) = cas.resultType: @ unchecked
5089
- val specPattern = tryConvertToSpecPattern (cas, pat)
5090
- if specPattern != null then
5091
- SpeccedPatMat (cas, cas.paramNames.size, specPattern, body )
5092
+ val missing = checkCapturesPresent (cas, pat)
5093
+ if ! missing.isEmpty then
5094
+ MissingCaptures (cas, missing )
5092
5095
else
5093
- LegacyPatMat (cas)
5096
+ val specPattern = tryConvertToSpecPattern(cas, pat)
5097
+ if specPattern != null then
5098
+ SpeccedPatMat (cas, cas.paramNames.size, specPattern, body)
5099
+ else
5100
+ LegacyPatMat (cas)
5094
5101
case _ =>
5095
5102
val defn .MatchCase (pat, body) = cas : @ unchecked
5096
5103
SubTypeTest (cas, pat, body)
5097
5104
end analyze
5098
5105
5106
+ /** Checks that all the captures of the case are present in the case.
5107
+ *
5108
+ * Sometimes, because of earlier substitutions of an abstract type constructor,
5109
+ * we can end up with patterns that do not mention all their captures anymore.
5110
+ * This can happen even when the body still refers to these missing captures.
5111
+ * In that case, we must always consider the case to be unmatchable, i.e., to
5112
+ * become `Stuck`.
5113
+ *
5114
+ * See pos/i12127.scala for an example.
5115
+ */
5116
+ def checkCapturesPresent (cas : HKTypeLambda , pat : Type )(using Context ): ju.BitSet =
5117
+ val captureCount = cas.paramNames.size
5118
+ val missing = new java.util.BitSet (captureCount)
5119
+ missing.set(0 , captureCount)
5120
+ new CheckCapturesPresent (cas).apply(missing, pat)
5121
+
5122
+ private class CheckCapturesPresent (cas : HKTypeLambda )(using Context ) extends TypeAccumulator [ju.BitSet ]:
5123
+ def apply (missing : ju.BitSet , tp : Type ): ju.BitSet = tp match
5124
+ case TypeParamRef (binder, num) if binder eq cas =>
5125
+ missing.clear(num)
5126
+ missing
5127
+ case _ =>
5128
+ foldOver(missing, tp)
5129
+ end CheckCapturesPresent
5130
+
5099
5131
private def tryConvertToSpecPattern (caseLambda : HKTypeLambda , pat : Type )(using Context ): MatchTypeCasePattern | Null =
5100
5132
var typeParamRefsAccountedFor : Int = 0
5101
5133
0 commit comments