-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[QoI] Diagnose initializers written as typed patterns (SR-1461) #4371
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
Conversation
} | ||
diagnose(lParenLoc, diag::initializer_as_typed_pattern) | ||
.highlightChars(Ty.get()->getStartLoc(), | ||
rParenLoc.getAdvancedLoc(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not .highlight({Ty.get()->getStartLoc(), rParenLoc})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I guess I was wrong about the need to use getAdvancedLoc to highlight all the way to the closing paren. Will change.
replacement = "="; | ||
} | ||
diagnose(lParenLoc, diag::initializer_as_typed_pattern) | ||
.highlight({Ty.get()->getStartLoc(), rParenLoc}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation is wrong here
diagnose(lParenLoc, diag::initializer_as_typed_pattern) | ||
.highlight({Ty.get()->getStartLoc(), rParenLoc}) | ||
.fixItReplace(colonLoc, replacement); | ||
result.setIsParseError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little unhappy that the parsed expr doesn't end up anywhere. That will probably break syntax highlighting and code completion. Is it possible to put it into the AST somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any ideas how? Might be able to hoist this into the caller, so if after parsing the pattern we find it's actually an initializer, we can parse it as such. It looked much easier the way it is when I implemented it, but I'll take another look later today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. @benlangmuir, @nkcsgexi, any ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrm. I take it Swift's lexer isn't fancy enough to be able to modify the token stream? If we backtracked and replaced the :
with `=' the caller would probably recover very well.
Short of that, yeah trying to handle more of this in the caller might be workable...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we at least preserve the TypeRepr, maybe parsed like var x: [Int]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, my bad. You do preserve the TypeRepr. For the expressions in call arg, I've no other suggestions except hoisting to the caller as another expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, I guess there is a question of whether we want PatternBindingDecl parsing to generally recognize incorrect var x: «expr»
and treat it as var x = «expr»
instead.
(The fix as written is pretty simple because it only handles exprs that look like initializer calls. It handles var x: [Int]()
, but it won't handle var x: Unmanaged.fromOpaque(y)
or var x: MemoryLayout<Int>.stride
, for instance.)
In general, if the user made a typo and wrote :
instead of =
, the parser might only notice a problem after successfully parsing a typed pattern binding. So, unless we want to try parsing var x = «expr»
first every time we look at a pattern (even if we see a :
), I think this would need to be hoisted even further out than the caller of parseTypedPattern()
, because it needs to invoke all the logic in parseExpr
/parseExprPostfix
, and it might need to do so even if parseTypedPattern succeeded.
Which is to say: the fix as written is pretty simple and self-contained. After reading some more of the parser implementation, I'm inclined to think producing better results than this would be considerably more involved. Feel free to prove me wrong, if you can think of a clean way to do it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of recognizing var x : <<expr>>
as var x = <<expr>>
. However, there may be other problems by doing so; for instance, if there is a function called getEqualPos()
in the AST node, what will it return? an invalid position or the position of :
instead.
The fixit per se is for sure an improvement! Thanks for working on that. Preserving erroneous AST nodes and providing insight of them is ideal for tooling but I have to say it is not easy in this case.
This is a great fix to have. |
@jrose-apple Thanks for the prompting on additional tests — that led me to discover trailing closures weren't handled properly at the top level, so I added a I also improved the logic for choosing a replacement string, so the fix-it won't produce invalid expressions like @swift-ci please smoke test macOS |
// Suggest replacing ':' with '=' (ensuring proper whitespace). | ||
|
||
bool needSpaceBefore = | ||
SourceMgr.getByteDistance(pastEndOfPrevLoc, colonLoc) == 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can just use ==
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can just use ==
.
@jrose-apple done! |
friendly bump @jrose-apple @DougGregor |
LGTM! |
|
||
bool needSpaceBefore = (pastEndOfPrevLoc == colonLoc); | ||
bool needSpaceAfter = | ||
SourceMgr.getByteDistance(colonLoc, startOfNextLoc) <= 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[pull] swiftwasm from main
What's in this pull request?
Diagnose and offer to replace
var x: [Int]()
withvar x = [Int]()
.Resolved bug number: SR-1461
Before merging this pull request to apple/swift repository:
Triggering Swift CI
The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:
Smoke Testing
A smoke test on macOS does the following:
device standard libraries are not built.
version of these tests are not run.
A smoke test on Linux does the following:
tests are not run.
Validation Testing
Lint Testing
Note: Only members of the Apple organization can trigger swift-ci.