Update sum types design

Pull request

Table of contents

Abstract

This proposal updates the design of #157 to reflect subsequent evolution of the language.

Problem

Some aspects of the design of #157 have become inconsistent with the rest of the language, or can be made more precise in light of subsequent language development.

Proposal

  • Make the continuation interface an associated type rather than an interface parameter.
  • For patterns that can be matched using either Match or ==, require both implementations to be well-formed.
  • Use name: Type order instead of Type: name order in alternative declarations.
  • Use current syntax and semantics for generics and class types.
  • Rename Matchable.Match to Match.Op, following the resolution of #1058.

Alternatives considered

Keep the continuation interface as a parameter

Making the continuation interface a parameter of Match could in principle allow a single type to support pattern matching in multiple ways, by implementing Match for multiple continuation interfaces. However, that would require something like overload resolution on interfaces, to choose the implementation of Match(C) on the sum type for which C best matches the continuation constructed by the compiler. No such overloading mechanism is planned, and we don’t have sufficiently compelling use cases to motivate it.

Require the continuation to execute the whole case body

We will probably want to support in-place mutation of alternative parameters (for example so you can call a mutable method on the value stored in an Optional(Foo)), and we might even want to extend that to cases where the underlying parameter isn’t represented as an lvalue of that type, but has to be unpacked by Match.Op. The only way I see to make that work is to have Match.Op unpack the parameter to a local lvalue, pass it to the continuation, and then pack the possibly-mutated value back into the sum object after the continuation returns. That would mean the compiler has to execute the case body inside the continuation, not after Match.Op returns.

However, that’s fairly speculative, and wouldn’t apply to the read-only cases that we currently support, so we need not preemptively constrain the compiler here.