Skip to content

Collection literal inference and disambiguation in constant patterns #2637

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

Closed
eernstg opened this issue Nov 16, 2022 · 3 comments
Closed

Collection literal inference and disambiguation in constant patterns #2637

eernstg opened this issue Nov 16, 2022 · 3 comments
Labels
patterns Issues related to pattern matching. question Further information is requested

Comments

@eernstg
Copy link
Member

eernstg commented Nov 16, 2022

Consider the following example (where T is some type, not an error):

void main() {
  T value = ...;
  if (value case const {}) ...;
  switch (value) {
    case const {}: break;
  }
  var x = switch (value) { case const {} => 1; default => 2};
}

Looking at the feature spec, I couldn't easily spot an answer to questions like these:

  • Does {} receive a context type schema (based on T, presumably), such that we can choose to make it a constant map respectively a constant set?
  • If no context type is provided then presumably {} would be a map, not a set? And {with, some, elements} would use bottom-up inference to choose the type arguments?
@eernstg eernstg added question Further information is requested patterns Issues related to pattern matching. labels Nov 16, 2022
@lrhn
Copy link
Member

lrhn commented Nov 16, 2022

The type inference of if (value case const{}) first finds the static type of value (T), then type checks the pattern using T as the matched value type.
This is the step which infers missing type arguments in the pattern.

For a the constant pattern here, the important rule is:

Constant: Type check the pattern's value in context type M.

where M is the matched value type.

So, the constant expression is type checked/inferred with T as context type schema. If T provides a hint to being a set or map, and to the element/key/value types of such, those hints apply like they normally would, this is normal expression type inference with a context type. (And if those element/key/value types aren't constant, I assume we default to Never as usual, it's a normal constant expression.)

Basically, it's equivalent to:

T value = ...;
const T setOrMap =  {};
if (value case setOrMap) ...;

except that the constant might not be required to have a static type assignable to T, since it's a refutable pattern.

For the switch case, the logic is the same. The matched value type for the case patterns is the static type of the switch value expression.

(Having a context type for set/map literals and int/double literals was part of the design considerations.)

@eernstg
Copy link
Member Author

eernstg commented Nov 16, 2022

OK, so we do have the required rules: Constant patterns receive a context type from the scrutinee. The information flow is simple: Constant patterns are refutable, so no information flows from the pattern to the scrutinee. Hence, it's not a problem that we need to get the type from the scrutinee before we can decide whether {} is a map or a set.

@eernstg eernstg closed this as completed Nov 16, 2022
@stereotype441
Copy link
Member

Note: #2639 is a PR to clean up some spec text that was causing me to be confused about this issue.

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

No branches or pull requests

3 participants