Powershell: break and continue keywords ignore labels that start with a ":" (colon)

Created on 20 Dec 2017  路  2Comments  路  Source: PowerShell/PowerShell

break and continue accept a label argument referring to a :<labelname>-prefixed loop, providing the ability to transfer control to arbitrary enclosing loops.

Clearly, even though the : is part of the label _definition_ (e.g., :foo while { ...), it is currently not supported when _referencing_ the label (must be, e.g., break foo, not break :foo).

@lzybkr explains in https://github.com/PowerShell/PowerShell/issues/3879#issuecomment-304940545 that finding no enclosing loop to break out of / continue simply quietly exits the scripts.

While this is true of passing _nonexistent labels_ to break or continue in general, specifying a :-prefixed nonexistent label instead _targets the immediately enclosing construct_.

This is tricky especially if you think that the : is part of the label name and use it as such (as is reasonable by analogy, given that both variable assignments _and_ references use the $ sigil, for instance): By prepending the : to the name of an existing label, you get (a) an invalid label that (b) does unexpected things.

There are 2 possible solutions:

  • treat :-prefixed label references like any other nonexisting labels.

  • preferably, support : as an optional prefix character when _referencing_ labels

Steps to reproduce

  :foo while($true) {   # Loop with label
    switch ($i++) {
      0 {
        'continuing outer loop'
        # !! The label must be passed as `foo`, not `:foo`:
        continue :foo
      }
      1 {
        'exiting outer loop'
        break foo  # this works
      }
    }
    # !! Because the nonexistent label was ":"-prefixed, `continue :foo` 
    # !! unexpectedly continued its enclosing `switch` statement and
    # !! therefore transferred control here.
    'What are you doing here?'
  }

Expected behavior

continuing outer loop
exiting outer loop

Actual behavior

continuing outer loop
What are you doing here?
exiting outer loop

That is, the statement after the switch statement was unexpectedly executed.

Environment data

锘縋owerShell Core v6.0.0-rc.2 (v6.0.0-rc.2) on Microsoft Windows 7 Enterprise  (64-bit; v6.1.7601)
Windows PowerShell v5.1.14409.1012 on Microsoft Windows 7 Enterprise  (64-bit; v6.1.7601)
Issue-Discussion WG-Language

Most helpful comment

seems reasonable to me. Currently a label of ::foo is not supported so there would be no ambiguity if break :foo was referring to :foo or ::foo.

All 2 comments

seems reasonable to me. Currently a label of ::foo is not supported so there would be no ambiguity if break :foo was referring to :foo or ::foo.

Just noting, the reasoning for this seems that because ':' is not allowed in the name part of the label, using it on the 'break' or 'continue' statement is in affect not giving the statement any argument at all, and thus describes the behavior that is witnessed. An error is what should be returned, because there was a token, but it was not valid in construct, but an error is not returned because the colon and the term behind it are immediately treated as a label for a further appearing loop, but cannot actually be accessed because its behind the 'break'/'continue' statement, so its just ignored.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JohnLBevan picture JohnLBevan  路  3Comments

lzybkr picture lzybkr  路  3Comments

alx9r picture alx9r  路  3Comments

Michal-Ziemba picture Michal-Ziemba  路  3Comments

andschwa picture andschwa  路  3Comments