@@ -1026,6 +1026,8 @@ object RefChecks {
1026
1026
* An extension method is hidden if it does not offer a parameter that is not subsumed
1027
1027
* by the corresponding parameter of the member with the same name (or of all alternatives of an overload).
1028
1028
*
1029
+ * This check is suppressed if this method is an override.
1030
+ *
1029
1031
* For example, it is not possible to define a type-safe extension `contains` for `Set`,
1030
1032
* since for any parameter type, the existing `contains` method will compile and would be used.
1031
1033
*
@@ -1043,31 +1045,32 @@ object RefChecks {
1043
1045
* If the extension method is nullary, it is always hidden by a member of the same name.
1044
1046
* (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
1045
1047
*/
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)
1071
1074
end checkExtensionMethods
1072
1075
1073
1076
/** Verify that references in the user-defined `@implicitNotFound` message are valid.
0 commit comments