Skip to content

Name-based pattern matching rules #1805

Closed
@odersky

Description

@odersky

This is an attempt to come up with a sane set of rules for name-based pattern matching. To recall: In dotty, name-based is all we have, there is no special treatment of type classes anymore.

The purpose of the rules is, given a pattern P(P1, .., Pn), to produce the expected types PT1,..., PTn against which the argument patterns P1, .., Pn will be matched. Let X be the expected type of the whole pattern match.

  1. If the companion object P contains a member def unapply(x: T): U such that X conforms to T then

    1. If U is a subtype of a product type Product{n}[T1, ... Tn] with arity n then PTi = Ti, for i = 1,..,n.

    2. If U has parameterless (def or val) members isEmpty: Boolean and get: V,
      then:

      1. if there is exactly one argument (P1) then PT1 = V.
      2. if there are zero or more than one arguments, then V must derive from a product type
        Product{n}[V1, ..., Vn] and PTi = Vi, for i = 1,..,n.
    3. If U is of type Boolean and n = 0, OK

    4. Otherwise error.

  2. If the precondition (1) does not hold (i.e. no unapply method with the right argument type), but the companion object P contains a member def unapplySeq(x: T): U where X conforms to T then

    1. If U derives from Seq[V] for some type V, then PTi = V for i = 1,..,n, or PTn = V* if Pn is a repeated parameter.
    2. If U has parameterless (def or val) members isEmpty: Boolean and get: S,
      where S <: Seq[V] for some type V, then PTi = V for i = 1,..,n, or PTn = V* if Pn is a repeated parameter.
    3. Otherwise error.

Note 1: There are some subtleties with overloading which are skimmed over here. See the comment of typer.Applications#trySelectUnapply for a more detailed explanation.

Note 2: A consequence of the rules is that a selector type may match patterns of different arities using the same unapply. One arity could trigger a product based selection (using rule 1.i), the other a get/isEmpty selection (using rule 1.ii). Scala parser combinators actually exercise that functionality. A test case is in pos/Patterns.scala.

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