Why `Double` can pass to `CGFloat?`, but `Double?` cannot?

struct FrameCGFloatAndDouble: View {
    let value = 12.234
    let optional: Double? = 12.234

    var body: some View {
        Text("Hello")
            .frame(minHeight: value)    // okay
            .frame(minHeight: optional) // error: Cannot convert value of type 'Double?' to expected argument type 'CGFloat?'
    }
}

Is this not allowed under SE-0307: Allow interchangeable use of CGFloat and Double types

4 Likes

Let's ask the experts: @xedin @hborla

Running this in playground I get the error on // okay row:

import Foundation
import PlaygroundSupport
import SwiftUI

struct FrameCGFloatAndDouble: View {
    let value = 12.234
    let optional: Double? = 12.234

    var body: some View {
        Text("Hello")
            .frame(minHeight: value)    // okay
            .frame(minHeight: optional) // error: Cannot convert value of type 'Double?' to expected argument type 'CGFloat?'
    }
}

I tnink you might be running a version of Xcode which doesn't support Double <-> CGFloat conversions. You can try a snapshot of 5.5 or main and it should work.

1 Like

We did it only for value -> optional because optional <-> optional conversions are hard to represent via the mechanism we are using to implement this (calling Double.init or CGFloat.init implicitly) because there could be multiple levels of optionality that have to be matched. I guess one way to implement that might be to use linked flatMap implicitly e.g.

import Foundation

func test(v: Double??) -> CGFloat?? {
  v.flatMap { $0.flatMap { CGFloat($0) } }
}

Might be worth opening a bug on bugs.swift.org as a refinement on the current implementation.

7 Likes

https://bugs.swift.org/browse/SR-15218

2 Likes

Thank you!

I'm not very clear on Optional.map() vs. .flatMap(). I tested your func test() between the two and seems work equally either flatMap() or map().

Is there specific reason to choose flatMap here?

I thought that Optional had only flatMap for some reason, but either of them should do :)

1 Like

So you added support for Conversion CGFloat? <-> Double?

No, this is just a diagnostic. I mentioned on JIRA that adding such a conversion is not a trivial task and outliner a possible approach.

1 Like