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-14440] Confusing diagnostics when attempting to use a trailing closure in an if let
#56796
Comments
@swift-ci create |
Trailing closure syntax and statements with blocks such as
You can wrap the A minimal reproducer for this bug may be: struct S {
let foo = true
func bar(_: () -> ()) -> Self { self }
}
if S().bar {}
.foo { print(3) } If you press enter after if S().bar{}
.<HERE> // no suggestions
// it works inline
if S().bar {}.<HERE> // suggests .foo
// it works if wrapped in brackets
if (S().bar {}
.<HERE>) // suggests .foo |
lithium3141 (JIRA User) This is expected behavior. Trailing closure syntax is not supported in the condition of an if let string = (1 ... 9999)
.map { /* this is treated as the body of the 'if' statement! */ } Of course, the if let string = (1 ... 9999)
.map({ /* this is unambiguously a closure argument */ }) On the other hand, the diagnostic could certainly be clearer. I'm going to edit this report so it tracks the poor diagnostic instead of the surprising-but-correct behavior. |
(Specifically, if we see |
@beccadax, I think the problem resides in the fact that the parser acts differently if the statement spans multiple lines. Given the minimal reproducer I posted above struct S {
let foo = true
func bar(_: () -> ()) -> Self { self }
} if we have the following in a single line if S().bar {}.foo { print(3) } then the correct warning is emitted:
If, however, we split it in two lines if S().bar {}
.foo { print(3) } then it gets parsed as two statements, i.e. as if S().bar {}; .foo { print(3) } leading to the surprising errors. If lithium3141 (JIRA User)'s statement were on a single line if let string = (1 ... 9999).map { String(format: "%@_%04d", "foo", $0) }.first { $0.hasSuffix("_0003") } { print(string) } it would be parsed and compiled correctly. |
Environment
Xcode 12.4 (12D4e) on macOS Big Sur 11.2.3 (20D91)
Additional Detail from JIRA
md5: e4e6e9982f83a4f89bfc8bb0ef3cf88b
Issue Description:
I tried to write a snippet that mapped over a ClosedRange, looking for the first Int that — when formatted into a particular String — met a condition. (The exact format and condition aren't especially relevant.) My first pass was to wrap the entire chain in an `if let`, as such:
This does not compile, producing multiple errors:
"error: anonymous closure argument not contained in a closure" on the $0 in the map
"error: generic parameter 'T' could not be inferred" on the ... operator
"error: generic parameter 'T' could not be inferred" on "string" in the print()
If I compile this snippet with a plain `let` instead of an `if let`, it compiles and produces a `String?` value, as expected.
I think the original `if let` snippet should also be able to compile, binding `string` inside the body of the `if`.The text was updated successfully, but these errors were encountered: