scala/scala3

False positive unused import involving type alias and extractor

Closed this issue · 3 comments

Compiler version

3.6.4 (and also the current 3.7 nightly)

Minimized code

//> using scala 3.nightly
//> using option -Wunused:imports

object tpd:
  type Block = Trees.Block

object Trees:
  case class Block(x: Int)

trait Bug:
  import tpd.Block
  def foo: Unit =
    (??? : Any) match
      case Block(_) =>

Output

[warn] ./S.scala:11:14
[warn] unused import
[warn]   import tpd.Block
[warn]              ^^^^^

Expectation

The import is used. The code does not compile without it. The type alias must be confusing the compiler.

The tree is

          CaseDef(
            Typed(
              UnApply(Select(Ident(Block), unapply), List(), List(Ident(_))),
              TypeTree()),

for

case Trees.Block(_):Trees.Block =>

This compiles only by importing the alias:

object tpd:
  type Block = Trees.Block

object Trees:
  abstract case class Block(x: Int)
  private object Block
  val block = new Block(42) {}

@main def test = println:
  import tpd.Block
  //import Trees.Block
  (Trees.block: Any) match
  case Block(_) =>

That is clearly wrong.

Normally, the reference to Block, resolved by an import, becomes prefix.Block; but in the example, typechecking the pattern has snuck in the term reference.

The Block in the UnApply is indeed the private companion Trees.Block:

ID(Block) or TermRef(ThisType(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),module class Trees$)),object Block) at tests/warn/i22787.scala:<293..293>

Apparently, my previous comment intended to ask, What is a constructor pattern? If it compiles to unapply, is access to the companion module required? Probably, the question is moot because it is about the internal compiler fiction.