scala3
scala3 copied to clipboard
`-Wunused:import` gets confused on import both locally and globally in file
Ran into this when migrating workplace code to 3.3.0. Tried to minimize the code as much as possible, might be more available. When importing something from an object in the local scope and in global, unused:import gets confused about which one is actually needed.
Minimized code
//> using scala 3.3.0
//> using option -Wunused:imports
object MyImplicits:
extension (a: Int) def print: Unit = println(s"Hello, I am $a")
import MyImplicits.print //Global import of extension
object Foo:
def printInt(a: Int): Unit = a.print
import MyImplicits._ //Local import of extension
Foo.printInt(1)
Output
scala-cli .
[warn] ./main.sc:7:20
[warn] unused import
[warn] import MyImplicits.print
[warn] ^^^^^
Hello, I am 1
If I follow the "instructions" and remove the import on line 7..
//import MyImplicits.print
object Foo:
def printInt(a: Int): Unit = a.print
import MyImplicits._
gives
scala-cli .
Compiling project (Scala 3.3.0, JVM)
[error] ./main.sc:8:32
[error] value print is not a member of Int, but could be made available as an extension method.
[error]
[error] The following import might fix the problem:
[error]
[error] import main$_.this.MyImplicits.print
[error]
[error] def printInt(a: Int): Unit = a.print
[error] ^^^^^^^
Though removing the other one
import MyImplicits.print
object Foo:
def printInt(a: Int): Unit = a.print
// import MyImplicits._
Removes the warning correctly
scala-cli .
Compiling project (Scala 3.3.0, JVM)
Compiled project (Scala 3.3.0, JVM)
Hello, I am 1
Expectation
The warning refers to the import that actually can be safely removed on line 10, not 7
scala-cli .
[warn] ./main.sc:10:22
[warn] unused import
[warn] import MyImplicits._
[warn] ^^^^^
Hello, I am 1
What happens if print is a method on the object, called with print(a), instead of an extension? I wonder if this is due to the change in how givens are imported vs scala2
It's just a bug in the warning. Reproducing all the import behaviors is tricky.
Seems like it is only related to the order of the import, which is not accounted in the linting algorithm. Here's a minimized example :
Compiles :
import scala.util.Try // unused
def foo =
val trying = Try(1)
import scala.util.Try
Does NOT compile:
//import scala.util.Try // unused
def foo =
val trying = Try(1) // Not found: Try
import scala.util.Try
I think this one should be solvable by being more precise which imports are in scope. Imports following a definition are never in scope for that definition.