[CP] Patterns parsing: fix ambiguity resolution for when
and as
.
#52215
Labels
cherry-pick-approved
Label for approved cherrypick request
cherry-pick-merged
Cherry-pick has been merged to the stable or beta branch.
cherry-pick-review
Issue that need cherry pick triage to approve
legacy-area-fe-analyzer-shared
Legacy: Use area-dart-model instead.
merge-to-beta
Commit(s) to merge
637dd76
Target
Beta
Prepared changelist for beta/stable
https://dart-review.googlesource.com/c/sdk/+/299700
Issue Description
When encountering a guarded pattern of the form
case IDENTIFIER when !EXPRESSION:
orcase IDENTIFIER.IDENTIFIER when !EXPRESSION
, the parser incorrectly interprets theIDENTIFIER
(s) as a type name, thewhen
as an ordinary identifier, and the!
as a null assert pattern; then it considers theEXPRESSION
part to be unexpected text and rejects it with an error.What is the fix
The parser disambiguation rules have been adjusted so that when encountering a pattern of the form
T when
orT as
, whereT
could be parsed as a valid type name, it does not try to parse the construct as a typed variable pattern (withT
denoting the type and thewhen
oras
token denoting the variable name). Instead it falls back on an interpretation of the pattern whereT
is not a type. This could be:T
begins with an identifier)T
begins with(
)In addition to fixing the bug, this means, in effect, that typed variable patterns are no longer allowed to declare variables named
when
oras
.In a future release we intend to prohibit all variable and identifier patterns from declaring variables named
when
oras
, however for this cherry-pick request, we're restricting the change to just what's necessary to fix the bug.Why cherry-pick
Since guard expressions (the expressions after
when
in a guarded pattern) are boolean expressions, and!
is a boolean operator, guard expressions beginning with!
are likely to be common. Also, patterns of the formIDENTIFIER
andIDENTIFIER.IDENTIFIER
are likely to be comon (because these forms were both valid in switch cases prior to the introduction of patterns). So it seems likely that this issue will be triggered by user code fairly often. Without this fix, the user will see a fairly confusing parse error. The error can in principle be worked around by placing parentheses around theIDENTIFIER
(s), but this is in no way obvious.The fix is very targeted: the affected code path only triggers when a pattern is seen of the form
T when
orT as
, whereT
is a sequence of tokens that could be validly parsed as a type, and the only behaviour change is to avoid ever interpreting such a token sequence as a variable declaration. It's extremely rare for a user to deliberately name a variableas
(due to the meaning ofas
as a keyword); with the introduction of patterns it's likely that it will become equally rase for a user to deliberately name a variablewhen
. So it's highly unlikely that a user will ever write new code in which thewhen
oras
token is expected to be interpreted as a variable name. As for existing (pre-Dart-3.0) code that is being ported to Dart 3.0, @munificent checked a big corpus of pub packages, open source Flutter apps, open source Flutter widgets, the Dart repo, and the Flutter repo, and found zero switch cases containing the identifierwhen
(see #52199 (comment)).Risk
low
Issue link(s)
#52199
Extra Info
No response
The text was updated successfully, but these errors were encountered: