Skip to content

Commit d7edb73

Browse files
authoredMar 18, 2025
Merge pull request #182 from scala/backport-lts-3.3-22314
Backport "Append instead of prepending import selectors for the current scope when collecting them in CheckUnused" to 3.3 LTS
2 parents 51ad6e3 + e3996a3 commit d7edb73

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed
 

‎compiler/src/dotty/tools/dotc/transform/CheckUnused.scala

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dotty.tools.dotc.transform
22

33
import scala.annotation.tailrec
4+
import scala.collection.mutable
45

56
import dotty.tools.uncheckedNN
67
import dotty.tools.dotc.ast.tpd
@@ -24,7 +25,7 @@ import dotty.tools.dotc.core.Mode
2425
import dotty.tools.dotc.core.Types.{AnnotatedType, ConstantType, NoType, TermRef, Type, TypeTraverser}
2526
import dotty.tools.dotc.core.Flags.flagsString
2627
import dotty.tools.dotc.core.Flags
27-
import dotty.tools.dotc.core.Names.Name
28+
import dotty.tools.dotc.core.Names.{Name, TermName}
2829
import dotty.tools.dotc.core.NameOps.isReplWrapperName
2930
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
3031
import dotty.tools.dotc.core.Annotations
@@ -211,7 +212,7 @@ class CheckUnused private (phaseMode: CheckUnused.PhaseMode, suffix: String, _ke
211212
/**
212213
* This traverse is the **main** component of this phase
213214
*
214-
* It traverse the tree the tree and gather the data in the
215+
* It traverses the tree and gathers the data in the
215216
* corresponding context property
216217
*/
217218
private def traverser = new TreeTraverser:
@@ -456,14 +457,21 @@ object CheckUnused:
456457
val (wildcardSels, nonWildcardSels) = imp.selectors.partition(_.isWildcard)
457458
nonWildcardSels ::: wildcardSels
458459

460+
val excludedMembers: mutable.Set[TermName] = mutable.Set.empty
461+
459462
val newDataInScope =
460463
for sel <- reorderdSelectors yield
461464
val data = new ImportSelectorData(qualTpe, sel)
462465
if shouldSelectorBeReported(imp, sel) || isImportExclusion(sel) || isImportIgnored(imp, sel) then
463466
// Immediately mark the selector as used
464467
data.markUsed()
468+
if isImportExclusion(sel) then
469+
excludedMembers += sel.name
470+
if sel.isWildcard && excludedMembers.nonEmpty then
471+
// mark excluded members for the wildcard import
472+
data.markExcluded(excludedMembers.toSet)
465473
data
466-
impInScope.top.prependAll(newDataInScope)
474+
impInScope.top.appendAll(newDataInScope)
467475
end registerImport
468476

469477
/** Register (or not) some `val` or `def` according to the context, scope and flags */
@@ -703,7 +711,7 @@ object CheckUnused:
703711

704712
/** Given an import and accessibility, return selector that matches import<->symbol */
705713
private def isInImport(selData: ImportSelectorData, altName: Option[Name], isDerived: Boolean)(using Context): Boolean =
706-
assert(sym.exists)
714+
assert(sym.exists, s"Symbol $sym does not exist")
707715

708716
val selector = selData.selector
709717

@@ -719,7 +727,10 @@ object CheckUnused:
719727
selData.allSymbolsForNamed.contains(sym)
720728
else
721729
// Wildcard
722-
if !selData.qualTpe.member(sym.name).hasAltWith(_.symbol == sym) then
730+
if selData.excludedMembers.contains(altName.getOrElse(sym.name).toTermName) then
731+
// Wildcard with exclusions that match the symbol
732+
false
733+
else if !selData.qualTpe.member(sym.name).hasAltWith(_.symbol == sym) then
723734
// The qualifier does not have the target symbol as a member
724735
false
725736
else
@@ -832,11 +843,14 @@ object CheckUnused:
832843

833844
final class ImportSelectorData(val qualTpe: Type, val selector: ImportSelector):
834845
private var myUsed: Boolean = false
846+
var excludedMembers: Set[TermName] = Set.empty
835847

836848
def markUsed(): Unit = myUsed = true
837849

838850
def isUsed: Boolean = myUsed
839851

852+
def markExcluded(excluded: Set[TermName]): Unit = excludedMembers ++= excluded
853+
840854
private var myAllSymbols: Set[Symbol] | Null = null
841855

842856
def allSymbolsForNamed(using Context): Set[Symbol] =

‎tests/warn/i21420.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//> using options -Wunused:imports
2+
3+
object decisions4s{
4+
trait HKD
5+
trait DecisionTable
6+
}
7+
8+
object DiagnosticsExample {
9+
import decisions4s.HKD
10+
val _ = new HKD {}
11+
import decisions4s.*
12+
val _ = new DecisionTable {}
13+
}

0 commit comments

Comments
 (0)
Failed to load comments.