Skip to content

Commit 05354ba

Browse files
authored
Fix #18383: Never consider top-level imports as unused in the repl. (#20310)
2 parents cb554eb + 509c235 commit 05354ba

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

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

+9-6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import dotty.tools.dotc.core.Types.{AnnotatedType, ConstantType, NoType, TermRef
2020
import dotty.tools.dotc.core.Flags.flagsString
2121
import dotty.tools.dotc.core.Flags
2222
import dotty.tools.dotc.core.Names.Name
23+
import dotty.tools.dotc.core.NameOps.isReplWrapperName
2324
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
2425
import dotty.tools.dotc.core.Annotations
2526
import dotty.tools.dotc.core.Definitions
@@ -423,9 +424,11 @@ object CheckUnused:
423424
def registerImport(imp: tpd.Import)(using Context): Unit =
424425
if !tpd.languageImport(imp.expr).nonEmpty && !imp.isGeneratedByEnum && !isTransparentAndInline(imp) then
425426
impInScope.top += imp
426-
unusedImport ++= imp.selectors.filter { s =>
427-
!shouldSelectorBeReported(imp, s) && !isImportExclusion(s) && !isImportIgnored(imp, s)
428-
}
427+
if currScopeType.top != ScopeType.ReplWrapper then // #18383 Do not report top-level import's in the repl as unused
428+
unusedImport ++= imp.selectors.filter { s =>
429+
!shouldSelectorBeReported(imp, s) && !isImportExclusion(s) && !isImportIgnored(imp, s)
430+
}
431+
end registerImport
429432

430433
/** Register (or not) some `val` or `def` according to the context, scope and flags */
431434
def registerDef(memDef: tpd.MemberDef)(using Context): Unit =
@@ -794,12 +797,13 @@ object CheckUnused:
794797
enum ScopeType:
795798
case Local
796799
case Template
800+
case ReplWrapper
797801
case Other
798802

799803
object ScopeType:
800804
/** return the scope corresponding to the enclosing scope of the given tree */
801-
def fromTree(tree: tpd.Tree): ScopeType = tree match
802-
case _:tpd.Template => Template
805+
def fromTree(tree: tpd.Tree)(using Context): ScopeType = tree match
806+
case tree: tpd.Template => if tree.symbol.name.isReplWrapperName then ReplWrapper else Template
803807
case _:tpd.Block => Local
804808
case _ => Other
805809

@@ -810,4 +814,3 @@ object CheckUnused:
810814
val Empty = UnusedResult(Set.empty)
811815

812816
end CheckUnused
813-

compiler/test-resources/repl/i18383

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
scala>:settings -Wunused:all
2+
3+
scala> import scala.collection.*
4+
5+
scala> class Foo { import scala.util.*; println("foo") }
6+
1 warning found
7+
-- Warning: --------------------------------------------------------------------
8+
1 | class Foo { import scala.util.*; println("foo") }
9+
| ^
10+
| unused import
11+
// defined class Foo
12+
13+
scala> { import scala.util.*; "foo" }
14+
val res0: String = foo

compiler/test/dotty/tools/repl/ReplCompilerTests.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ class ReplCompilerTests extends ReplTest:
2020
assertEquals("def foo: 1", storedOutput().trim)
2121
}
2222

23+
@Test def i18383NoWarnOnUnusedImport: Unit = {
24+
initially {
25+
run("import scala.collection.*")
26+
} andThen {
27+
println(lines().mkString("* ", "\n * ", ""))
28+
}
29+
}
30+
2331
@Test def compileTwo =
2432
initially {
2533
run("def foo: 1 = 1")
@@ -509,4 +517,3 @@ class ReplHighlightTests extends ReplTest(ReplTest.defaultOptions.filterNot(_.st
509517
case class Tree(left: Tree, right: Tree)
510518
def deepTree(depth: Int): Tree
511519
deepTree(300)""")
512-

0 commit comments

Comments
 (0)