-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[Parse/Sema/SILGen] Variables in 'case' labels with multiple patterns. #1383
Conversation
This looks awesome. Do you have any SILGen tests? |
@jckarter I've been looking at the generated SIL with various examples by hand, but I'm not sure what ought to actually be checked in as tests. Here's a simple example: https://gist.github.com/gregomni/cfaef124bd943168f266 Mostly verifying that the correct tuple elements get passed into the case block, that the bits of the pattern that aren't used are still released in the pattern emission blocks. But clearly I need more work with the managed cleanups part, since I'm seeing now that %21 is still being leaked. Argh. Is there an easier / better way I haven't found to transfer a +1 value from one BB as an arg to another BB? I'm having a tough time with wanting the SILGenPattern code structure (and thus the cleanup scopes) being different from the order I'd actually like to generate the SIL. |
There's a |
Yep, I think you are right, the single scope per case instead of also per pattern is at the root of my troubles. Thanks for looking, and sorry for being a bit premature! |
Ah, I'd been staring at things too long last night. That example SIL is actually fine, what I was thinking of then as an extra retain_value of %21 is consumed by being an @owned argument to a call. So I'm back to still needing to write some SILGen tests. |
@@ -945,6 +945,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction | |||
|
|||
void emitConditionalPBD(PatternBindingDecl *PBD, SILBasicBlock *FailBB); | |||
|
|||
void usingImplicitVariablesForPattern(Pattern *pattern, CaseStmt *stmt, | |||
const std::function<void(void)> &f); |
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.
Nitpick: we have llvm::function_ref for generalized functions that don't need to be copied to the heap.
This is pretty great. |
Another thing to test: What happens if you try to access a pattern variable from another pattern in the same case? switch x {
case let a,
a: // Ought to be an error
} |
Can you also add code completion tests? They don't have to produce the best results, but they shouldn't crash. Interesting cases off the top of my head:
Completion tests live in test/IDE/. |
@jckarter Added test for accessing a pattern var from another pattern in the same case. This would be a problem if it made it through the parser, because it does think that the variable is defined, but it gets caught by the check for the second pattern needing to also define the variable. Also improved that error message so that it says 'a' must appear "as a variable" so that the diagnosis makes more sense in this case. @jrose-apple Fixed to use function_ref, thanks for the pointer! And added the code completion tests you suggested. They run and don't produce anything surprising, although ideally it wouldn't suggest using variables defined in the first pattern as an expression in the second (or subsequent) pattern. Added a FIXME for that. Are there docs or other info you could point me at to get started understanding swiftIDE? Not familiar with that part of the code yet, and nothing in the docs folder jumps out as relevant. Thanks! |
I think formally the umbrella term for For the swiftIDE question…@nkcsgexi? |
You're right, "must be bound" is a better way of putting it. |
FWIW, the code completion including the previous pattern binding var decls while in the next pattern is not a regression, it's been that way forever. |
} | ||
} | ||
|
||
// MULTI_PATTERN_2: Begin completions |
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.
Please check that a
is part of the output here too!
Sorry for missing this earlier. @gregomni A good start point to understand how Swift code completion works is by studying several straight-forward completion kinds. One example is completing import decl, you can find it at CodeCompletion.swift:4012. |
4a6be65
to
88f2dea
Compare
Added the completion test checks @jrose-apple suggested and squashed. Thanks for the pointer @nkcsgexi! I'll look into improving the completion for additional pattern next. To me it seems like it would make sense for that to be a separate pull. |
Thumbs-up from me, leaving it to Joe to say whether it's fully ready. (I didn't look too closely at the code, but it looked okay from a skim.) |
LGTM. Nice work! |
@swift-ci Please test |
Test failure looks unrelated. I'll try again when the builders are clear. |
@swift-ci Please test |
Or first, @gregomni, can you rebase? Are you able to build this branch locally? |
88f2dea
to
7848efe
Compare
Parser now accepts multiple patterns in switch cases that contain variables. Every pattern must contain the same variable names, but can be in arbitrary positions. New error for variable that doesn't exist in all patterns. Sema now checks cases with multiple patterns that each occurence of a variable name is bound to the same type. New error for unexpected types. SILGen now shares basic blocks for switch cases that contain multiple patterns. That BB takes incoming arguments from each applicable pattern match emission with the specific var decls for the pattern that matched. Added tests for all three of these, and some simple IDE completion sanity tests.
7848efe
to
63f810d
Compare
This commit e249fd6 changed the order of arguments to RValue.forwardInto(). Should've rebased and retested when I was squashing, sorry! Reran all the tests locally to make sure, that looked like the only issue. |
@jckarter Should be good to go now! |
@swift-ci Please test |
Thanks @gregomni! |
[Parse/Sema/SILGen] Variables in 'case' labels with multiple patterns.
Hooray! This deserves an update to CHANGELOG.md. :-) |
@lattner Done, thanks! |
There was a thread on swift-evolution back on Jan 23rd about adding this, and the response from the team was that it was something desirable but that you just hadn’t had time to do it so far.
Parser now accepts multiple patterns in switch cases that contain variables. Every pattern must contain the same variable names, but can be in arbitrary positions. New error for variable that doesn't exist in all patterns.
Sema now checks cases with multiple patterns that each occurrence of a variable name is bound to the same type. New error for unexpected types.
SILGen now shares a basic block for a switch case that contains multiple patterns even if there are variables. That BB takes incoming arguments from each applicable pattern match emission with the specific variables for the pattern that matched.
Added simple tests for the Parse and Sema functionality. I’d greatly appreciate suggestions on what sort of SILGen tests would be helpful. (The existing dominator assertions of variable usage and BB assertions on predecessor args caught a bunch of my mistakes along the way, so I’m pretty confident this all works, but how do I help make everyone else be confident too…)
I’m also not terribly happy with the managed value cleanup stuff between the pattern BBs and case body BBs, which works, but seems like the code could be cleaner. Again, suggestions greatly appreciated.