-
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
[SR-11711] [Parse] Single-expression implicit returns within #if declarations #34510
Conversation
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.
Active condition reliance makes me nervous because it means that new behavior would be inconsistent between static and purely dynamic cases which is not great. This might be worth discussing on forums before merging. I'm also going to add @rintaro to take a look.
Thanks for looking. The reason I singled out the active clause is because something like this is considered valid today: var z: Int {
#if false
0
#else
return 1
#endif
} Can you give an example of dynamic cases? From my understanding, only the active clause is ever executed. |
Maybe something like |
I just ran a local test on my machine using this snippet: var z: Int {
#if swift(>=5.2)
0
#else
1
#endif
}
print(z) It prints |
Could you add more test cases for closures? All I could find are {
#if true
print("howdy")
#endif
} in For example: let fn = {
#if FLAG
"foo"
#else
42
#endif
} We want to make sure that |
FYI this should resolve https://bugs.swift.org/browse/SR-3417 too |
@maustinstar Maybe I misunderstand the feature but it sounds like it's not always possible to determine active case statically, so it would be great to get some more tests for that and/or adjust the behavior to check that all of the cases have a single expression inside and if not point out locations where explicit
would type-check if we needed |
Adding test cases as @rintaro suggested. @xedin, I see your point. I also want to mention that code like this is valid in the current version of Swift (even before this pr): var z: Int {
#if FLAG
return 0
#else
var x = 1 + 2
x
#endif
} When your build setting sets the compiler flag, FLAG, to true, this compiles successfully. When false, the missing return has an error. This is because the non-active clause is not checked for a return statement during compilation. I get that this behavior doesn't seem expected, but because it is the current behavior of Swift, it seems out of scope for this PR, and might better fit in a bugfix by itself. What do you think? |
Ok, if that's the way it works today - I'd say let's just keep it... |
Okay thanks for the chat. I'll also write a new SR about that behavior and see if others think it's a bug. |
Okay @rintaro, I made changes to |
@rintaro thank you for the reviews! I've added the assertion |
@swift-ci please test |
@swift-ci please test source compatibility |
@swift-ci Please test Windows |
Thank you, @maustinstar! Please don't forget to resolve related SRs. |
Summary
Implicit returns for single line expressions do not currently allow for omitting "return" in single-expression #if declarations.
Problem
From SR-11711:
Impact
This PR enables a new set of implicit return declarations to be considered valid.
After merging this PR:
This is now valid, as is every test case covered by
test/Parse/omit_return.swift
,test/expr/closure/single_expr.swift
, and others when using #if declarations. Near-verbatim filestest/Parse/omit_return_ifdecl.swift
andtest/expr/closure/single_expr_ifdecl.swift
test the same cases wrapped in #if declarations.For closures, the implicit result type is now inferred from the single-expression in the active clause.
This now resolves to
() -> Int
or() -> String
depending on the flag. (This previously resolved to() -> ()
with an unused literal).Limitations
The only scenario that can't be replicated (yet) is this:
This seems to be a problem with the way #if declarations are lexed, and probably warrants a separate pull request. For now, syntax like this works:
Implementation Notes
Using back node for single-expression
Previously, when getting or setting the single-line expression, it was common to access the front node. This implementation now retrieves the back node. This will retrieve the same node for single-expression bodies, but #if declarations that look like single expressions actually contain two nodes: the if-declaration, and the active clause. To get the active clause in these scenarios, we need to use the back node.
Unsupported if-declaration bodies
Consider the following cases:
Such cases are intentionally not supported. While the flag condition combinations seem to leave a single-expression, certain flag combinations could result in cases with an unused literal or an error for missing a return statement. Additionally, any flag combination state can already be represented within a single #if declaration.
Links
Resolves SR-11711 and SR-3417.
Tagging @nate-chandler for authoring #23251 and @dabrahams for reporting SR-1171.