overlap permits an instance to overlap other explicitly marked instances. Put the attribute immediately before define-instance:

(define-class (Label :a)
  (label (:a -> String)))

(overlap)
(define-instance (Label :a)
  (define (label _) "value"))

(overlap)
(define-instance (Label Integer)
  (define (label _) "integer"))

(label True)                ; "value"
(label (the Integer 42))    ; "integer"

Every distinct instance participating in an overlap must have the attribute. It takes no arguments and does not assign priority.

Selection

Selection compares only instance heads. A head is more specific if it can be obtained by substituting types into another head, but not conversely. Definition order has no effect. The unique most-specific matching head wins; its context must then be satisfied. An unsatisfied context is an error, not a reason to try another instance.

Sometimes two matching heads are incomparable: neither is more specific than the other. These definitions can coexist, but a use matching both is ambiguous unless another marked instance resolves their intersection. See the examples below.

The attribute does not relax functional-dependency consistency, kind checking, or the requirements on method definitions. Equivalent heads remain instance redefinitions under the usual redefinition rules.

Polymorphic functions

Using the Label instances above, a function that calls label must use the appropriate instance for each argument type:

(declare describe (Label :a => :a -> String))
(define (describe x) (label x))

(describe True)             ; "value"
(describe (the Integer 42)) ; "integer"

When compiling the body of describe, the compiler knows only that x has type :a. Choosing the general Label :a instance at that point would make both calls return "value", ignoring the Label Integer instance. The Label :a => constraint keeps that choice with the caller: the compiler passes the selected label implementation to describe in an implicit dictionary argument. The call to label inside describe uses that dictionary.

If you omit the entire declare form, the compiler infers (Label :a => :a -> String) from the body. If you instead explicitly declare (declare describe (:a -> String)), the definition is rejected because the declaration omits the required Label :a constraint.

This requirement also holds when only the general marked instance has been defined: a more-specific instance may be added in another compilation unit. Constraints such as Label (List :a) are retained too, since the element type is still unknown and could affect instance selection.

Efficiency

Instance selection happens during compilation. Calling an overloaded method does not search an instance table at runtime. A polymorphic function instead receives dictionaries containing the methods for its retained constraints. Retaining a constraint can therefore add dictionary arguments and indirect method calls when the dictionaries are unknown to the optimizer.

The compiler preserves passed dictionaries and superclass fields because the chosen methods affect program behavior. Type-based specialize replacements are skipped when they would discard constraints involving marked instances or their subclasses. This restriction also applies to unmarked instances of a class that has marked instances. Inlining known dictionary methods remains available, so concrete calls can still become direct calls or inline code.

Separate-compilation validation adds work when compiling and loading units, and when adding or redefining instances. It does not add a validation check to each method call.

Separate compilation

Compiled units record the instance choices used during checking and code generation. Loading a unit validates those choices against the current instance environment before installing its definitions. Adding or redefining instances also validates previously recorded choices. A new instance that would change a compiled choice causes an error in either load order.

For example, after compiling a concrete call to the general Label :a instance at Integer, adding Label Integer requires rebuilding the affected code. A generic describe that retains its Label :a dictionary parameter can accept the new instance without recompilation.

To rebuild after an incompatible extension, use a fresh Lisp/compiler environment, load the complete instance set, and then recompile its clients. Validation is conservative and may retain assumptions from compiler constraint solving as well as emitted calls. There is no operation to unload compiled assumptions selectively or silently retarget already compiled calls. The checks apply to both Coalton source files and coalton-toplevel/coalton forms compiled into Lisp FASLs. Use a clean rebuild when updating the compiler: every participating compiled unit must carry its instance assumptions.

Examples

Resolving an intersection

These first two instances describe pairs with an integer in either position. The third specifies the behavior when both positions are integers:

(define-class (PairLabel :a :b)
  (pair-label (:a * :b -> String)))

(overlap)
(define-instance (PairLabel :a Integer)
  (define (pair-label _ _) "integer on the right"))

(overlap)
(define-instance (PairLabel Integer :b)
  (define (pair-label _ _) "integer on the left"))

(overlap)
(define-instance (PairLabel Integer Integer)
  (define (pair-label _ _) "two integers"))

(pair-label True (the Integer 1))           ; "integer on the right"
(pair-label (the Integer 1) True)           ; "integer on the left"
(pair-label (the Integer 1) (the Integer 2)) ; "two integers"

Without the third instance, the last call is ambiguous. Reordering the first two definitions does not resolve it.

Generic library conversions

The standard library uses overlapping instances to provide identity conversions alongside generic collection conversions:

(the (Tuple Integer String) (into (Tuple (the Integer 42) "answer")))
; (Tuple 42 "answer")
(the (Seq Integer) (into (Some (the Integer 42))))

The last expression builds a one-element sequence through the generic Foldable conversion. Identity conversion of a Seq is handled by an explicit intersection instance and returns the existing sequence.

A polymorphic wrapper retains the conversion constraint:

(declare to-seq
  (Into (:f :a) (Seq :a) => :f :a -> Seq :a))
(define (to-seq xs) (into xs))

(to-seq (Some (the Integer 42)))
(to-seq (the (List Integer) (make-list 1 2)))

The wrapper works with user-defined foldable collections as well. Its callers select the conversion, so a later specialization is respected. Declaring only Foldable :f and RuntimeRepr :a would not suffice: those are the context of one candidate instance, and another instance may be selected. Likewise, a polymorphic identity conversion needs Into :a :a; ordinary identity functions can simply return their argument.