Skip to content

Commit d0e9062

Browse files
committed
Extension check checks for no parens not empty parens
1 parent 72d0026 commit d0e9062

File tree

3 files changed

+25
-108
lines changed

3 files changed

+25
-108
lines changed

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

+23-17
Original file line numberDiff line numberDiff line change
@@ -1150,8 +1150,8 @@ object RefChecks {
11501150
* This check is suppressed if the method is an override. (Because the type of the receiver
11511151
* may be narrower in the override.)
11521152
*
1153-
* If the extension method is nullary, it is always hidden by a member of the same name.
1154-
* (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
1153+
* If the extension method is nilary, it is always hidden by a member of the same name.
1154+
* (Either the member is nilary, or the reference is taken as the eta-expansion of the member.)
11551155
*
11561156
* This check is in lieu of a more expensive use-site check that an application failed to use an extension.
11571157
* That check would account for accessibility and opacity. As a limitation, this check considers
@@ -1175,25 +1175,29 @@ object RefChecks {
11751175
extension (tp: Type)
11761176
def explicit = Applications.stripImplicit(tp.stripPoly, wildcardOnly = true)
11771177
def hasImplicitParams = tp.stripPoly match { case mt: MethodType => mt.isImplicitMethod case _ => false }
1178+
def isNilary = tp.stripPoly match { case mt: MethodType => false case _ => true }
11781179
val explicitInfo = sym.info.explicit // consider explicit value params
1179-
val target0 = explicitInfo.firstParamTypes.head // required for extension method, the putative receiver
1180-
val target = target0.dealiasKeepOpaques.typeSymbol.info
1181-
val methTp = explicitInfo.resultType // skip leading implicits and the "receiver" parameter
1182-
def memberMatchesMethod(member: Denotation) =
1180+
def memberHidesMethod(member: Denotation): Boolean =
1181+
val methTp = explicitInfo.resultType // skip leading implicits and the "receiver" parameter
1182+
if methTp.isNilary then
1183+
return true // extension without parens is always hidden by a member of same name
11831184
val memberIsImplicit = member.info.hasImplicitParams
1184-
val paramTps =
1185-
if memberIsImplicit then methTp.stripPoly.firstParamTypes
1186-
else methTp.explicit.firstParamTypes
11871185
inline def paramsCorrespond =
1186+
val paramTps =
1187+
if memberIsImplicit then methTp.stripPoly.firstParamTypes
1188+
else methTp.explicit.firstParamTypes
11881189
val memberParamTps = member.info.stripPoly.firstParamTypes
11891190
memberParamTps.corresponds(paramTps): (m, x) =>
11901191
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias && (x frozen_<:< m)
1191-
paramTps.isEmpty || memberIsImplicit && !methTp.hasImplicitParams || paramsCorrespond
1192-
def hidden =
1193-
target.nonPrivateMember(sym.name)
1194-
.filterWithPredicate: member =>
1195-
member.symbol.isPublic && memberMatchesMethod(member)
1196-
.exists
1192+
memberIsImplicit && !methTp.hasImplicitParams || paramsCorrespond
1193+
def targetOfHiddenExtension: Symbol =
1194+
val target =
1195+
val target0 = explicitInfo.firstParamTypes.head // required for extension method, the putative receiver
1196+
target0.dealiasKeepOpaques.typeSymbol.info
1197+
val member = target.nonPrivateMember(sym.name)
1198+
.filterWithPredicate: member =>
1199+
member.symbol.isPublic && memberHidesMethod(member)
1200+
if member.exists then target.typeSymbol else NoSymbol
11971201
if sym.is(HasDefaultParams) then
11981202
val getterDenot =
11991203
val receiverName = explicitInfo.firstParamNames.head
@@ -1202,8 +1206,10 @@ object RefChecks {
12021206
sym.owner.info.member(getterName)
12031207
if getterDenot.exists
12041208
then report.warning(ExtensionHasDefault(sym), getterDenot.symbol.srcPos)
1205-
if !sym.nextOverriddenSymbol.exists && hidden
1206-
then report.warning(ExtensionNullifiedByMember(sym, target.typeSymbol), sym.srcPos)
1209+
if !sym.nextOverriddenSymbol.exists then
1210+
val target = targetOfHiddenExtension
1211+
if target.exists then
1212+
report.warning(ExtensionNullifiedByMember(sym, target), sym.srcPos)
12071213
end checkExtensionMethods
12081214

12091215
/** Verify that references in the user-defined `@implicitNotFound` message are valid.

tests/warn/i16743.check

-91
This file was deleted.

tests/warn/i16743.scala

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ trait T:
2525
def x(n: Int): Int = 42 + n
2626
def y(n: Int): Int = u + n
2727
def y(s: String): String = s + u
28+
def z(s: String): String = s + m
2829

2930
extension (_t: T)
3031
def t = 27 // warn
@@ -45,6 +46,7 @@ extension (_t: T)
4546
def w(using String)(n: String): Int = (summon[String] + n).toInt
4647
def x(using String)(n: Int): Int = summon[String].toInt + n // warn
4748
def y(using String)(s: String): String = s + summon[String] // warn
49+
def z(): String = "extension"
4850

4951
// deferred extension is defined in subclass
5052
trait Foo:

0 commit comments

Comments
 (0)