@@ -1026,6 +1026,8 @@ object RefChecks {
10261026 * An extension method is hidden if it does not offer a parameter that is not subsumed
10271027 * by the corresponding parameter of the member with the same name (or of all alternatives of an overload).
10281028 *
1029+ * This check is suppressed if this method is an override.
1030+ *
10291031 * For example, it is not possible to define a type-safe extension `contains` for `Set`,
10301032 * since for any parameter type, the existing `contains` method will compile and would be used.
10311033 *
@@ -1043,31 +1045,32 @@ object RefChecks {
10431045 * If the extension method is nullary, it is always hidden by a member of the same name.
10441046 * (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
10451047 */
1046- def checkExtensionMethods (sym : Symbol )(using Context ): Unit = if sym.is(Extension ) then
1047- extension (tp : Type )
1048- def strippedResultType = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).resultType
1049- def firstExplicitParamTypes = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).firstParamTypes
1050- def hasImplicitParams = tp.stripPoly match { case mt : MethodType => mt.isImplicitMethod case _ => false }
1051- val target = sym.info.firstExplicitParamTypes.head // required for extension method, the putative receiver
1052- val methTp = sym.info.strippedResultType // skip leading implicits and the "receiver" parameter
1053- def hidden =
1054- target.nonPrivateMember(sym.name)
1055- .filterWithPredicate:
1056- member =>
1057- val memberIsImplicit = member.info.hasImplicitParams
1058- val paramTps =
1059- if memberIsImplicit then methTp.stripPoly.firstParamTypes
1060- else methTp.firstExplicitParamTypes
1061-
1062- paramTps.isEmpty || memberIsImplicit && ! methTp.hasImplicitParams || {
1063- val memberParamTps = member.info.stripPoly.firstParamTypes
1064- ! memberParamTps.isEmpty
1065- && memberParamTps.lengthCompare(paramTps) == 0
1066- && memberParamTps.lazyZip(paramTps).forall((m, x) => x frozen_<:< m)
1067- }
1068- .exists
1069- if ! target.typeSymbol.denot.isAliasType && ! target.typeSymbol.denot.isOpaqueAlias && hidden
1070- then report.warning(ExtensionNullifiedByMember (sym, target.typeSymbol), sym.srcPos)
1048+ def checkExtensionMethods (sym : Symbol )(using Context ): Unit =
1049+ if sym.is(Extension ) && ! sym.nextOverriddenSymbol.exists then
1050+ extension (tp : Type )
1051+ def strippedResultType = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).resultType
1052+ def firstExplicitParamTypes = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).firstParamTypes
1053+ def hasImplicitParams = tp.stripPoly match { case mt : MethodType => mt.isImplicitMethod case _ => false }
1054+ val target = sym.info.firstExplicitParamTypes.head // required for extension method, the putative receiver
1055+ val methTp = sym.info.strippedResultType // skip leading implicits and the "receiver" parameter
1056+ def hidden =
1057+ target.nonPrivateMember(sym.name)
1058+ .filterWithPredicate:
1059+ member =>
1060+ val memberIsImplicit = member.info.hasImplicitParams
1061+ val paramTps =
1062+ if memberIsImplicit then methTp.stripPoly.firstParamTypes
1063+ else methTp.firstExplicitParamTypes
1064+
1065+ paramTps.isEmpty || memberIsImplicit && ! methTp.hasImplicitParams || {
1066+ val memberParamTps = member.info.stripPoly.firstParamTypes
1067+ ! memberParamTps.isEmpty
1068+ && memberParamTps.lengthCompare(paramTps) == 0
1069+ && memberParamTps.lazyZip(paramTps).forall((m, x) => x frozen_<:< m)
1070+ }
1071+ .exists
1072+ if ! target.typeSymbol.denot.isAliasType && ! target.typeSymbol.denot.isOpaqueAlias && hidden
1073+ then report.warning(ExtensionNullifiedByMember (sym, target.typeSymbol), sym.srcPos)
10711074 end checkExtensionMethods
10721075
10731076 /** Verify that references in the user-defined `@implicitNotFound` message are valid.
0 commit comments