Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Use case
We enabled "treat warnings as errors" for Swift pigeon's unit test in this PR, which got reverted, because our recent migration to Xcode 14.3 that introduced a new warning about type inference for "Any collection".
Background
The original diagnosis was introduced in swiftlang/swift@1d21b4e, which checks against type inference for heterogeneous collection:
let foo = ["Hello", 999] // (1)
// Error: Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional.
let bar = [nil] // (2)
// Error: Heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional.
The fix is simply to add type annotation:
let foo: [Any] = ["Hello", 999] // (1)
let bar: [Any?] = [nil] // (2)
This is reasonable diagnosis, since the heterogenous collection loses the concrete type info for the elements, so we need to explicitly indicate this is indeed what we want.
Though for (2), it could use better error message - it's not exactly a "heterogeneous" collection. But anyways, this diagnosis is basically saying, if a collection can only be inferred to [Any] or [Any?] (either heterogeneous collection or [nil]), you have to explicitly tell compiler this is indeed what you want.
Changes in Xcode 14.3 / Swift 5.8
Before Swift 5.8, when passing a literal into a function, the type annotation requirement is considered as satisfied:
func takeFoo(_ foo: [Any?]) {
print(foo)
}
takeFoo(["Hello", 999])
takeFoo([nil])
This was fine, because the argument explicitly indicate that we want [Any?]
type, hence no warnings or errors. However, in Swift 5.8, the above will trigger the same diagnosis (tho as a warning not an error).
NullableReturnsTests.swift:43:53: error: heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional
let inputEncoded = binaryMessenger.codec.encode([nil])
^~~~~
as [Any?]
This change seems to be introduced by mistake, and already reverted in main branch and will be in Swift 5.9, so possibly Xcode 14.3.1
or 14.4
.
Proposal
The fix should be easy:
takeFoo([nil] as [Any?])
or:
let foo: [Any?] = [nil]
takeFoo(foo)