Skip to content

Commit 07d63c4

Browse files
authored
Check extension method at typer (#24199)
Fixes #24198 Refchecks follows typer, so check extension method signature at typer.
2 parents ce57b71 + a71b76c commit 07d63c4

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,8 +1136,8 @@ object RefChecks {
11361136
* This check is suppressed if the method is an override. (Because the type of the receiver
11371137
* may be narrower in the override.)
11381138
*
1139-
* If the extension method is nilary, it is always hidden by a member of the same name.
1140-
* (Either the member is nilary, or the reference is taken as the eta-expansion of the member.)
1139+
* If the extension method is parameterless, it is always hidden by a member of the same name.
1140+
* (Either the member is parameterless, or the reference is taken as the eta-expansion of the member.)
11411141
*
11421142
* This check is in lieu of a more expensive use-site check that an application failed to use an extension.
11431143
* That check would account for accessibility and opacity. As a limitation, this check considers
@@ -1157,15 +1157,15 @@ object RefChecks {
11571157
* parameters of the extension method must be distinguishable from the member parameters, as described above.
11581158
*/
11591159
def checkExtensionMethods(sym: Symbol)(using Context): Unit =
1160-
if sym.is(Extension) then
1160+
if sym.is(Extension) then atPhase(typerPhase):
11611161
extension (tp: Type)
11621162
def explicit = Applications.stripImplicit(tp.stripPoly, wildcardOnly = true)
11631163
def hasImplicitParams = tp.stripPoly match { case mt: MethodType => mt.isImplicitMethod case _ => false }
1164-
def isNilary = tp.stripPoly match { case mt: MethodType => false case _ => true }
1164+
def isParamLess = tp.stripPoly match { case mt: MethodType => false case _ => true }
11651165
val explicitInfo = sym.info.explicit // consider explicit value params
11661166
def memberHidesMethod(member: Denotation): Boolean =
11671167
val methTp = explicitInfo.resultType // skip leading implicits and the "receiver" parameter
1168-
if methTp.isNilary then
1168+
if methTp.isParamLess then
11691169
return true // extension without parens is always hidden by a member of same name
11701170
val memberIsImplicit = member.info.hasImplicitParams
11711171
inline def paramsCorrespond =
@@ -1174,7 +1174,8 @@ object RefChecks {
11741174
else methTp.explicit.firstParamTypes
11751175
val memberParamTps = member.info.stripPoly.firstParamTypes
11761176
memberParamTps.corresponds(paramTps): (m, x) =>
1177-
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias && (x frozen_<:< m)
1177+
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias
1178+
&& (x frozen_<:< m)
11781179
memberIsImplicit && !methTp.hasImplicitParams || paramsCorrespond
11791180
def targetOfHiddenExtension: Symbol =
11801181
val target =

tests/warn/i16743.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ object Depending:
9393
def f(using d: Depends) = d.thing.y
9494
def g(using d: Depends) = d.thing.length()
9595

96+
class i24198:
97+
def m(ss: String*) = ss.foldLeft("")(_ + _)
98+
object i24198:
99+
extension (r: i24198) def m(ss: Seq[String]) = ss.foldRight("!")(_ + _)
100+
96101
@main def test() =
97102
val x = new T {}
98103
println(x.f(42)) // OK!
@@ -119,3 +124,6 @@ object Depending:
119124
given String = "42"
120125
x.w("27")
121126
}
127+
println:
128+
val sut = i24198()
129+
sut.m(List("hello", ", ", "world"))

0 commit comments

Comments
 (0)