2

Here's one,

 import SQLite

    var r:[[Any]] = []

    do {
        if let stmt = try local.db?.prepare(q) {
            r = Array(stmt)
        }
        else {
            print("woe in sql?")
        }
    }
    catch { return [] }

the call

 r = Array(stmt)

gives Expression implicitly coerced from 'Binding?' to Any.

enter image description here

And indeed, I do not know how to Provide a default value to avoid this warning, Force-unwrap the value to avoid this warning, or even Explicitly cast to Any with 'as Any' to silence this warning. :O

Here's a self-contained example that reproduces the same warning:

struct Binding {}

struct Statement : IteratorProtocol, Sequence {
    func next() -> [Binding?]? {
        return nil
    }
}

let stmt = Statement()

let r: [[Any]]

r = Array(stmt) // warning: Expression implicitly coerced from 'Binding?' to Any.

Related interesting question:

Why does the compiler ...

enter image description here

... appear to not know the line number, with problems like this? And indeed: why does the warning only arise once you compile?

Most warnings appear right there in the IDE as you're typing, before compilation.

This warning would appear to (a) only be known during compiling and (b) the compiler doesn't know the line number.

How so? What's the difference?

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • Can you make your code self-contained? There are are multiple `prepare()` methods, so it is difficult to tell which one is called here. – Martin R Jan 28 '17 at 18:58
  • Martin, thanks .. (a) I don't actually know what you mean by self-contained here (b) unfortunately indeed I can't figure out what the heck call is being used exactly in https://github.com/stephencelis/SQLite.swift :/ – Fattie Jan 29 '17 at 12:04
  • @Hamish: yes, good point: I'm totally in favor of using [[Binding?]]. The thing is, the otherwise awesome SQLite.Swift is a little under-documented regarding the feature of using arbitrary sql calls (which is the only way we use it in the project at hand); for whatever reason the little example code I found kicking around favored [[Any]]. Indeed, I haven't been able to find any good reason to use [[Any]] so we indeed changed to [[Binding?]]. However, the question posted here keeps me up at night. – Fattie Jan 29 '17 at 12:52
  • Regarding the compiler not knowing what line the warning occurs on – I cannot comment on the cause, but it is fixed in Swift 3.1 with Xcode 8.3 beta :) – Hamish Jan 29 '17 at 13:08
  • I hope you don't mind @JoeBlow, but I added a self-contained example to your question in order to make it easier for others to reproduce. – Hamish Jan 29 '17 at 13:21
  • @Hamish - yeah, of course, edit anything anytime - good one – Fattie Jan 29 '17 at 13:29
  • Doesn't know line number: ah, so basically that was just a bug; no deeper meaning. Good one! – Fattie Jan 29 '17 at 13:30

1 Answers1

5

You're using Array's sequence initialiser, which has the signature:

init<S>(_ s: S) where S : Sequence, Element == S.Iterator.Element

Because you typed r as [[Any]], Element is [Any]. However, the sequence you're passing in has an Iterator.Element type of [Binding?]. Therefore, you're implicitly coercing Binding? to Any, and as per SE-0140, this will invoke a warning – as you're losing the optionality of the inner elements, which is potentially undesirable.

As the proposal says, one way to silence this warning is to add an explicit as Any cast. In your case, this can be achieved by using a nested map(_:):

r = stmt.map { $0.map { $0 as Any } }

enter image description here

This shouldn't be any more costly than using Array's sequence initialiser due to the fact that a walk over all the inner elements will have to be done in either case, due to the difference in how Swift stores abstract-typed values (see this Q&A for more info).

However, really you should be asking yourself whether r should be of type [[Any]]. I see no reason why you shouldn't just type it as [[Binding?]]. Doing so will both get rid of the warning and give you better type-safety.

Community
  • 1
  • 1
Hamish
  • 78,605
  • 19
  • 187
  • 280