@@ -1698,58 +1698,68 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
16981698 */
16991699 protected def hasMatchingMember (name : Name , tp1 : Type , tp2 : RefinedType ): Boolean =
17001700 trace(i " hasMatchingMember( $tp1 . $name :? ${tp2.refinedInfo}), mbr: ${tp1.member(name).info}" , subtyping) {
1701- // If the member is an abstract type and the prefix is a path, compare the member itself
1702- // instead of its bounds. This case is needed situations like:
1703- //
1704- // class C { type T }
1705- // val foo: C
1706- // foo.type <: C { type T {= , <: , >:} foo.T }
1707- //
1708- // or like:
1709- //
1710- // class C[T]
1711- // C[?] <: C[TV]
1712- //
1713- // where TV is a type variable. See i2397.scala for an example of the latter.
1714- def matchAbstractTypeMember (info1 : Type ) = info1 match {
1715- case TypeBounds (lo, hi) if lo ne hi =>
1716- tp2.refinedInfo match {
1717- case rinfo2 : TypeBounds if tp1.isStable =>
1718- val ref1 = tp1.widenExpr.select(name)
1719- isSubType(rinfo2.lo, ref1) && isSubType(ref1, rinfo2.hi)
1720- case _ =>
1721- false
1722- }
1723- case _ => false
1724- }
17251701
1726- // A relaxed version of isSubType, which compares method types
1727- // under the standard arrow rule which is contravarient in the parameter types,
1728- // but only if `tp2.refinedName` is also defined in the underlying class of tp2.
1729- // The reason for the "but only" retriction is that if `tp2.refinedName`
1730- // is not otherwise defined, we will have to resort to reflection to invoke
1731- // the member. And reflection needs to know exact parameter types. The relaxation is
1732- // needed to correctly compare dependent function types.
1733- // See {pos,neg}/i12211.scala as test cases.
1734- def isSubInfo (info1 : Type , info2 : Type ): Boolean =
1735- info2 match
1736- case info2 : MethodType
1737- if tp2.underlyingClassRef(refinementOK = true ).member(tp2.refinedName).exists =>
1738- info1 match
1739- case info1 : MethodType =>
1740- matchingMethodParams(info1, info2, precise = false )
1741- && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1))
1742- case _ => isSubType(info1, info2)
1743- case _ => isSubType(info1, info2)
1744-
1745- def qualifies (m : SingleDenotation ) =
1746- isSubInfo(m.info.widenExpr, tp2.refinedInfo.widenExpr)
1702+ def qualifies (m : SingleDenotation ): Boolean =
1703+ // If the member is an abstract type and the prefix is a path, compare the member itself
1704+ // instead of its bounds. This case is needed situations like:
1705+ //
1706+ // class C { type T }
1707+ // val foo: C
1708+ // foo.type <: C { type T {= , <: , >:} foo.T }
1709+ //
1710+ // or like:
1711+ //
1712+ // class C[T]
1713+ // C[?] <: C[TV]
1714+ //
1715+ // where TV is a type variable. See i2397.scala for an example of the latter.
1716+ def matchAbstractTypeMember (info1 : Type ): Boolean = info1 match {
1717+ case TypeBounds (lo, hi) if lo ne hi =>
1718+ tp2.refinedInfo match {
1719+ case rinfo2 : TypeBounds if tp1.isStable =>
1720+ val ref1 = tp1.widenExpr.select(name)
1721+ isSubType(rinfo2.lo, ref1) && isSubType(ref1, rinfo2.hi)
1722+ case _ =>
1723+ false
1724+ }
1725+ case _ => false
1726+ }
1727+
1728+ // An additional check for type member matching: If the refinement of the
1729+ // supertype `tp2` does not refer to a member symbol defined in the parent of `tp2`.
1730+ // then the symbol referred to in the subtype must have a signature that coincides
1731+ // in its parameters with the refinement's signature. The reason for the check
1732+ // is that if the refinement does not refer to a member symbol, we will have to
1733+ // resort to reflection to invoke the member. And reflection needs to know exact
1734+ // erased parameter types. See neg/i12211.scala.
1735+ def sigsOK (symInfo : Type , info2 : Type ) =
1736+ tp2.underlyingClassRef(refinementOK = true ).member(name).exists
1737+ || symInfo.isInstanceOf [MethodType ]
1738+ && symInfo.signature.consistentParams(info2.signature)
1739+
1740+ // A relaxed version of isSubType, which compares method types
1741+ // under the standard arrow rule which is contravarient in the parameter types,
1742+ // but under the condition that signatures might have to match (see sigsOK)
1743+ // This releaxed version is needed to correctly compare dependent function types.
1744+ // See pos/i12211.scala.
1745+ def isSubInfo (info1 : Type , info2 : Type , symInfo : Type ): Boolean =
1746+ info2 match
1747+ case info2 : MethodType =>
1748+ info1 match
1749+ case info1 : MethodType =>
1750+ matchingMethodParams(info1, info2, precise = false )
1751+ && isSubInfo(info1.resultType, info2.resultType.subst(info2, info1), symInfo.stripPoly.resultType)
1752+ && sigsOK(symInfo, info2)
1753+ case _ => isSubType(info1, info2)
1754+ case _ => isSubType(info1, info2)
1755+
1756+ isSubInfo(m.info.widenExpr, tp2.refinedInfo.widenExpr, m.symbol.info)
17471757 || matchAbstractTypeMember(m.info)
1758+ end qualifies
17481759
1749- tp1.member(name) match { // inlined hasAltWith for performance
1760+ tp1.member(name) match // inlined hasAltWith for performance
17501761 case mbr : SingleDenotation => qualifies(mbr)
17511762 case mbr => mbr hasAltWith qualifies
1752- }
17531763 }
17541764
17551765 final def ensureStableSingleton (tp : Type ): SingletonType = tp.stripTypeVar match {
0 commit comments