@@ -605,10 +605,24 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
605
605
isSubRefinements(tp1w.asInstanceOf [RefinedType ], tp2, skipped2) &&
606
606
recur(tp1, skipped2)
607
607
608
- if ctx.phase == Phases .checkCapturesPhase && defn.isFunctionOrPolyType(tp2) then
609
- hasMatchingMember(nme.apply, tp1, tp2)
610
- else
611
- compareRefined
608
+ def isSubInfo (info1 : Type , info2 : Type ): Boolean = (info1, info2) match
609
+ case (info1 : PolyType , info2 : PolyType ) =>
610
+ sameLength(info1.paramNames, info2.paramNames)
611
+ && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1))
612
+ case (info1 : MethodType , info2 : MethodType ) =>
613
+ matchingMethodParams(info1, info2, precise = false )
614
+ && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1))
615
+ case _ =>
616
+ isSubType(info1, info2)
617
+
618
+ tp1 match
619
+ case tp1 : RefinedType
620
+ if ctx.phase == Phases .checkCapturesPhase
621
+ && defn.isFunctionOrPolyType(tp1)
622
+ && defn.isFunctionOrPolyType(tp2) =>
623
+ isSubInfo(tp1.refinedInfo, tp2.refinedInfo)
624
+ case _ =>
625
+ compareRefined
612
626
case tp2 : RecType =>
613
627
def compareRec = tp1.safeDealias match {
614
628
case tp1 : RecType =>
@@ -1793,69 +1807,68 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1793
1807
protected def hasMatchingMember (name : Name , tp1 : Type , tp2 : RefinedType ): Boolean =
1794
1808
trace(i " hasMatchingMember( $tp1 . $name :? ${tp2.refinedInfo}), mbr: ${tp1.member(name).info}" , subtyping) {
1795
1809
1796
- def qualifies (m : SingleDenotation ): Boolean =
1797
- // If the member is an abstract type and the prefix is a path, compare the member itself
1798
- // instead of its bounds. This case is needed situations like:
1799
- //
1800
- // class C { type T }
1801
- // val foo: C
1802
- // foo.type <: C { type T {= , <: , >:} foo.T }
1803
- //
1804
- // or like:
1805
- //
1806
- // class C[T]
1807
- // C[?] <: C[TV]
1808
- //
1809
- // where TV is a type variable. See i2397.scala for an example of the latter.
1810
- def matchAbstractTypeMember (info1 : Type ): Boolean = info1 match {
1811
- case TypeBounds (lo, hi) if lo ne hi =>
1812
- tp2.refinedInfo match {
1813
- case rinfo2 : TypeBounds if tp1.isStable =>
1814
- val ref1 = tp1.widenExpr.select(name)
1815
- isSubType(rinfo2.lo, ref1) && isSubType(ref1, rinfo2.hi)
1816
- case _ =>
1817
- false
1818
- }
1819
- case _ => false
1820
- }
1810
+ // If the member is an abstract type and the prefix is a path, compare the member itself
1811
+ // instead of its bounds. This case is needed situations like:
1812
+ //
1813
+ // class C { type T }
1814
+ // val foo: C
1815
+ // foo.type <: C { type T {= , <: , >:} foo.T }
1816
+ //
1817
+ // or like:
1818
+ //
1819
+ // class C[T]
1820
+ // C[?] <: C[TV]
1821
+ //
1822
+ // where TV is a type variable. See i2397.scala for an example of the latter.
1823
+ def matchAbstractTypeMember (info1 : Type ): Boolean = info1 match {
1824
+ case TypeBounds (lo, hi) if lo ne hi =>
1825
+ tp2.refinedInfo match {
1826
+ case rinfo2 : TypeBounds if tp1.isStable =>
1827
+ val ref1 = tp1.widenExpr.select(name)
1828
+ isSubType(rinfo2.lo, ref1) && isSubType(ref1, rinfo2.hi)
1829
+ case _ =>
1830
+ false
1831
+ }
1832
+ case _ => false
1833
+ }
1821
1834
1822
- // An additional check for type member matching: If the refinement of the
1823
- // supertype `tp2` does not refer to a member symbol defined in the parent of `tp2`.
1824
- // then the symbol referred to in the subtype must have a signature that coincides
1825
- // in its parameters with the refinement's signature. The reason for the check
1826
- // is that if the refinement does not refer to a member symbol, we will have to
1827
- // resort to reflection to invoke the member. And Java reflection needs to know exact
1828
- // erased parameter types. See neg/i12211.scala. Other reflection algorithms could
1829
- // conceivably dispatch without knowning precise parameter signatures. One can signal
1830
- // this by inheriting from the `scala.reflect.SignatureCanBeImprecise` marker trait,
1831
- // in which case the signature test is elided.
1832
- def sigsOK (symInfo : Type , info2 : Type ) =
1833
- tp2.underlyingClassRef(refinementOK = true ).member(name).exists
1834
- || tp2.derivesFrom(defn.WithoutPreciseParameterTypesClass )
1835
- || symInfo.isInstanceOf [MethodType ]
1836
- && symInfo.signature.consistentParams(info2.signature)
1837
-
1838
- // A relaxed version of isSubType, which compares method types
1839
- // under the standard arrow rule which is contravarient in the parameter types,
1840
- // but under the condition that signatures might have to match (see sigsOK)
1841
- // This relaxed version is needed to correctly compare dependent function types.
1842
- // See pos/i12211.scala.
1843
- def isSubInfo (info1 : Type , info2 : Type , symInfo : Type ): Boolean =
1844
- info2 match
1845
- case info2 : MethodType =>
1846
- info1 match
1847
- case info1 : MethodType =>
1848
- val symInfo1 = symInfo.stripPoly
1849
- matchingMethodParams(info1, info2, precise = false )
1850
- && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType)
1851
- && sigsOK(symInfo1, info2)
1852
- case _ => isSubType(info1, info2)
1853
- case _ => isSubType(info1, info2)
1835
+ // An additional check for type member matching: If the refinement of the
1836
+ // supertype `tp2` does not refer to a member symbol defined in the parent of `tp2`.
1837
+ // then the symbol referred to in the subtype must have a signature that coincides
1838
+ // in its parameters with the refinement's signature. The reason for the check
1839
+ // is that if the refinement does not refer to a member symbol, we will have to
1840
+ // resort to reflection to invoke the member. And Java reflection needs to know exact
1841
+ // erased parameter types. See neg/i12211.scala. Other reflection algorithms could
1842
+ // conceivably dispatch without knowning precise parameter signatures. One can signal
1843
+ // this by inheriting from the `scala.reflect.SignatureCanBeImprecise` marker trait,
1844
+ // in which case the signature test is elided.
1845
+ def sigsOK (symInfo : Type , info2 : Type ) =
1846
+ tp2.underlyingClassRef(refinementOK = true ).member(name).exists
1847
+ || tp2.derivesFrom(defn.WithoutPreciseParameterTypesClass )
1848
+ || symInfo.isInstanceOf [MethodType ]
1849
+ && symInfo.signature.consistentParams(info2.signature)
1850
+
1851
+ // A relaxed version of isSubType, which compares method types
1852
+ // under the standard arrow rule which is contravarient in the parameter types,
1853
+ // but under the condition that signatures might have to match (see sigsOK)
1854
+ // This relaxed version is needed to correctly compare dependent function types.
1855
+ // See pos/i12211.scala.
1856
+ def isSubInfo (info1 : Type , info2 : Type , symInfo : Type ): Boolean =
1857
+ info2 match
1858
+ case info2 : MethodType =>
1859
+ info1 match
1860
+ case info1 : MethodType =>
1861
+ val symInfo1 = symInfo.stripPoly
1862
+ matchingMethodParams(info1, info2, precise = false )
1863
+ && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo1.resultType)
1864
+ && sigsOK(symInfo1, info2)
1865
+ case _ => isSubType(info1, info2)
1866
+ case _ => isSubType(info1, info2)
1854
1867
1868
+ def qualifies (m : SingleDenotation ): Boolean =
1855
1869
val info1 = m.info.widenExpr
1856
1870
isSubInfo(info1, tp2.refinedInfo.widenExpr, m.symbol.info.orElse(info1))
1857
1871
|| matchAbstractTypeMember(m.info)
1858
- end qualifies
1859
1872
1860
1873
tp1.member(name) match // inlined hasAltWith for performance
1861
1874
case mbr : SingleDenotation => qualifies(mbr)
@@ -1980,15 +1993,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1980
1993
case formal2 :: rest2 =>
1981
1994
val formal2a = if (tp2.isParamDependent) formal2.subst(tp2, tp1) else formal2
1982
1995
val paramsMatch =
1983
- if ctx.phase == Phases .checkCapturesPhase then
1984
- // ^^^ TODO: make this more robust. We want isSubtypeWhenFrozen for the type parts
1985
- // of formals but isSameType for the capture sets. We cannot use isSubType for
1986
- // capture sets since that constrains inferred arguments not enough, and we
1987
- // cannot constrain them later since we would run into the "cannot constrain mapped
1988
- // type from new source" problem.
1989
- isSubType(formal2a, formal1)
1990
- else if precise then
1996
+ if precise then
1991
1997
isSameTypeWhenFrozen(formal1, formal2a)
1998
+ else if ctx.phase == Phases .checkCapturesPhase then
1999
+ isSubType(formal2a, formal1)
1992
2000
else
1993
2001
isSubTypeWhenFrozen(formal2a, formal1)
1994
2002
paramsMatch && loop(rest1, rest2)
0 commit comments