From 970ac2ded67fcaf73716357944b64aa6d15cc97e Mon Sep 17 00:00:00 2001 From: Paul Coral Date: Wed, 11 Jan 2023 11:52:56 +0100 Subject: [PATCH 1/2] Fix -Wunused:import for "" - Register owner of the constructor instead of the constructor. - This solves the issue where `member(sym.name)` have multiple identical names --- compiler/src/dotty/tools/dotc/transform/CheckUnused.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 5549e5c48d45..6775dd922913 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -27,6 +27,7 @@ import dotty.tools.dotc.core.Definitions import dotty.tools.dotc.core.Types.ConstantType import dotty.tools.dotc.core.NameKinds.WildcardParamName import dotty.tools.dotc.core.Types.TermRef +import dotty.tools.dotc.core.Types.NameFilter @@ -326,9 +327,10 @@ object CheckUnused: */ def registerUsed(sym: Symbol, name: Option[Name])(using Context): Unit = if !isConstructorOfSynth(sym) && !doNotRegister(sym) then - usedInScope.top += ((sym, sym.isAccessibleAsIdent, name)) if sym.isConstructor && sym.exists then registerUsed(sym.owner, None) // constructor are "implicitly" imported with the class + else + usedInScope.top += ((sym, sym.isAccessibleAsIdent, name)) /** Register a symbol that should be ignored */ def addIgnoredUsage(sym: Symbol)(using Context): Unit = From fa1d2bb5a01863ee89063a2732015f03c0ada87b Mon Sep 17 00:00:00 2001 From: Paul Coral Date: Wed, 11 Jan 2023 16:36:36 +0100 Subject: [PATCH 2/2] Fix -Wunused:import enum - Some enum generates an import clause for its cases - Update some test suits --- .../src/dotty/tools/dotc/transform/CheckUnused.scala | 8 +++++++- tests/neg-custom-args/fatal-warnings/i15503a.scala | 7 ++++++- tests/neg-custom-args/fatal-warnings/i15503i.scala | 9 +++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 6775dd922913..29af47ce844e 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -331,6 +331,8 @@ object CheckUnused: registerUsed(sym.owner, None) // constructor are "implicitly" imported with the class else usedInScope.top += ((sym, sym.isAccessibleAsIdent, name)) + usedInScope.top += ((sym.companionModule, sym.isAccessibleAsIdent, name)) + usedInScope.top += ((sym.companionClass, sym.isAccessibleAsIdent, name)) /** Register a symbol that should be ignored */ def addIgnoredUsage(sym: Symbol)(using Context): Unit = @@ -347,7 +349,7 @@ object CheckUnused: /** Register an import */ def registerImport(imp: tpd.Import)(using Context): Unit = - if !tpd.languageImport(imp.expr).nonEmpty then + if !tpd.languageImport(imp.expr).nonEmpty && !imp.isGeneratedByEnum then impInScope.top += imp unusedImport ++= imp.selectors.filter { s => !shouldSelectorBeReported(imp, s) && !isImportExclusion(s) @@ -591,6 +593,10 @@ object CheckUnused: !isSyntheticMainParam(sym) && !sym.shouldNotReportParamOwner + extension (imp: tpd.Import) + /** Enum generate an import for its cases (but outside them), which should be ignored */ + def isGeneratedByEnum(using Context): Boolean = + imp.symbol.exists && imp.symbol.owner.is(Flags.Enum, butNot = Flags.Case) extension (thisName: Name) private def isWildcard: Boolean = diff --git a/tests/neg-custom-args/fatal-warnings/i15503a.scala b/tests/neg-custom-args/fatal-warnings/i15503a.scala index 28482c7addde..c626fd88085e 100644 --- a/tests/neg-custom-args/fatal-warnings/i15503a.scala +++ b/tests/neg-custom-args/fatal-warnings/i15503a.scala @@ -250,4 +250,9 @@ package foo.testing.rename.imports: package foo.testing.imports.precedence: import scala.collection.immutable.{BitSet => _, _} // error import scala.collection.immutable.BitSet // OK - def t = BitSet.empty \ No newline at end of file + def t = BitSet.empty + +package foo.test.enums: + enum A: // OK + case B extends A // OK + case C extends A // OK \ No newline at end of file diff --git a/tests/neg-custom-args/fatal-warnings/i15503i.scala b/tests/neg-custom-args/fatal-warnings/i15503i.scala index cecb79b70a34..60a1ad4741fd 100644 --- a/tests/neg-custom-args/fatal-warnings/i15503i.scala +++ b/tests/neg-custom-args/fatal-warnings/i15503i.scala @@ -65,3 +65,12 @@ package foo.test.scala.annotation: @unused private def c = 3 // OK def other = b + +package foo.test.companionprivate: + class A: + import A.b // OK + def a = b // OK + + object A: + private def b = c // OK + def c = List(1,2,3) // OK \ No newline at end of file