csharplang/meetings/2019/LDM-2019-11-18.md
2019-12-16 16:24:22 -08:00

3.1 KiB

C# LDM for Nov. 18th, 2019

Agenda

  1. More patterns

Discussion

More patterns

Parenthesized patterns:

  • What about ambiguity with a potential 1-tuple pattern?

    • There was a previous ambiguity here with a parenthesized constant expression, so matching a 1-tuple pattern requires resolving ambiguity, for example by adding tuple names: x is (Item1: var tupleVal)

Relational patterns:

We don't love the syntax. The problem is really that we're using a binary operator in a unary context. On the other hand, it's useful in that it's easy to adjust for closed or open bounds by adjusting the inclusiveness of the operator.

The other shaky part of the syntax is support for user-defined operators. One of the fundamental parts of pattern matching is that the semantics are well-understood, meaning that the switch expression expects certain things must be true, like that checks must return the same value for the same inputs and can be called any number of times. We have a few patterns that execute user-defined code, but it seems more likely that they're usually safe (property getters and Deconstruct).

For == and != specifically, they seem redundant and likely to cause confusion when there is a user-defined operator that is not supported. Consensus is to remove support in relational patterns.

The other confusing part is conversion, where the input type does not statically contain a built-in the binary operator. For instance,

object o = (short)1;
_ = o switch
{
    < 3 => 0, // This would be false, since `o` is a short, not an int, and the
              // unconverted '3' is an `int`
};

This is already how constant patterns work, so there may be some confusion here already, but we're worried about broadening the problem by adding the not pattern in combination with the relational operators. For example, if you match not < 3, this would evaluate to true, but not because the value is not less than three, but because it is not an int. This would mean that >= 3 and not < 3 would be different, since the type check can play into the check.

However, we don't have any better approaches, and the hope is that this will be a relatively rare occurrence. If the input pattern has a statically known built-in operator this would not be a concern.

The proposal states that the input type of the expression must contain a conversion that is not a boxing conversion. However, we do support constant pattern checks for unconstrained type parameters, so we need to change the proposal to allow unconstrained type parameters as well.

Pattern combinators

The proposal contains three breaking changes:

- `not` is considered a type in C# 8 and a pattern in C# 9.

- `and` and `or` are allowed as variable names in C# 8, but are pattern combinators in C# 9

An important question is whether these are allowed and how they are breaking. Changing behavior is probably a bridge too far. We would consider providing an error in the old scenarios and forcing disambiguation.

We'll need more discussion on the breaking changes and how we can mitigate them.