Xcode 14.3b2 is out and while beta 1's concurrency warnings have been fixed, there are new warnings about Any in collections. I understand why they exist, though I haven't seen anything mentioned on the forums about the new strictness. They also aren't disabled the way I'd expect. For example:
ParameterEncodingTests.swift:156:34: warning: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
let parameters = ["foo": ["a", 1, true]]
^~~~~~~~~~~~~~
as [Any]
There are two odd things here. First, the warning points only to the inner collection which, yes, is an [Any], but the overall collection also uses Any, so it was a bit surprising to me it complained about the inner collection but not the outer.
Second, while I could add the as [Any] inline, but initial thought was just to make the whole value as [String: Any], since that's the type of parameter I'm passing the value into. But that doesn't work. Instead, either you need to do the inline as or declare it as [String: [Any]], which just seems unnecessarily pedantic.
This gets more tedious with nested collections. For example:
ParameterEncodingTests.swift:226:50: warning: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
let parameters = ["foo": ["bar": ["baz": ["a", 1, true]]]]
^~~~~~~~~~~~~~
as [Any]
In this case, either I do the inline as inside several layers of collection, or declare the value as [String: [String: [String: [Any]]]], which is pretty silly.
So my questions are:
Is this intentional?
Is there a better way to address the warning? (Aside from avoiding any, which these tests specifically exercise.)
Could a root Any value be made to address the warning? It seems like, if I declare a [String: Any] value, I'm explicitly declaring that everything on the value side could be Any, including collections.
This feels like a trap. If you’re relying on a certain structure of collections (e.g. an in-memory representation of a JSON structure), typing the top level as [String : Any] would let you break that structure.
These warnings also feel unhelpful
for collection literals that are immediately bridged to their CoreFoundation equivalents. For example the following code:
let key: Data = …
let addQuery = [kSecClass: kSecClassKey, kSecAttrApplicationTag: tag, kSecValueRef: key] as CFDictionary
for use with the Security framework now produces a warning and recommends you rewrite it as as [CFString: Any] as CFDictionary.
I strongly dislike this warning and I don't think that any of the changes required to silence them improved things in any way, I also managed to introduce several bugs that took a while to track down while trying to silence them.
I get what was being attempted but something seems off, or I dont understand something. Why would even this still give the warning?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var testDict: [String: AnyObject] = ["one": "one", "two": true] as [String: AnyObject]
}
That one's definitely odd, as you can't fix the warning using AnyObject. Given that AnyObject isn't really what you want there (I think it only works due to Obj-C shenanigans), you probably want [String: Any], which does work correctly. Probably worth a bug report though.
After having fixed so many occurrences of this on tests I'm surprised this went live without evolution, yes I know is not a new feature but it would have been nice to get some discussion and warning, pun intended, for such an annoying warning.
We could use this thread to further discuss and gather thoughts on how to improve the diagnostic based on what people find more helpful and once settled if needed have an issue open in the compiler to address it for next version :)
That's not really much of a discussion. It's unclear whether what we're seeing now is intentional or an overzealous bug fix which doesn't consider [String: Any] equivalent to any nested collection type.
If the change was intended only to fix that issue then these new warnings do sound like just a bug where it went from warning not often enough to warning too often.
I am truly sorry about this everyone. The new warnings sprung from a misinterpretation of the original purpose of this ancient diagnostic, which I believe was provision for source-compatible improvements to the algorithm that joins the types (computes the upper bound). We are reverting this for good and I will try to get the fix into 5.8 too.
That doesn't seem to be the case. I'm still seeing the warning on Xcode 14.3.1 (14E300c). (Unless I'm still getting cached diagnostics from somewhere.)
Hm. At the very least the revision tagged swift-5.8.1-RELEASE includes the fix. Swift revisions that ship with Xcode can apparently be ahead of the respective open-source releases, but I have never heard of one being intentionally behind.