To summarize, this is what i'm proposing,
using the same notation as Alan, we have two syntax
IDENTIFIER(BINDINGS), the unqualified pattern, and Qualifier.IDENTIFIER(BINDINGS), the qualified pattern.

Your previous mails seemed to focus on the declaration site, but now I think you're talking about how we connect the use site to a declaration.  That's an area which the document didn't fully cover, so good, let's talk about that.

Positing that there are three "kinds" of patterns -- deconstruction, static, and instance -- we need to map the use-site description of a pattern to a selected pattern declaration, not unlike overload selection.  The doc didn't provide rules for that, but its a fair question.  Let's do some examples.

    X x = ...

    switch (x) {
        case Foo(var x):    // probably a deconstruction pattern
        case foo(var x):     // probably an instance pattern in X *
        case X.foo(var x):  // either an instance or static pattern on X
    }

Obviously, we can't take capitalization into effect, so we'll need some priority order for disambiguation.  (If we allow dispatch to local patterns, or static import of patterns, these will fall into the second bucket too.)  And in all cases, we will have to be prepared to do some overload selection on patterns, since there might be multiple with the same name.

If this is what you are proposing, we are already on the same page (modulo patterns that have explicit input arguments -- some syntax is needed for that at the use site, but I've deliberately not gone there yet, because we're still nailing down the model conceptually.)

For the qualified pattern, Qualifier.IDENTIFIER(BINDINGS) references
- either an instance method inside the class Qualifier, with 'this' being the value switched upon - or a static method inside the class Qualifier, the first parameter containing the value switched upon

If by "instance method" or "static method", you mean "instance pattern" or "static pattern", then you've got this exactly right.

For the unqualified pattern, IDENTIFIER(BINDINGS), it is equivalent to
- AnotherType(BINDINGS) if the identifier is the type AnotherType (it's the deconstruction pattern) - either Type.IDENTIFIER(BINDINGS) and the rules above applied (it's the inference rule of Tagir) - or AnotherType.IDENTIFIER(BINDINGS) if there is an import static AnotherType.IDENTIFIER

Right, this is the universe of choices, we may want to prune the list if we decide that (say) static import of patterns isn't helpful.

So I think you have correctly intuited the mapping from use-site [Qualifier.]PatternName(BINDINGS) that I had in mind.

Now, a few words about overload selection.  We have to declare what it means for a pattern to be applicable to a "pattern invocation". This includes:

 - compatibility of the target
 - compatibility of the input arguments
 - compatibility of the bindings

For the target, this was outlined in the "Pattern Matching - Semantics" document.  For the input arguments, this will be lifted straight from overload selection.  For the bindings, these must agree in arity (unless it's a varargs pattern), and the type at the use site must be compatible with the declared type.  (Though most of the time, the type at the use site will be `var`, so I expect in practice, we'll mostly see overloading on arity.)  I suspect further that we'll borrow similar treatment of varargs from overload selection (prefer non-varargs to varargs).


Reply via email to