Skip to content

Irrefutability check does not work for named patterns in extractor patterns #22899

Closed
@SrTobi

Description

@SrTobi

Compiler version

3.7.1-RC1-bin-20250328-d519790-NIGHTLY

Minimized code

case class CaseClass(a: Int)

object ProductMatch_CaseClass {
  def unapply(int: Int): CaseClass = CaseClass(int)
}

object ProductMatch_NamedTuple {
  def unapply(int: Int): (a: Int) = (a = int)
}

object NameBasedMatch_CaseClass {
  def unapply(int: Int): Some[CaseClass] = Some(CaseClass(int))
}

object NameBasedMatch_NamedTuple {
  def unapply(int: Int): Some[(a: Int)] = Some((a = int))
}

object Test {
  val ProductMatch_CaseClass(a = x1) = 1    // pattern's type (x1 : Int) is more specialized than the right hand side expression's type Int
  val ProductMatch_NamedTuple(a = x2) = 2   // pattern binding uses refutable extractor `org.test.ProductMatch_NamedTuple`
  val NameBasedMatch_CaseClass(a = x3) = 3  // pattern's type (x3 : Int) is more specialized than the right hand side expression's type Int
  val NameBasedMatch_NamedTuple(a = x4) = 4 // pattern's type (x4 : Int) is more specialized than the right hand side expression's type Int

  val CaseClass(a = x5) = CaseClass(5)      // pattern's type (x5 : Int) is more specialized than the right hand side expression's type Int
  val (a = x6) = (a = 6)                    // ok
}

Output

/home/tobi/workspace/test-projects/named-tuples/src/main/scala/org/test/Test.scala:24:40
pattern's type (x1 : Int) is more specialized than the right hand side expression's type Int

If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
which may result in a MatchError at runtime.
This patch can be rewritten automatically under -rewrite -source 3.2-migration.
  val ProductMatch_CaseClass(a = x1) = 1

/home/tobi/workspace/test-projects/named-tuples/src/main/scala/org/test/Test.scala:25:30
pattern binding uses refutable extractor `org.test.ProductMatch_NamedTuple`

If this usage is intentional, this can be communicated by adding `: @unchecked` after the expression,
which may result in a MatchError at runtime.
This patch can be rewritten automatically under -rewrite -source 3.2-migration.
  val ProductMatch_NamedTuple(a = x2) = 2

/home/tobi/workspace/test-projects/named-tuples/src/main/scala/org/test/Test.scala:26:42
pattern's type (x3 : Int) is more specialized than the right hand side expression's type Int

If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
which may result in a MatchError at runtime.
This patch can be rewritten automatically under -rewrite -source 3.2-migration.
  val NameBasedMatch_CaseClass(a = x3) = 3

/home/tobi/workspace/test-projects/named-tuples/src/main/scala/org/test/Test.scala:27:43
pattern's type (x4 : Int) is more specialized than the right hand side expression's type Int

If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
which may result in a MatchError at runtime.
This patch can be rewritten automatically under -rewrite -source 3.2-migration.
  val NameBasedMatch_NamedTuple(a = x4) = 4

/home/tobi/workspace/test-projects/named-tuples/src/main/scala/org/test/Test.scala:29:36
pattern's type (x5 : Int) is more specialized than the right hand side expression's type Int

If the narrowing is intentional, this can be communicated by adding `: @unchecked` after the expression,
which may result in a MatchError at runtime.
This patch can be rewritten automatically under -rewrite -source 3.2-migration.
  val CaseClass(a = x5) = CaseClass(5)

Expectation

All of the above cases should be irrefutable and not produce warnings

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions