@@ -1108,6 +1108,8 @@ object RefChecks {
11081108 * An extension method is hidden if it does not offer a parameter that is not subsumed
11091109 * by the corresponding parameter of the member with the same name (or of all alternatives of an overload).
11101110 *
1111+ * This check is suppressed if this method is an override.
1112+ *
11111113 * For example, it is not possible to define a type-safe extension `contains` for `Set`,
11121114 * since for any parameter type, the existing `contains` method will compile and would be used.
11131115 *
@@ -1125,31 +1127,32 @@ object RefChecks {
11251127 * If the extension method is nullary, it is always hidden by a member of the same name.
11261128 * (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
11271129 */
1128- def checkExtensionMethods (sym : Symbol )(using Context ): Unit = if sym.is(Extension ) then
1129- extension (tp : Type )
1130- def strippedResultType = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).resultType
1131- def firstExplicitParamTypes = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).firstParamTypes
1132- def hasImplicitParams = tp.stripPoly match { case mt : MethodType => mt.isImplicitMethod case _ => false }
1133- val target = sym.info.firstExplicitParamTypes.head // required for extension method, the putative receiver
1134- val methTp = sym.info.strippedResultType // skip leading implicits and the "receiver" parameter
1135- def hidden =
1136- target.nonPrivateMember(sym.name)
1137- .filterWithPredicate:
1138- member =>
1139- val memberIsImplicit = member.info.hasImplicitParams
1140- val paramTps =
1141- if memberIsImplicit then methTp.stripPoly.firstParamTypes
1142- else methTp.firstExplicitParamTypes
1143-
1144- paramTps.isEmpty || memberIsImplicit && ! methTp.hasImplicitParams || {
1145- val memberParamTps = member.info.stripPoly.firstParamTypes
1146- ! memberParamTps.isEmpty
1147- && memberParamTps.lengthCompare(paramTps) == 0
1148- && memberParamTps.lazyZip(paramTps).forall((m, x) => x frozen_<:< m)
1149- }
1150- .exists
1151- if ! target.typeSymbol.denot.isAliasType && ! target.typeSymbol.denot.isOpaqueAlias && hidden
1152- then report.warning(ExtensionNullifiedByMember (sym, target.typeSymbol), sym.srcPos)
1130+ def checkExtensionMethods (sym : Symbol )(using Context ): Unit =
1131+ if sym.is(Extension ) && ! sym.nextOverriddenSymbol.exists then
1132+ extension (tp : Type )
1133+ def strippedResultType = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).resultType
1134+ def firstExplicitParamTypes = Applications .stripImplicit(tp.stripPoly, wildcardOnly = true ).firstParamTypes
1135+ def hasImplicitParams = tp.stripPoly match { case mt : MethodType => mt.isImplicitMethod case _ => false }
1136+ val target = sym.info.firstExplicitParamTypes.head // required for extension method, the putative receiver
1137+ val methTp = sym.info.strippedResultType // skip leading implicits and the "receiver" parameter
1138+ def hidden =
1139+ target.nonPrivateMember(sym.name)
1140+ .filterWithPredicate:
1141+ member =>
1142+ val memberIsImplicit = member.info.hasImplicitParams
1143+ val paramTps =
1144+ if memberIsImplicit then methTp.stripPoly.firstParamTypes
1145+ else methTp.firstExplicitParamTypes
1146+
1147+ paramTps.isEmpty || memberIsImplicit && ! methTp.hasImplicitParams || {
1148+ val memberParamTps = member.info.stripPoly.firstParamTypes
1149+ ! memberParamTps.isEmpty
1150+ && memberParamTps.lengthCompare(paramTps) == 0
1151+ && memberParamTps.lazyZip(paramTps).forall((m, x) => x frozen_<:< m)
1152+ }
1153+ .exists
1154+ if ! target.typeSymbol.denot.isAliasType && ! target.typeSymbol.denot.isOpaqueAlias && hidden
1155+ then report.warning(ExtensionNullifiedByMember (sym, target.typeSymbol), sym.srcPos)
11531156 end checkExtensionMethods
11541157
11551158 /** Verify that references in the user-defined `@implicitNotFound` message are valid.
0 commit comments