scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

`-Wunused:import` gets confused on import both locally and globally in file

Open amumurst opened this issue 2 years ago • 4 comments
trafficstars

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

amumurst avatar May 31 '23 10:05 amumurst

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

Daenyth avatar Jun 01 '23 18:06 Daenyth

It's just a bug in the warning. Reproducing all the import behaviors is tricky.

som-snytt avatar Jun 01 '23 19:06 som-snytt

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

PaulCoral avatar Jun 09 '23 23:06 PaulCoral

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.

odersky avatar Aug 23 '23 14:08 odersky