Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[patterns] Constant context? #2758

Closed
eernstg opened this issue Jan 5, 2023 · 2 comments · Fixed by #2779
Closed

[patterns] Constant context? #2758

eernstg opened this issue Jan 5, 2023 · 2 comments · Fixed by #2779
Labels
patterns Issues related to pattern matching. question Further information is requested

Comments

@eernstg
Copy link
Member

eernstg commented Jan 5, 2023

Thanks to @sgrekhov for bringing up this issue. It would seem convenient and benign if syntactic positions in patterns that require a constant expression could be a constant context (that is: const can be left implicit). For example:

class C {
  final int i;
  const C(this.i);
  bool operator <(other) => other is C ? i < other.i : false;
  bool operator >=(other) => other is C ? i >= other.i : false;
}

String test(C c) {
  return switch (c) {
    < const C(0) => "negative", // We would then be able to omit `const` here ..
    >= const C(0) => "positive", // .. and here.
    const C(1) => "The actual object `const C(1)`", // But not here.
    _ => "Impossible!"
  };
}

This could apply to at least three constructs:

  • The <bitwiseOrExpression> of a <relationalPattern>.
  • The <expression> of a <constantPattern> of the form 'const' '(' <expression> ')'.
  • The <elements> of a collection pattern ('const' '[' <elements>? ']', or 'const' '{' <elements>? '}').

@munificent, @kallentu, @stereotype441, @jakemac53, @lrhn, @leafpetersen, @natebosch, WDYT?

@eernstg eernstg added question Further information is requested patterns Issues related to pattern matching. labels Jan 5, 2023
@lrhn
Copy link
Member

lrhn commented Jan 11, 2023

It's slightly tricky, because there are contexts that look like they must be const, like the const C(1) => here where removing the const would be invalid as a pattern, so surely it must be a constant, but where we can't allow you to remove the const because then another call would be ambiguous (C(x: 1) =>).

Will users be more or less confused if we allow the const to be removed in some places, but not all.
For example: {const C(1): const C(1)} would allow you to remove the former const, but not the latter (because map keys are in parameters that must be provided by the user, and map values are out parameters to be matched by a pattern).

Are users going to be more or less confused by making some positions implicitly const, and others not.
I think we can provide a story (if it's a pattern, you need the const, if it's an input/parameter to an object member, it's always implicitly const.)

That requires us to commit to such parameters always being const, which means we can't do:

  case List(length: var length & >= 2, last: var ultimate, [length - 2]: var penultimate)

where the [length - 2] is a member access using the value of a previously bound variable.
We don't allow that now, but are we sure we never want to?

(I want to generalize object-pattern accessors to not just be getters, so we could also end up with Map<C, List<C>>([const C(1)]: [const C(1)]). I don't think it makes anything worse by itself, it's allowing non-constant arguments which changes things. The part before the : is still going to be a non-pattern member invocation with constant arguments, the RHS is a pattern, but I'd want to make sure we don't make something impossible for our later selves.)

@munificent
Copy link
Member

I'd want to make sure we don't make something impossible for our later selves.

I agree. I could see us loosening the restriction on relational pattern operands to allow non-const ones which would be a breaking change if we make it an implicit const context.

In practice, I think almost all relational operand RHS expressions will be either integer literals or named constants, neither of which require const. So treating the RHS as implicitly const doesn't buy us much and could cause us problems later. I think we should just leave it as it is.

munificent added a commit that referenced this issue Jan 19, 2023
-   Allow object pattern fields to tear off methods.

-   No exception for non-exhaustive switch statements that don't need
    to be exhaustive.

-   Promoted types and bounds can be always-exhaustive.

-   Fix incorrect static error with cast patterns in assignments.

-   Clarify that patterns are not const contexts.

Fix #2561.
Fix #2698.
Fix #2765.
Fix #2758.
munificent added a commit that referenced this issue Jan 19, 2023
* [patterns] Fix a handful of small-ish patterns issues:

-   Allow object pattern fields to tear off methods.

-   No exception for non-exhaustive switch statements that don't need
    to be exhaustive.

-   Promoted types and bounds can be always-exhaustive.

-   Fix incorrect static error with cast patterns in assignments.

-   Clarify that patterns are not const contexts.

Fix #2561.
Fix #2698.
Fix #2765.
Fix #2758.

* Tweak wording in a few places.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patterns Issues related to pattern matching. question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants