E165: Matchable Warning

This warning occurs when pattern matching is performed on a value whose type doesn't extend Matchable. In future Scala versions, pattern matching will require the scrutinee to be an instance of Matchable.

The Matchable trait marks types that can be safely pattern matched. This restriction helps catch potential issues with pattern matching on abstract types that might be instantiated with types that don't support pattern matching (like opaque types or certain intersection types).

This warning is enabled with -source:future or -source:future-migration


Example

//> using options -source:future

def example[T](x: T) = x match {
  case s: String => s
  case _ => ""
}

Error

-- [E165] Type Warning: example.scala:4:10 -------------------------------------
4 |  case s: String => s
  |          ^^^^^^
  |          pattern selector should be an instance of Matchable,
  |          but it has unmatchable type T instead
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | A value of type T cannot be the selector of a match expression
  | since it is not constrained to be `Matchable`. Matching on unconstrained
  | values is disallowed since it can uncover implementation details that
  | were intended to be hidden and thereby can violate paramtetricity laws
  | for reasoning about programs.
  |
  | The restriction can be overridden by appending `.asMatchable` to
  | the selector value. `asMatchable` needs to be imported from
  | scala.compiletime. Example:
  |
  |     import compiletime.asMatchable
  |     def f[X](x: X) = x.asMatchable match { ... }
   -----------------------------------------------------------------------------

Solution

// Constrain the type parameter to Matchable
def example[T <: Matchable](x: T) = x match {
  case s: String => s
  case _ => ""
}
//> using options -source:future

// Or use a more specific type bound
def example[T <: AnyRef](x: T) = x match {
  case s: String => s
  case _ => ""
}