Skip to content

Commit e158a9f

Browse files
committed
Add better support for unused renamed import
1 parent d1f9441 commit e158a9f

File tree

2 files changed

+22
-15
lines changed

2 files changed

+22
-15
lines changed

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

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import dotty.tools.dotc.core.Types.Type
2121
import dotty.tools.dotc.core.Types.AnnotatedType
2222
import dotty.tools.dotc.core.Flags.flagsString
2323
import dotty.tools.dotc.core.Flags
24+
import dotty.tools.dotc.core.Names.Name
2425

2526

2627

@@ -71,10 +72,10 @@ class CheckUnused extends Phase:
7172
unusedDataApply(_.registerImport(imp))
7273
traverseChildren(tree)(using newCtx)
7374
case ident: Ident =>
74-
unusedDataApply(_.registerUsed(ident.symbol))
75+
unusedDataApply(_.registerUsed(ident.symbol, Some(ident.name)))
7576
traverseChildren(tree)(using newCtx)
7677
case sel: Select =>
77-
unusedDataApply(_.registerUsed(sel.symbol))
78+
unusedDataApply(_.registerUsed(sel.symbol, Some(sel.name)))
7879
traverseChildren(tree)(using newCtx)
7980
case _: (tpd.Block | tpd.Template | tpd.PackageDef) =>
8081
unusedDataApply { ud =>
@@ -99,7 +100,7 @@ class CheckUnused extends Phase:
99100

100101
private def typeTraverser(dt: (UnusedData => Any) => Unit)(using Context) = new TypeTraverser:
101102
override def traverse(tp: Type): Unit = tp match
102-
case AnnotatedType(_, annot) => dt(_.registerUsed(annot.symbol))
103+
case AnnotatedType(_, annot) => dt(_.registerUsed(annot.symbol, None))
103104
case _ => traverseChildren(tp)
104105

105106
private def reportUnused(res: UnusedData.UnusedResult)(using Context): Unit =
@@ -156,7 +157,7 @@ object CheckUnused:
156157
*
157158
* See the `isAccessibleAsIdent` extension method below in the file
158159
*/
159-
private val usedInScope = MutStack(MutSet[(Symbol,Boolean)]())
160+
private val usedInScope = MutStack(MutSet[(Symbol,Boolean, Option[Name])]())
160161
/* unused import collected during traversal */
161162
private val unusedImport = MutSet[ImportSelector]()
162163

@@ -195,17 +196,15 @@ object CheckUnused:
195196
registerUsed(annotSym)
196197

197198
/** Register a found (used) symbol */
198-
def registerUsed(sym: Symbol)(using Context): Unit =
199+
def registerUsed(sym: Symbol, name: Option[Name])(using Context): Unit =
199200
if !isConstructorOfSynth(sym) then
200-
usedInScope.top += sym -> sym.isAccessibleAsIdent
201-
usedDef += sym
201+
usedInScope.top += ((sym, sym.isAccessibleAsIdent, name))
202202
if sym.isConstructor && sym.exists then
203-
registerUsed(sym.owner) // constructor are "implicitly" imported with the class
203+
registerUsed(sym.owner, None) // constructor are "implicitly" imported with the class
204204

205205
/** Register a list of found (used) symbols */
206206
def registerUsed(syms: Seq[Symbol])(using Context): Unit =
207-
usedInScope.top ++= syms.filterNot(isConstructorOfSynth).map(s => s -> s.isAccessibleAsIdent)
208-
usedDef ++= syms
207+
usedInScope.top ++= syms.filterNot(isConstructorOfSynth).map(s => (s, s.isAccessibleAsIdent, None))
209208

210209
/** Register an import */
211210
def registerImport(imp: tpd.Import)(using Context): Unit =
@@ -248,10 +247,10 @@ object CheckUnused:
248247
// used imports in this scope
249248
val imports = impInScope.pop().toSet
250249
val kept = used.filter { t =>
251-
val (sym, isAccessible) = t
250+
val (sym, isAccessible, optName) = t
252251
// keep the symbol for outer scope, if it matches **no** import
253252
!imports.exists { imp =>
254-
sym.isInImport(imp, isAccessible) match
253+
sym.isInImport(imp, isAccessible, optName) match
255254
case None => false
256255
case Some(sel) =>
257256
unusedImport -= sel
@@ -368,10 +367,10 @@ object CheckUnused:
368367
}
369368

370369
/** Given an import and accessibility, return an option of selector that match import<->symbol */
371-
def isInImport(imp: tpd.Import, isAccessible: Boolean)(using Context): Option[ImportSelector] =
370+
def isInImport(imp: tpd.Import, isAccessible: Boolean, symName: Option[Name])(using Context): Option[ImportSelector] =
372371
val tpd.Import(qual, sels) = imp
373372
val qualHasSymbol = qual.tpe.member(sym.name).alternatives.map(_.symbol).contains(sym)
374-
def selector = sels.find(sel => sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name)
373+
def selector = sels.find(sel => (sel.name.toTermName == sym.name || sel.name.toTypeName == sym.name) && symName.map(n => n.toTermName == sel.rename).getOrElse(true))
375374
def wildcard = sels.find(sel => sel.isWildcard && ((sym.is(Given) == sel.isGiven) || sym.is(Implicit)))
376375
if qualHasSymbol && !isAccessible && sym.exists then
377376
selector.orElse(wildcard) // selector with name or wildcard (or given)

tests/neg-custom-args/fatal-warnings/i15503a.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,12 @@ package testOnOverloadedMethodsImports:
236236
package f:
237237
import b.D.foo // OK
238238
def bar = foo((??? : a.A))
239-
def baz = foo((??? : a.B))
239+
def baz = foo((??? : a.B))
240+
241+
//-------------------------------------
242+
package foo.testing.rename.imports:
243+
import collection.mutable.{Set => MutSet1} // OK
244+
import collection.mutable.{Set => MutSet2} // OK
245+
import collection.mutable.{Set => MutSet3} // error
246+
type A[X] = MutSet1[X]
247+
val a = MutSet2(1)

0 commit comments

Comments
 (0)