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-1996] Accessing count inline on a filtered Lazy{Map,Filter}Collection causes ambiguous use of filter() #44605
Comments
Comment by Zenny Chen (JIRA) There're two overloaded filter methods here and both have the same parameter list but different return types. So, you should specify the definite type of the method you want to invoke. The following code is OK: let dict = [
"Key1": "ABCDEFG",
"Key2": "HIJKLMN",
"Key3": "OPQRSTU",
"Key4": "VWXYZ"
]
// Here, use `as` to specify the right method to invoke
let count = (dict.values.filter as ((String) -> Bool) -> LazyFilterCollection<LazyMapCollection<[String:String], String>>)() { $0.hasPrefix("ABC") }.count
print("count = \(count)") It works though the type using `as` to specify is too complicated... 🙂 |
Interestingly it only happens when accessing |
Comment by Zenny Chen (JIRA) Without accessing the property `count`, the method `filter` doesn't need the result and it may choose an either method. Because there is no return value and no other side effects, either of these methods is OK. I suppose it is an optimization. There's another easy way to work around this problem: let values = [String](dict.values)
let count = values.filter() {
return $0.hasPrefix("ABC")
}.count Convert the LazyMapCollection type to an array, and that'll be simpler. |
Yea. This is one of the workarounds I mentioned. |
Comment by Zenny Chen (JIRA) What's weird, the following code has no problem: let tmp = dict.values.filter() {
return $0.hasPrefix("ABC")
} According to the debugger, the type of `tmp` is LazyFilterCollection. |
Yep. That's exactly what I meant before. Since it's able to choose an implementation in this case, it should also be able to choose an implementation in case I call |
@gribozavr, @moiseev, there was another one like this recently, right? |
I can't find it, but yes, we have lots of similar issues, that are caused by the same root issue. |
https://bugs.swift.org/browse/SR-461 and https://bugs.swift.org/browse/SR-1856 and https://bugs.swift.org/browse/SR-851 are believed to be caused by the same overload resolution behavior. |
There's no error in Swift 4 anymore. Has this been fixed? |
@ffried The type of `Dictionary.Values` is different between Swift 3 and Swift 4. See https://github.com/apple/swift/blob/master/stdlib/public/core/HashedCollections.swift.gyb#L2406 and https://github.com/apple/swift/blob/master/stdlib/public/core/HashedCollections.swift.gyb#L2449 The described problem arises whenever you're calling |
Thanks for the info, @moiseev. Didn't notice this change. So, is there an issue tracking this particular version of the issue ( These few lines are enough to reproduce it: let arr = ["A", "B", "C"]
let lazy: LazyMapCollection = arr.lazy.map { $0 }
lazy.filter { $0 > "A" }.count // <- Error: Ambiguous use of 'filter' |
@ffried I don't know of a JIRA that this can be duped to, so I'd leave it as is. Please update the description with a shorter reproduction case. Thanks! |
Comment by Chris Aljoudi (JIRA) This also occurs, similarly, when accessing `.first` |
@xedin I've just downloaded the latest development snapshot from https://swift.org/download/#snapshots (created on Nov 21th) but it still gives me an ambiguous use of filter for the simplified reproduction case: let arr = ["A", "B", "C"]
let lazy: LazyMapCollection = arr.lazy.map { $0 }
lazy.filter { $0 > "A" }.count // <- Error: Ambiguous use of 'filter' Two candidates are found: one in Am I missing something? |
@ffried You should try with "Trunk Snapshot", here is what I get:
|
@xedin Yep, you're right. Seems like I used a Swift 4.1 Snapshot. |
Environment
Xcode 7.3.1 (7D1014)
OS X 10.11.5 (15F34)
Additional Detail from JIRA
md5: ffe0ef4741407bbc4173d4fc97cb3ebd
duplicates:
Issue Description:
When accessing the
count
property of aLazyFilterCollection
generated by filtering aLazyMapCollection
generated by accessing values of aDictionary<K, V>
causes an error about an ambiguous use offilter()
.Sample Code:
Full Error Message:
Workaround
Filtering the
Dictionary<K,V>
directly works fine.Also, it works when storing the results of
filter()
in a variable and accessingcount
on this variable.So does converting either the
LazyFilterCollection
or theLazyMapCollection
into anArray<T>
before usingfilter()
, orcount
respectively.Samples:
Update 1
In Swift 4, this can no longer be reproduced using a Dictionary, since
values
of a Dictionary is no longer lazy.The underlying issue always was with
LazyMapCollection
orLazyFilterCollection
. This code reproduces this in Swift 4:The text was updated successfully, but these errors were encountered: