Skip to content

Commit 1f9f1a0

Browse files
som-snytttgodzik
authored andcommitted
Extension check checks for no parens not empty parens
[Cherry-picked d0e9062]
1 parent 7c90bb2 commit 1f9f1a0

File tree

3 files changed

+25
-108
lines changed

3 files changed

+25
-108
lines changed

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

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,8 @@ object RefChecks {
10431043
* This check is suppressed if the method is an override. (Because the type of the receiver
10441044
* may be narrower in the override.)
10451045
*
1046-
* If the extension method is nullary, it is always hidden by a member of the same name.
1047-
* (Either the member is nullary, or the reference is taken as the eta-expansion of the member.)
1046+
* If the extension method is nilary, it is always hidden by a member of the same name.
1047+
* (Either the member is nilary, or the reference is taken as the eta-expansion of the member.)
10481048
*
10491049
* This check is in lieu of a more expensive use-site check that an application failed to use an extension.
10501050
* That check would account for accessibility and opacity. As a limitation, this check considers
@@ -1068,25 +1068,29 @@ object RefChecks {
10681068
extension (tp: Type)
10691069
def explicit = Applications.stripImplicit(tp.stripPoly, wildcardOnly = true)
10701070
def hasImplicitParams = tp.stripPoly match { case mt: MethodType => mt.isImplicitMethod case _ => false }
1071+
def isNilary = tp.stripPoly match { case mt: MethodType => false case _ => true }
10711072
val explicitInfo = sym.info.explicit // consider explicit value params
1072-
val target0 = explicitInfo.firstParamTypes.head // required for extension method, the putative receiver
1073-
val target = target0.dealiasKeepOpaques.typeSymbol.info
1074-
val methTp = explicitInfo.resultType // skip leading implicits and the "receiver" parameter
1075-
def memberMatchesMethod(member: Denotation) =
1073+
def memberHidesMethod(member: Denotation): Boolean =
1074+
val methTp = explicitInfo.resultType // skip leading implicits and the "receiver" parameter
1075+
if methTp.isNilary then
1076+
return true // extension without parens is always hidden by a member of same name
10761077
val memberIsImplicit = member.info.hasImplicitParams
1077-
val paramTps =
1078-
if memberIsImplicit then methTp.stripPoly.firstParamTypes
1079-
else methTp.explicit.firstParamTypes
10801078
inline def paramsCorrespond =
1079+
val paramTps =
1080+
if memberIsImplicit then methTp.stripPoly.firstParamTypes
1081+
else methTp.explicit.firstParamTypes
10811082
val memberParamTps = member.info.stripPoly.firstParamTypes
10821083
memberParamTps.corresponds(paramTps): (m, x) =>
10831084
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias && (x frozen_<:< m)
1084-
paramTps.isEmpty || memberIsImplicit && !methTp.hasImplicitParams || paramsCorrespond
1085-
def hidden =
1086-
target.nonPrivateMember(sym.name)
1087-
.filterWithPredicate: member =>
1088-
member.symbol.isPublic && memberMatchesMethod(member)
1089-
.exists
1085+
memberIsImplicit && !methTp.hasImplicitParams || paramsCorrespond
1086+
def targetOfHiddenExtension: Symbol =
1087+
val target =
1088+
val target0 = explicitInfo.firstParamTypes.head // required for extension method, the putative receiver
1089+
target0.dealiasKeepOpaques.typeSymbol.info
1090+
val member = target.nonPrivateMember(sym.name)
1091+
.filterWithPredicate: member =>
1092+
member.symbol.isPublic && memberHidesMethod(member)
1093+
if member.exists then target.typeSymbol else NoSymbol
10901094
if sym.is(HasDefaultParams) then
10911095
val getterDenot =
10921096
val receiverName = explicitInfo.firstParamNames.head
@@ -1095,8 +1099,10 @@ object RefChecks {
10951099
sym.owner.info.member(getterName)
10961100
if getterDenot.exists
10971101
then report.warning(ExtensionHasDefault(sym), getterDenot.symbol.srcPos)
1098-
if !sym.nextOverriddenSymbol.exists && hidden
1099-
then report.warning(ExtensionNullifiedByMember(sym, target.typeSymbol), sym.srcPos)
1102+
if !sym.nextOverriddenSymbol.exists then
1103+
val target = targetOfHiddenExtension
1104+
if target.exists then
1105+
report.warning(ExtensionNullifiedByMember(sym, target), sym.srcPos)
11001106
end checkExtensionMethods
11011107

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

tests/warn/i16743.check

Lines changed: 0 additions & 91 deletions
This file was deleted.

tests/warn/i16743.scala

Lines changed: 2 additions & 0 deletions
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)