@@ -641,6 +641,14 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
641
641
def compareRefined : Boolean =
642
642
val tp1w = tp1.widen
643
643
644
+ if ctx.phase == Phases .checkCapturesPhase then
645
+ def compareInfo (info1 : Type , info2 : Type ): Boolean =
646
+ isSubInfo(info1, info2, NoType )
647
+ if defn.isFunctionType(tp2) then
648
+ tp1w.widenDealias match
649
+ case tp1 : RefinedType => return compareInfo(tp1.refinedInfo, tp2.refinedInfo)
650
+ case _ =>
651
+
644
652
val skipped2 = skipMatching(tp1w, tp2)
645
653
if (skipped2 eq tp2) || ! Config .fastPathForRefinedSubtype then
646
654
if containsAnd(tp1) then
@@ -1917,6 +1925,40 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1917
1925
case _ =>
1918
1926
refines.map(RefinedType (tp, _, _): Type ).reduce(AndType (_, _))
1919
1927
1928
+ // A relaxed version of isSubType, which compares method types
1929
+ // under the standard arrow rule which is contravariant in the parameter types,
1930
+ // but under the condition that signatures might have to match (see sigsOK)
1931
+ // This relaxed version is needed to correctly compare dependent function types.
1932
+ // See pos/i12211.scala.
1933
+ def isSubInfo (info1 : Type , info2 : Type , symInfo1 : Type , sigsOK : ((Type , Type ) => Boolean ) | Null = null , fallbackFn : ((Type , Type ) => Boolean ) | Null = null ): Boolean = trace(i " isSubInfo $info1 <:< $info2" ):
1934
+ def fallback =
1935
+ if fallbackFn != null then fallbackFn(info1, info2)
1936
+ else isSubType(info1, info2)
1937
+ val isCCPhase = ctx.phase == Phases .checkCapturesPhase
1938
+
1939
+ (info1, info2) match
1940
+ case (info1 : PolyType , info2 : PolyType ) if ccEnabled => // See TODO about `ccEnabled` in `sigsOK`, this should also go under `relaxedSubtyping`.
1941
+ comparingTypeLambdas(info1, info2):
1942
+ info1.paramNames.hasSameLengthAs(info2.paramNames)
1943
+ && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType, sigsOK, fallbackFn)
1944
+ // Signature checks are never necessary because polymorphic
1945
+ // refinements are only allowed for the `apply` method of a
1946
+ // PolyFunction.
1947
+ case (info1 : MethodType , info2 : MethodType ) =>
1948
+ matchingMethodParams(info1, info2, precise = false )
1949
+ && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType, sigsOK, fallbackFn)
1950
+ && (if sigsOK != null then sigsOK(symInfo1, info2) else true )
1951
+ case _ => (info1.widenDealias, info2) match
1952
+ case (CapturingType (parent1, _), info2 : Type ) if isCCPhase =>
1953
+ val refs1 = info1.captureSet
1954
+ subCaptures(refs1, info2.captureSet, frozenConstraint).isOK && sameBoxed(info1, info2, refs1)
1955
+ && isSubInfo(parent1, info2, symInfo1, sigsOK, fallbackFn)
1956
+ case (info1 : Type , CapturingType (parent2, refs2)) if isCCPhase =>
1957
+ val refs1 = info1.captureSet
1958
+ (refs1.isAlwaysEmpty || subCaptures(refs1, refs2, frozenConstraint).isOK) && sameBoxed(info1, info2, refs1)
1959
+ && isSubInfo(info1, parent2, symInfo1, sigsOK, fallbackFn)
1960
+ case _ => fallback
1961
+
1920
1962
/** Can comparing this type on the left lead to an either? This is the case if
1921
1963
* the type is and AndType or contains embedded occurrences of AndTypes
1922
1964
*/
@@ -1984,43 +2026,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1984
2026
|| symInfo.isInstanceOf [MethodType ]
1985
2027
&& symInfo.signature.consistentParams(info2.signature)
1986
2028
1987
- def tp1IsSingleton : Boolean = tp1.isInstanceOf [SingletonType ]
1988
-
1989
- // A relaxed version of isSubType, which compares method types
1990
- // under the standard arrow rule which is contravariant in the parameter types,
1991
- // but under the condition that signatures might have to match (see sigsOK)
1992
- // This relaxed version is needed to correctly compare dependent function types.
1993
- // See pos/i12211.scala.
1994
- def isSubInfo (info1 : Type , info2 : Type , symInfo1 : Type ): Boolean =
1995
- def fallback = inFrozenGadtIf(tp1IsSingleton) { isSubType(info1, info2) }
1996
- info2 match
1997
- case info2 : PolyType if ccEnabled => // See TODO about `ccEnabled` in `sigsOK`, this should also go under `relaxedSubtyping`.
1998
- info1 match
1999
- case info1 : PolyType =>
2000
- comparingTypeLambdas(info1, info2):
2001
- info1.paramNames.hasSameLengthAs(info2.paramNames)
2002
- && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType)
2003
- // Signature checks are never necessary because polymorphic
2004
- // refinements are only allowed for the `apply` method of a
2005
- // PolyFunction.
2006
- case _ => fallback
2007
- case info2 : MethodType =>
2008
- info1 match
2009
- case info1 : MethodType =>
2010
- matchingMethodParams(info1, info2, precise = false )
2011
- && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType)
2012
- && sigsOK(symInfo1, info2)
2013
- case _ => fallback
2014
- case info2 @ CapturingType (parent2, refs2) if ctx.phase == Phases .checkCapturesPhase =>
2015
- val refs1 = info1.captureSet
2016
- (refs1.isAlwaysEmpty || subCaptures(refs1, refs2, frozenConstraint).isOK) && sameBoxed(info1, info2, refs1)
2017
- && isSubInfo(info1, parent2, symInfo1)
2018
- case _ =>
2019
- info1 match
2020
- case info1 @ CapturingType (parent1, refs1) if ctx.phase == Phases .checkCapturesPhase =>
2021
- subCaptures(refs1, info2.captureSet, frozenConstraint).isOK && sameBoxed(info1, info2, refs1)
2022
- && isSubInfo(parent1, info2, symInfo1)
2023
- case _ => fallback
2029
+ def fallback = (info1 : Type , info2 : Type ) =>
2030
+ def tp1IsSingleton : Boolean = tp1.isInstanceOf [SingletonType ]
2031
+ inFrozenGadtIf(tp1IsSingleton):
2032
+ isSubType(info1, info2)
2024
2033
2025
2034
def qualifies (m : SingleDenotation ): Boolean =
2026
2035
val info2 = tp2.refinedInfo
@@ -2035,7 +2044,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
2035
2044
// OK{ { def x(): T } <: { def x: T} // if x is Java defined
2036
2045
ExprType (info1.resType)
2037
2046
case info1 => info1
2038
- isSubInfo(info1, info2, m.symbol.info.orElse(info1))
2047
+ isSubInfo(info1, info2, m.symbol.info.orElse(info1), sigsOK, fallback )
2039
2048
|| matchAbstractTypeMember(m.info)
2040
2049
|| (tp1.isStable && m.symbol.isStableMember && isSubType(TermRef (tp1, m.symbol), tp2.refinedInfo))
2041
2050
0 commit comments