@@ -5097,6 +5097,7 @@ object Types {
5097
5097
case BaseTypeTest (classType : TypeRef , argPatterns : List [MatchTypeCasePattern ], needsConcreteScrut : Boolean )
5098
5098
case CompileTimeS (argPattern : MatchTypeCasePattern )
5099
5099
case AbstractTypeConstructor (tycon : Type , argPatterns : List [MatchTypeCasePattern ])
5100
+ case TypeMemberExtractor (typeMemberName : TypeName , capture : Capture )
5100
5101
5101
5102
def isTypeTest : Boolean =
5102
5103
this .isInstanceOf [TypeTest ]
@@ -5191,12 +5192,45 @@ object Types {
5191
5192
MatchTypeCasePattern .CompileTimeS (argPattern)
5192
5193
else
5193
5194
tycon.info match
5194
- case _ : RealTypeBounds => recAbstractTypeConstructor(pat)
5195
- case _ => null
5195
+ case _ : RealTypeBounds =>
5196
+ recAbstractTypeConstructor(pat)
5197
+ case TypeAlias (tl @ HKTypeLambda (onlyParam :: Nil , resType : RefinedType )) =>
5198
+ /* Unlike for eta-expanded classes, the typer does not automatically
5199
+ * dealias poly type aliases to refined types. So we have to give them
5200
+ * a chance here.
5201
+ * We are quite specific about the shape of type aliases that we are willing
5202
+ * to dealias this way, because we must not dealias arbitrary type constructors
5203
+ * that could refine the bounds of the captures; those would amount of
5204
+ * type-test + capture combos, which are out of the specced match types.
5205
+ */
5206
+ rec(pat.superType, variance)
5207
+ case _ =>
5208
+ null
5196
5209
5197
5210
case pat @ AppliedType (tycon : TypeParamRef , _) if variance == 1 =>
5198
5211
recAbstractTypeConstructor(pat)
5199
5212
5213
+ case pat @ RefinedType (parent, refinedName : TypeName , TypeAlias (alias @ TypeParamRef (binder, num)))
5214
+ if variance == 1 && (binder eq caseLambda) =>
5215
+ parent.member(refinedName) match
5216
+ case refinedMember : SingleDenotation if refinedMember.exists =>
5217
+ // Check that the bounds of the capture contain the bounds of the inherited member
5218
+ val refinedMemberBounds = refinedMember.info
5219
+ val captureBounds = caseLambda.paramInfos(num)
5220
+ if captureBounds.contains(refinedMemberBounds) then
5221
+ /* In this case, we know that any member we eventually find during reduction
5222
+ * will have bounds that fit in the bounds of the capture. Therefore, no
5223
+ * type-test + capture combo is necessary, and we can apply the specced match types.
5224
+ */
5225
+ val capture = rec(alias, variance = 0 ).asInstanceOf [MatchTypeCasePattern .Capture ]
5226
+ MatchTypeCasePattern .TypeMemberExtractor (refinedName, capture)
5227
+ else
5228
+ // Otherwise, a type-test + capture combo might be necessary, and we are out of spec
5229
+ null
5230
+ case _ =>
5231
+ // If the member does not refine a member of the `parent`, we are out of spec
5232
+ null
5233
+
5200
5234
case _ =>
5201
5235
MatchTypeCasePattern .TypeTest (pat)
5202
5236
end rec
0 commit comments