Skip to content

Fixes for break label and continue label parsing#60910

Open
c42f wants to merge 1 commit intomasterfrom
caf/break-continue-fixes
Open

Fixes for break label and continue label parsing#60910
c42f wants to merge 1 commit intomasterfrom
caf/break-continue-fixes

Conversation

@c42f
Copy link
Member

@c42f c42f commented Feb 3, 2026

Fixes for the new parsing for labeled break / continue which is broken or surprising in a few ways:

  • The syntax break f() was allowed but parsed as (break f (tuple)) rather than (break (call f)). This is very surprising, so introduce a condition forcing the label to be followed by whitespace.
  • The trailing token error handling was somehow deleted (but replaced with a comment yay AI slop :-/ ?), allowing things like break + x to parse as (call-i (break) + x). We didn't have tests for this, so fix this bug and beef up the tests.
  • It doesn't use bump() with remap_kind=K"Identifier" so the label can be a contextual keyword. This is inconsistent with the rest of the parser's treatment of identifier-like things in identifier position.

Also clean up other AI slop written by Claude in #60481: delete redundant comments and factoring break and continue parsing back into a single block as they share the same logic for label validity and error recovery.

Currently this parsing doesn't allow a few things as labels that we allow in other locations as plain identifiers. For consistency we might want to consider allowing the following as labels which are currently allowed in macros like @label

  • Operator symbols like +
  • Word operators where in, as
  • var"" identifiers (?)

I didn't change these yet, however.

Fixes for the new parsing for labeled `break` / `continue` which is
broken or surprising in a few ways:

* The syntax `break f()` was allowed but parsed as `(break f (tuple))`
  rather than `(break (call f))`. This is very surprising, so introduce
  a condition forcing the label to be followed by whitespace.
* The trailing token error handling was somehow deleted (but replaced
  with a comment yay AI slop :-/ ?), allowing things like `break + x` to
  parse as `(call-i (break) + x)`. We didn't have tests for this, so fix
  this bug and beef up the tests.
* It doesn't use `bump()` with `remap_kind=K"Identifier"` so the label
  can be a contextual keyword. This is inconsistent with the rest of the
  parser's treatment of identifier-like things in identifier position.

Also clean up other AI slop, deleting redundant comments and factoring
break and continue parsing back into a single block as they share the
same logic for label validity and recovery.

Currently this parsing doesn't allow a few things as labels that we
allow in other locations as plain identifiers. For consistency we might
want to consider allowing the following as labels:

* Operator symbols like `+`
* Word operators `where` `in`, `as`
* `var""` identifiers (?)
@c42f c42f requested a review from Keno February 3, 2026 10:36
@fingolfin
Copy link
Member

fingolfin commented Feb 3, 2026

Just my two cents, but to me it is a feature that + or where can not be used as labels.

@c42f
Copy link
Member Author

c42f commented Feb 3, 2026

The win64 failure seems like an unrelated issue with the Profile stdlib. I think I've seen it elsewhere.

Just my two cents, but to me is a feature that + or where can not be used as labels

Yes I'm also ok with not supporting operators so I didn't try to generalize in this PR.

"begin break end" => "(block (break))"
"a ? continue : c" => "(? a (continue) c)"
"begin continue end" => "(block (continue))"
"break:x" => "(call-i (break) : x)" # range colon allowed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should disallow this one in 1.14 syntax - needs to work in 1.13 syntax of course, but i think it's too confusing otherwise and we may want it for more complicated labels in the future.

Copy link
Member Author

@c42f c42f Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this one is pretty weird.

It seems it was added along with the fix of #9358 but there's no sign in the commit message for why the colon was allowed as punctuation. Maybe it was just a bug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although that does raise an interesting point. What about:

label = :foo
:(@label $label begin break $label end)

I think we should probably allow interpolation here.

Copy link
Member Author

@c42f c42f Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ok I think I see. The fix of #9358 probably added : so that ternary could work, but that should have been combined with (not range-colon-enabled) to restrict it to ternaries and not ranges. But that was never added.

So there's another subtle bug to fix here: it was correct to add a test on range_colon_enabled but we actually needed the opposite !range_colon_enabled. The normal_context() at the top of parse_resword undoes our ability to test for this so will need a little refactor. Also we should gate that parsing change on syntax version.

@Keno
Copy link
Member

Keno commented Feb 3, 2026

Operator symbols like +
Word operators where in, as

Disallow I think

  • var"" identifiers (?)

These should probably be allowed.

@Keno Keno added this to the 1.14 milestone Feb 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants