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