@@ -5069,6 +5069,7 @@ object Types {
5069
5069
case BaseTypeTest (classType : TypeRef , argPatterns : List [MatchTypeCasePattern ], needsConcreteScrut : Boolean )
5070
5070
case CompileTimeS (argPattern : MatchTypeCasePattern )
5071
5071
case AbstractTypeConstructor (tycon : Type , argPatterns : List [MatchTypeCasePattern ])
5072
+ case TypeMemberExtractor (typeMemberName : TypeName , capture : Capture )
5072
5073
5073
5074
def isTypeTest : Boolean =
5074
5075
this .isInstanceOf [TypeTest ]
@@ -5163,12 +5164,45 @@ object Types {
5163
5164
MatchTypeCasePattern .CompileTimeS (argPattern)
5164
5165
else
5165
5166
tycon.info match
5166
- case _ : RealTypeBounds => recAbstractTypeConstructor(pat)
5167
- case _ => null
5167
+ case _ : RealTypeBounds =>
5168
+ recAbstractTypeConstructor(pat)
5169
+ case TypeAlias (tl @ HKTypeLambda (onlyParam :: Nil , resType : RefinedType )) =>
5170
+ /* Unlike for eta-expanded classes, the typer does not automatically
5171
+ * dealias poly type aliases to refined types. So we have to give them
5172
+ * a chance here.
5173
+ * We are quite specific about the shape of type aliases that we are willing
5174
+ * to dealias this way, because we must not dealias arbitrary type constructors
5175
+ * that could refine the bounds of the captures; those would amount of
5176
+ * type-test + capture combos, which are out of the specced match types.
5177
+ */
5178
+ rec(pat.superType, variance)
5179
+ case _ =>
5180
+ null
5168
5181
5169
5182
case pat @ AppliedType (tycon : TypeParamRef , _) if variance == 1 =>
5170
5183
recAbstractTypeConstructor(pat)
5171
5184
5185
+ case pat @ RefinedType (parent, refinedName : TypeName , TypeAlias (alias @ TypeParamRef (binder, num)))
5186
+ if variance == 1 && (binder eq caseLambda) =>
5187
+ parent.member(refinedName) match
5188
+ case refinedMember : SingleDenotation if refinedMember.exists =>
5189
+ // Check that the bounds of the capture contain the bounds of the inherited member
5190
+ val refinedMemberBounds = refinedMember.info
5191
+ val captureBounds = caseLambda.paramInfos(num)
5192
+ if captureBounds.contains(refinedMemberBounds) then
5193
+ /* In this case, we know that any member we eventually find during reduction
5194
+ * will have bounds that fit in the bounds of the capture. Therefore, no
5195
+ * type-test + capture combo is necessary, and we can apply the specced match types.
5196
+ */
5197
+ val capture = rec(alias, variance = 0 ).asInstanceOf [MatchTypeCasePattern .Capture ]
5198
+ MatchTypeCasePattern .TypeMemberExtractor (refinedName, capture)
5199
+ else
5200
+ // Otherwise, a type-test + capture combo might be necessary, and we are out of spec
5201
+ null
5202
+ case _ =>
5203
+ // If the member does not refine a member of the `parent`, we are out of spec
5204
+ null
5205
+
5172
5206
case _ =>
5173
5207
MatchTypeCasePattern .TypeTest (pat)
5174
5208
end rec
0 commit comments