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-586] $0 captures all closure argument as single tuple when no larger-numbed $N used #43203
Comments
Comment by Robert (JIRA) +1 This doesn't look like a bug, it actually seems like this was intentional (although I agree it is a terrible design choice). In a closure accepting N+1 arguments, you must explicitly use the largest anonymous variable, $N, in order to use any smaller arguments, unless you only use $0 in which case $0 will capture all arguments. For instance,
|
Comment by Robert (JIRA) After a little more thought, there actually seems to be a consistent explanation for all of this behavior: Swift believes that a closure takes as many arguments as the largest $n used within the closure. The oddity of $0 capturing all arguments is really just the closure taking in the "arguments" as a tuple and treating the tuple as a single argument. In the cases of f1 and f2, Swift believes the closure takes 2 or 3 arguments, and the type of f1 and f2 is inconsistent with this. The final case works because it happens that a 4-argument closure is exactly what was needed. |
Robert — Yes, you’ve correctly understood the current behavior's (il)logic. The question is whether it's a bug. There’s additional detail from the core team in this swift-evolution discussion thread: http://thread.gmane.org/gmane.comp.lang.swift.evolution/3915/ There's disagreement among members of the core team about whether the current behavior is a bug, a feature, or some of both. On the one hand, it's confusing, and it contradicts the documentation. On the other hand, people may be using the $0-is-a-tuple behavior in existing code. I think we need a call from the team to determine whether this is something to fix in 2.x, a language change for Swift 3+, or something else. |
SE-0110 has been implemented so this code is no longer accepted in Swift 4 mode. |
@slavapestov: I’m not sure this should be closed. I still think the code in the bug ought to compile in principle. The underlying problem here is that when a closure with implicit args has highest-numbered arg $n, the compiler assumes the closure has exactly n args. It should assume that the closure has at least n args. This snippet is perhaps a better illustration than the one in the original bug: func foo(_ val: Int) { }
func bar(closure: (Int,Int,Int,Int,Int) -> Void) {
closure(0, 1, 2, 3, 4)
}
bar { foo($0) } // compiler error!
bar { foo($1) } // nope!
bar { foo($2) } // sadness!
bar { foo($3) } // ennui!
bar { foo($4) } // just hunky dory It’s a bit absurd that the compiler will infer lower-numbered unused implicit args, but not higher-numbered ones. SE-110 doesn’t address this directly. It does shift the single tuple interpretation mentioned in the original bug statement, but nothing in SE-110 says the example code shouldn’t compile. |
Confirmed: this is not fixed in Swift 4. This bug should not be marked resolved. cc @slavapestov |
This behavior really surprises me, and is against much of what makes Swift intuitive and logical. Given a method like:
I should be able to call it using the first parameter only without issue:
Unfortunately, this is not possible. Error
Tested in Swift 4 Beta 1 (and per @pcantrell it appears to still not be addressed despite any fixes related to SE-110). cc @slavapestov |
Via: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160118/007095.html
@rjmccall do you still agree that this is a bug that needs to be fixed? |
If it still reproduces, I think it's still a bug? I don't know why it wouldn't be. |
Yes, it still reproduces. Created new issue SR-6612 which links to this one. |
Environment
Swift 2.1
Additional Detail from JIRA
md5: f978a8209f2dc3cd4b9e748eb484c07d
relates to:
Issue Description:
The following code does not compile, but should:
In the absence of $1, the implicit $0 variable captures all the arguments as a tuple. The compiler error is:
Cannot convert value of type (Int, Int) to expected argument type Int
John McCall indicated on swift-evolution that this is a bug, not an intentional feature:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160118/007095.html
The text was updated successfully, but these errors were encountered: