diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 79a0b279aefe..5759abeb9364 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -387,12 +387,12 @@ object Contexts { /** The next outer context whose tree is a template or package definition * Note: Currently unused - def enclTemplate: Context = { + def enclTemplate: Context = var c = this - while (c != NoContext && !c.tree.isInstanceOf[Template[?]] && !c.tree.isInstanceOf[PackageDef[?]]) - c = c.outer + while c != NoContext && !c.tree.isInstanceOf[Template[?]] && !c.tree.isInstanceOf[PackageDef[?]] + do c = c.outer c - }*/ + */ /** The context for a supercall. This context is used for elaborating * the parents of a class and their arguments. diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 87c80ebd78d0..5e74a744f365 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2441,7 +2441,7 @@ class PureUnitExpression(stat: untpd.Tree, tpe: Type)(using Context) class UnqualifiedCallToAnyRefMethod(stat: untpd.Tree, method: Symbol)(using Context) extends Message(UnqualifiedCallToAnyRefMethodID) { def kind = MessageKind.PotentialIssue - def msg(using Context) = i"Suspicious top-level unqualified call to ${hl(method.name.toString)}" + def msg(using Context) = i"Universal method ${hl(method.name.toString)} does not resolve to the enclosing class" def explain(using Context) = val getClassExtraHint = if method.name == nme.getClass_ && ctx.settings.classpath.value.contains("scala3-staging") then diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index cb1aea27c444..63d515035cf1 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -1252,11 +1252,13 @@ object RefChecks { end checkImplicitNotFoundAnnotation def checkAnyRefMethodCall(tree: Tree)(using Context): Unit = + extension (c: Context) def enclosingClass: Symbol = + c.outersIterator.find(_.isClassDefContext).map(_.owner).getOrElse(NoSymbol) if tree.symbol.exists && defn.topClasses.contains(tree.symbol.owner) then tree.tpe match - case tp: NamedType if tp.prefix.typeSymbol != ctx.owner.enclosingClass => + case tp: NamedType if tp.prefix.typeSymbol != ctx.enclosingClass => report.warning(UnqualifiedCallToAnyRefMethod(tree, tree.symbol), tree) - case _ => () + case _ => } import RefChecks.* diff --git a/tests/warn/i17266.check b/tests/warn/i17266.check index ce8626b14225..fe2483fb7448 100644 --- a/tests/warn/i17266.check +++ b/tests/warn/i17266.check @@ -1,7 +1,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:4:2 --------------------------------------------------------- 4 | synchronized { // warn | ^^^^^^^^^^^^ - | Suspicious top-level unqualified call to synchronized + | Universal method synchronized does not resolve to the enclosing class |--------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -12,7 +12,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:17:2 -------------------------------------------------------- 17 | synchronized { // warn | ^^^^^^^^^^^^ - | Suspicious top-level unqualified call to synchronized + | Universal method synchronized does not resolve to the enclosing class |-------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -33,7 +33,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:108:2 ------------------------------------------------------- 108 | wait() // warn | ^^^^ - | Suspicious top-level unqualified call to wait + | Universal method wait does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -44,7 +44,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:115:2 ------------------------------------------------------- 115 | wait() // warn | ^^^^ - | Suspicious top-level unqualified call to wait + | Universal method wait does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -55,7 +55,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:121:2 ------------------------------------------------------- 121 | wait(10) // warn | ^^^^ - | Suspicious top-level unqualified call to wait + | Universal method wait does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -66,7 +66,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:128:2 ------------------------------------------------------- 128 | wait(10) // warn | ^^^^ - | Suspicious top-level unqualified call to wait + | Universal method wait does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -77,7 +77,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:134:2 ------------------------------------------------------- 134 | hashCode() // warn | ^^^^^^^^ - | Suspicious top-level unqualified call to hashCode + | Universal method hashCode does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -88,7 +88,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:141:2 ------------------------------------------------------- 141 | hashCode() // warn | ^^^^^^^^ - | Suspicious top-level unqualified call to hashCode + | Universal method hashCode does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -99,7 +99,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17266.scala:148:2 ------------------------------------------------------- 148 | synchronized { // warn | ^^^^^^^^^^^^ - | Suspicious top-level unqualified call to synchronized + | Universal method synchronized does not resolve to the enclosing class |------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/warn/i17493.check b/tests/warn/i17493.check index 8a4c102980fe..a86ef09d9be9 100644 --- a/tests/warn/i17493.check +++ b/tests/warn/i17493.check @@ -1,7 +1,7 @@ -- [E181] Potential Issue Warning: tests/warn/i17493.scala:4:10 -------------------------------------------------------- 4 | def g = synchronized { println("hello, world") } // warn | ^^^^^^^^^^^^ - | Suspicious top-level unqualified call to synchronized + | Universal method synchronized does not resolve to the enclosing class |--------------------------------------------------------------------------------------------------------------------- | Explanation (enabled by `-explain`) |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/warn/i20651.scala b/tests/warn/i20651.scala new file mode 100644 index 000000000000..5e3c294803d6 --- /dev/null +++ b/tests/warn/i20651.scala @@ -0,0 +1,20 @@ +package example + +class B(val x: String) + +class C: + def wasBad = new B(getClass.getName){}.x // nowarn ever C.this.getClass + def neverBad = new B(getClass.getName).x // nowarn ever + +def alwaysBad = new B(getClass.getName).x // warn Predef.getClass not `package`.getClass + +object A: + def main(args: Array[String]): Unit = + println(new B(getClass.getName){}.x) // nowarn was warn bc A is not $anon + println(new B(getClass.getName).x) // nowarn A.getClass + +trait T(val x: String) + +object U: + def main(args: Array[String]): Unit = + println(new T(getClass.getName){}.x) // nowarn