From 71208c3710b2ba2b30b70d8ec07ae3c8ec04458c Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Mon, 28 Aug 2023 18:36:10 +0200 Subject: [PATCH 1/5] Fix false positive in WUnused for renamed path-dependent imports [Cherry-picked 3b3dea383601fce2f21e94515710480b501b4194] --- .../src/dotty/tools/dotc/transform/CheckUnused.scala | 6 ++++-- tests/pos-special/fatal-warnings/i18366.scala | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/pos-special/fatal-warnings/i18366.scala diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index eb3c37622e0d..0ba360fa21a4 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -669,8 +669,10 @@ object CheckUnused: val simpleSelections = qual.tpe.member(sym.name).alternatives val typeSelections = sels.flatMap(n => qual.tpe.member(n.name.toTypeName).alternatives) val termSelections = sels.flatMap(n => qual.tpe.member(n.name.toTermName).alternatives) + val sameTermPath = qual.isTerm && sym.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType val selectionsToDealias = typeSelections ::: termSelections - val qualHasSymbol = simpleSelections.map(_.symbol).contains(sym) || (simpleSelections ::: selectionsToDealias).map(_.symbol).map(dealias).contains(dealiasedSym) + def renamedSelection = if(sameTermPath) then sels.find(sel => sel.imported.name == sym.name) else None + val qualHasSymbol = simpleSelections.map(_.symbol).contains(sym) || (simpleSelections ::: selectionsToDealias).map(_.symbol).map(dealias).contains(dealiasedSym) || renamedSelection.isDefined def selector = sels.find(sel => (sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name) && symName.map(n => n.toTermName == sel.rename).getOrElse(true)) def dealiasedSelector = if(isDerived) sels.flatMap(sel => selectionsToDealias.map(m => (sel, m.symbol))).collect { case (sel, sym) if dealias(sym) == dealiasedSym => sel @@ -680,7 +682,7 @@ object CheckUnused: else None def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given) == sel.isGiven && sel.bound.isEmpty) || sym.is(Implicit))) if qualHasSymbol && (!isAccessible || sym.isRenamedSymbol(symName)) && sym.exists then - selector.orElse(dealiasedSelector).orElse(givenSelector).orElse(wildcard) // selector with name or wildcard (or given) + selector.orElse(dealiasedSelector).orElse(givenSelector).orElse(wildcard).orElse(renamedSelection) // selector with name or wildcard (or given) else None diff --git a/tests/pos-special/fatal-warnings/i18366.scala b/tests/pos-special/fatal-warnings/i18366.scala new file mode 100644 index 000000000000..bd25d607e897 --- /dev/null +++ b/tests/pos-special/fatal-warnings/i18366.scala @@ -0,0 +1,10 @@ +// scalac: -Wunused:all + +trait Builder { + def foo(): Unit +} + +def repro = + val builder: Builder = ??? + import builder.{foo => bar} + bar() \ No newline at end of file From 37ea99994e613b425eee3bd0a5a5135e05a1a8e6 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Tue, 29 Aug 2023 12:29:12 +0200 Subject: [PATCH 2/5] Check if owner of symbol exists [Cherry-picked 21641151411d9ea0a0b829bf11b82644cfb46c16] --- compiler/src/dotty/tools/dotc/transform/CheckUnused.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 0ba360fa21a4..56e7bbcf3b89 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -669,7 +669,7 @@ object CheckUnused: val simpleSelections = qual.tpe.member(sym.name).alternatives val typeSelections = sels.flatMap(n => qual.tpe.member(n.name.toTypeName).alternatives) val termSelections = sels.flatMap(n => qual.tpe.member(n.name.toTermName).alternatives) - val sameTermPath = qual.isTerm && sym.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType + val sameTermPath = qual.isTerm && sym.owner.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType val selectionsToDealias = typeSelections ::: termSelections def renamedSelection = if(sameTermPath) then sels.find(sel => sel.imported.name == sym.name) else None val qualHasSymbol = simpleSelections.map(_.symbol).contains(sym) || (simpleSelections ::: selectionsToDealias).map(_.symbol).map(dealias).contains(dealiasedSym) || renamedSelection.isDefined From b697cfa106682c4cc50b06ef63df942059eebc06 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Tue, 29 Aug 2023 14:11:06 +0200 Subject: [PATCH 3/5] Revert "Check if owner of symbol exists" This reverts commit 21641151411d9ea0a0b829bf11b82644cfb46c16. [Cherry-picked c1f4e5a190e2d674c807c4352af4d8f2cb1825a9] --- compiler/src/dotty/tools/dotc/transform/CheckUnused.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 56e7bbcf3b89..0ba360fa21a4 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -669,7 +669,7 @@ object CheckUnused: val simpleSelections = qual.tpe.member(sym.name).alternatives val typeSelections = sels.flatMap(n => qual.tpe.member(n.name.toTypeName).alternatives) val termSelections = sels.flatMap(n => qual.tpe.member(n.name.toTermName).alternatives) - val sameTermPath = qual.isTerm && sym.owner.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType + val sameTermPath = qual.isTerm && sym.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType val selectionsToDealias = typeSelections ::: termSelections def renamedSelection = if(sameTermPath) then sels.find(sel => sel.imported.name == sym.name) else None val qualHasSymbol = simpleSelections.map(_.symbol).contains(sym) || (simpleSelections ::: selectionsToDealias).map(_.symbol).map(dealias).contains(dealiasedSym) || renamedSelection.isDefined From f2fc101ed743f5d6cc41597eab2e3ef33d7909ee Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Tue, 29 Aug 2023 15:02:39 +0200 Subject: [PATCH 4/5] Replace def with lazy val [Cherry-picked 8bc81ef0a995b74125a1abfd9eb87584e32ddf21] --- compiler/src/dotty/tools/dotc/transform/CheckUnused.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 0ba360fa21a4..4100ada0869f 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -671,7 +671,7 @@ object CheckUnused: val termSelections = sels.flatMap(n => qual.tpe.member(n.name.toTermName).alternatives) val sameTermPath = qual.isTerm && sym.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType val selectionsToDealias = typeSelections ::: termSelections - def renamedSelection = if(sameTermPath) then sels.find(sel => sel.imported.name == sym.name) else None + lazy val renamedSelection = if sameTermPath then sels.find(sel => sel.imported.name == sym.name) else None val qualHasSymbol = simpleSelections.map(_.symbol).contains(sym) || (simpleSelections ::: selectionsToDealias).map(_.symbol).map(dealias).contains(dealiasedSym) || renamedSelection.isDefined def selector = sels.find(sel => (sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name) && symName.map(n => n.toTermName == sel.rename).getOrElse(true)) def dealiasedSelector = if(isDerived) sels.flatMap(sel => selectionsToDealias.map(m => (sel, m.symbol))).collect { From 71fd92df9bc1f78c4cd004d99b54253478221b5e Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Thu, 31 Aug 2023 11:56:04 +0200 Subject: [PATCH 5/5] Replace lazy val with val [Cherry-picked 6c6070a45fc7ec393825c07a71a194cf65c5955c] --- compiler/src/dotty/tools/dotc/transform/CheckUnused.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 4100ada0869f..a3dbbfb202e7 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -671,7 +671,7 @@ object CheckUnused: val termSelections = sels.flatMap(n => qual.tpe.member(n.name.toTermName).alternatives) val sameTermPath = qual.isTerm && sym.exists && sym.owner.isType && qual.tpe.typeSymbol == sym.owner.asType val selectionsToDealias = typeSelections ::: termSelections - lazy val renamedSelection = if sameTermPath then sels.find(sel => sel.imported.name == sym.name) else None + val renamedSelection = if sameTermPath then sels.find(sel => sel.imported.name == sym.name) else None val qualHasSymbol = simpleSelections.map(_.symbol).contains(sym) || (simpleSelections ::: selectionsToDealias).map(_.symbol).map(dealias).contains(dealiasedSym) || renamedSelection.isDefined def selector = sels.find(sel => (sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name) && symName.map(n => n.toTermName == sel.rename).getOrElse(true)) def dealiasedSelector = if(isDerived) sels.flatMap(sel => selectionsToDealias.map(m => (sel, m.symbol))).collect {