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

[SR-9220] Swift takes exponential time to parse nested square brackets #51709

Closed
swift-ci opened this issue Nov 11, 2018 · 4 comments
Closed
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself parser Area → compiler: The legacy C++ parser

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-9220
Radar rdar://problem/45221238
Original Reporter christopherstern (JIRA User)
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, Parser
Assignee None
Priority Medium

md5: afb72cc93343d881cf679a6c5f48c134

Issue Description:

When the swift parser encounters a square bracket ('['), it needs to determine whether an Array or a Dictionary is starting. Swift does this by parsing the next expr, and then checking for a ':'. The parser then backtracks, throwing the results away, and parses the whole square bracketed expr list, re-parsing the first expr a second time.
<https://github.com/apple/swift/blob/b2f60bf97857aaf898d8c2fffbdff91ef32cf7f0/lib/Parse/ParseExpr.cpp#L3379:L3399>
In nested square brackets, each level doubles the number of re-parses of the head element.

That is:

  • when parsing a bracketed expression list, swift parses the first expression twice.

  • parsing an expression parses all sub-expressions

  • -> swift parses the first expr of a sbl 2^d times, d = depth of the bracketing.

So this will never finish parsing:

let b =     [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ 
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ 
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[       
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ 
            [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
            1           
              ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]        
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
            ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

To see that the parser is responsible, and not type checking, replace this code:
<https://github.com/apple/swift/blob/b2f60bf97857aaf898d8c2fffbdff91ef32cf7f0/lib/Parse/ParseExpr.cpp#L3379:L3399>
with

 bool ParseDict = false;

This removes non-empty dictionaries and the speculative parsing needed to identify them from the grammer. Now, the parser dose not hang.

The other brackets '(' and '{' do not have this issue, it is specific to '[' and the backtracking used to distinguish `[ x ]` from `[ x:y ]`.

There are several options here.

*Do nothing.
The example above was developed as a test of the compiler's cutoff of nested structures, anyone not torturing the parser is at lower risk.

*Impose an lower cutoff on square brackets then other structures.

*Remember the results of the first speculative parse.
While in a speculative-parse, store and retain the whether each '[' started an arr or dict.
This still parses heads twice, but not (2^d)-times.

@belkadan
Copy link
Contributor

Hm, we've heard of slow type-checking here but this is the first I've seen with slow parsing. @rintaro, have you seen this before?

@rintaro
Copy link
Mannequin

rintaro mannequin commented Nov 12, 2018

Yeah, this is known issue in Parser.
CC: @nkcsgexi

@nkcsgexi
Copy link
Member

Ack. Thank you for working on this! christopherstern (JIRA User)🙂

@rintaro
Copy link
Mannequin

rintaro mannequin commented Jan 8, 2019

#21487

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself parser Area → compiler: The legacy C++ parser
Projects
None yet
Development

No branches or pull requests

3 participants