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