@@ -5094,6 +5094,7 @@ object Types extends TypeUtils {
50945094 case BaseTypeTest (classType : TypeRef , argPatterns : List [MatchTypeCasePattern ], needsConcreteScrut : Boolean )
50955095 case CompileTimeS (argPattern : MatchTypeCasePattern )
50965096 case AbstractTypeConstructor (tycon : Type , argPatterns : List [MatchTypeCasePattern ])
5097+ case TypeMemberExtractor (typeMemberName : TypeName , capture : Capture )
50975098
50985099 def isTypeTest : Boolean =
50995100 this .isInstanceOf [TypeTest ]
@@ -5187,12 +5188,45 @@ object Types extends TypeUtils {
51875188 MatchTypeCasePattern .CompileTimeS (argPattern)
51885189 else
51895190 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
51925205
51935206 case pat @ AppliedType (tycon : TypeParamRef , _) if variance == 1 =>
51945207 recAbstractTypeConstructor(pat)
51955208
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+
51965230 case _ =>
51975231 MatchTypeCasePattern .TypeTest (pat)
51985232 end rec
0 commit comments