(This is about pattern alternatives, not union types !)
enum Tree:
  case Wrap(t: Tree)
  case Node(t1: Tree, t2: Tree)
  case Leaf(value: Int)
import Tree.*
def rightmostValue(tree: Tree): Int =
  tree match
    case Wrap(subtree) | Node(_, subtree) => rightmostValue(subtree)
    case Leaf(value) => value
The code above is unambiguous, right ?
We extract a value subtree of type Tree, and recurse on it
But this is not allowed:
Illegal variable subtree in pattern alternative
It is said as much in the Scala 2 spec:
“They may not bind variables other than wildcards.”
https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#pattern-alternatives
My somewhat crude proposal is the following:
Binding identifier id is allowed in pattern alternatives iff all the following conditions are true:
- each alternative 
iextractsidwith typeT_i - effect: 
idhas typeT = T_1 | ... | T_n - if an alternative or one of its sub-patterns is 
id: U_i, thenTmust be=:= U_i - 
idcannot be bound in a “pattern binder”id@Extractor(...) 
The last condition could also be replaced by “if id appears in a pattern binder, then the pattern must be the same in all aternatives”
Examples:
tree match
  case Wrap(subtree) | Leaf(subtree) =>
    // body where subtree has type Tree | Int
tree match
  case Wrap(subtree) | Leaf(subtree: Int) =>
    // error: subtree is bound to type Tree | Int, not Int
tree match
  case Wrap(subtree@Wrap(_)) | Leaf(subtree) =>
    // error: multi-bound variables cannot be part of pattern binders
tree match
  case Wrap(subtree@Wrap(_)) | Node(_, subtree@Wrap(_)) =>
    // Might be okay ?
This has the impact that P1 | P2 is not always equivalent to P2 | P1:
tree match
  case Wrap(t) | t: Tree =>
    // not equivalent to
  case t: Tree | Wrap(t) =>
Questions for you:
- Is this sound ?
 - Does this have good UX ?
 - Would this be useful ?
 - Suggestions ?