@@ -1108,6 +1108,8 @@ object RefChecks {
1108
1108
* An extension method is hidden if it does not offer a parameter that is not subsumed
1109
1109
* by the corresponding parameter of the member with the same name (or of all alternatives of an overload).
1110
1110
*
1111
+ * This check is suppressed if this method is an override.
1112
+ *
1111
1113
* For example, it is not possible to define a type-safe extension `contains` for `Set`,
1112
1114
* since for any parameter type, the existing `contains` method will compile and would be used.
1113
1115
*
@@ -1125,31 +1127,32 @@ object RefChecks {
1125
1127
* If the extension method is nullary, it is always hidden by a member of the same name.
1126
1128
* (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
1127
1129
*/
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)
1153
1156
end checkExtensionMethods
1154
1157
1155
1158
/** Verify that references in the user-defined `@implicitNotFound` message are valid.
0 commit comments