Skip to content

Macro-generated match expression generates a false exhaustivity warning #16784

Open
@arainko

Description

@arainko

Compiler version

3.2.1, 3.2.2. 3.3.0-RC2, 3.3.1-RC1-bin-20230127-c0a7d12-NIGHTLY

Minimized code

// file: GeneratedMatchRepro.scala
import scala.quoted.*

object GeneratedMatchRepro {
  inline def generateMatch(tuple: (Option[Int], String)): Option[Int] = ${ generateMatchMacro('tuple) }

  def generateMatchMacro(expr: Expr[(Option[Int], String)])(using Quotes): Expr[Option[Int]] = {
    import quotes.reflect.*
    val optTpe = TypeRepr.of[Option[Int]]
    val strTpe = TypeRepr.of[String]

    val extractor = Select.unique('{ Tuple2 }.asTerm, "unapply").appliedToTypes(optTpe :: strTpe :: Nil)

    val optBind = Symbol.newBind(Symbol.spliceOwner, "opt", Flags.Local, optTpe)
    val strBind = Symbol.newBind(Symbol.spliceOwner, "str", Flags.Local, strTpe)

    val unapply = Unapply(extractor, Nil, Bind(optBind, Wildcard()) :: Bind(strBind, Wildcard()) :: Nil)

    Match(expr.asTerm, CaseDef(unapply, None, Ref(optBind)) :: Nil).asExprOf[Option[Int]]
  }
}
//file: usage.scala

object usage {
  val works1 = GeneratedMatchRepro.generateMatch(Some(1) -> "str")
  val works2 = GeneratedMatchRepro.generateMatch(None -> "str")

  /*warning:
  match may not be exhaustive.

  It would fail on pattern case: (_, _)
   */
  val warns = GeneratedMatchRepro.generateMatch(Option(1) -> "str")

}

Output

match may not be exhaustive.

It would fail on pattern case: (_, _)

Expectation

No exhaustivity warning.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions