Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1135,8 +1135,8 @@ object RefChecks {
* This check is suppressed if the method is an override. (Because the type of the receiver
* may be narrower in the override.)
*
* If the extension method is nilary, it is always hidden by a member of the same name.
* (Either the member is nilary, or the reference is taken as the eta-expansion of the member.)
* If the extension method is parameterless, it is always hidden by a member of the same name.
* (Either the member is parameterless, or the reference is taken as the eta-expansion of the member.)
*
* This check is in lieu of a more expensive use-site check that an application failed to use an extension.
* That check would account for accessibility and opacity. As a limitation, this check considers
Expand All @@ -1156,15 +1156,15 @@ object RefChecks {
* parameters of the extension method must be distinguishable from the member parameters, as described above.
*/
def checkExtensionMethods(sym: Symbol)(using Context): Unit =
if sym.is(Extension) then
if sym.is(Extension) then atPhase(typerPhase):
extension (tp: Type)
def explicit = Applications.stripImplicit(tp.stripPoly, wildcardOnly = true)
def hasImplicitParams = tp.stripPoly match { case mt: MethodType => mt.isImplicitMethod case _ => false }
def isNilary = tp.stripPoly match { case mt: MethodType => false case _ => true }
def isParamLess = tp.stripPoly match { case mt: MethodType => false case _ => true }
val explicitInfo = sym.info.explicit // consider explicit value params
def memberHidesMethod(member: Denotation): Boolean =
val methTp = explicitInfo.resultType // skip leading implicits and the "receiver" parameter
if methTp.isNilary then
if methTp.isParamLess then
return true // extension without parens is always hidden by a member of same name
val memberIsImplicit = member.info.hasImplicitParams
inline def paramsCorrespond =
Expand All @@ -1173,7 +1173,8 @@ object RefChecks {
else methTp.explicit.firstParamTypes
val memberParamTps = member.info.stripPoly.firstParamTypes
memberParamTps.corresponds(paramTps): (m, x) =>
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias && (x frozen_<:< m)
m.typeSymbol.denot.isOpaqueAlias == x.typeSymbol.denot.isOpaqueAlias
&& (x frozen_<:< m)
memberIsImplicit && !methTp.hasImplicitParams || paramsCorrespond
def targetOfHiddenExtension: Symbol =
val target =
Expand Down
8 changes: 8 additions & 0 deletions tests/warn/i16743.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ object Depending:
def f(using d: Depends) = d.thing.y
def g(using d: Depends) = d.thing.length()

class i24198:
def m(ss: String*) = ss.foldLeft("")(_ + _)
object i24198:
extension (r: i24198) def m(ss: Seq[String]) = ss.foldRight("!")(_ + _)

@main def test() =
val x = new T {}
println(x.f(42)) // OK!
Expand All @@ -119,3 +124,6 @@ object Depending:
given String = "42"
x.w("27")
}
println:
val sut = i24198()
sut.m(List("hello", ", ", "world"))
Loading