4

FIXED IN SWIFT 4.2

Details

Xcode 9.2, Swift 4

Code

extension BinaryFloatingPoint {

    func toInt() -> Int {
        // Eror if remove this block (I do not know why)
        //  if let value = self as? CGFloat {
        //      return Int(value)
        //  }
        return Int(self)
    }
}

Error occurrence

let float: Float = 2.38945
print("Float: \(float.toInt())")        // No Error

let double = Double(float)
print("Double: \(double.toInt())")      // No Error

let cgfloat = CGFloat(float)
print("CGFloat(): \(Int(cgfloat))")     // No Error
print(".toInt(): \(cgfloat.toInt())")   // Thread 1: Fatal error: Conversion is not supported

enter image description here

Question

Why

Int(cgfloat) // No Error

but

cgfloat.toInt() // Thread 1: Fatal error: Conversion 

???

In both cases, the same type conversions Int(value) occur. My extension works with Float and Double types, but only with CGFloat error occurs. Does it a Swift language bug?

Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
  • Tht's odd, I thought `CGFloat` was an alias for `Double`/`Float` (depending on CPU bus size) – Alexander Mar 16 '18 at 17:01
  • I thought so too. Maybe a bug? – Vasily Bodnarchuk Mar 16 '18 at 17:03
  • Looks like a bug to me, maybe post on https://bugs.swift.org and see what the core team thinks. – Charles Srstka Mar 16 '18 at 17:04
  • 4
    The logic for fully generic binary floating point to `Int` conversions was recently(ish) implemented in https://github.com/apple/swift/pull/11259 (previously it was limited to just the stdlib's floating point types, such as `Float` and `Double`). In Swift 4.1, your example runs without issue. – Hamish Mar 16 '18 at 17:39
  • 1
    @Alexander It's actually a [fully fledged type of its own](https://github.com/apple/swift/blob/master/stdlib/public/SDK/CoreGraphics/CGFloat.swift.gyb#L25), but it does indeed wrap a `Float` or `Double` depending on architecture. – Hamish Mar 16 '18 at 17:43
  • @Hamish Why is that? Why couldn't `CGFloat` just be implemented as a typealias, just like its `NativeType` member typealias? – Alexander Mar 16 '18 at 18:33
  • @Alexander Good question! Presumably it's for architecture independent code, as e.g with a `typealias` you'd be able to freely pass a `CGFloat` to a `Double` on a 64 bit platform, but that won't compile on a 32 bit platform where `CGFloat` would be a `Float`. Having `CGFloat` as a separate type, which forces you to insert the necessary conversions e.g `Double(someCGFloat)`, lets the same code compile on both 32 bit and 64 bit platforms. – Hamish Mar 16 '18 at 19:06
  • 1
    @Hamish Gah, I keep wishing there was a language feature to address this, like Haskell's [`newtype`](https://wiki.haskell.org/Newtype) – Alexander Mar 16 '18 at 19:14
  • @Alexander Yeah that would be really nice, the current situation of having to create a wrapper type and mirror the underlying type's entire API is far from ideal :/ – Hamish Mar 16 '18 at 19:17
  • 3
    @Sweeper, why the bounty on this one? Current versions of Swift support this as written; there's no longer a problem here. – Rob Napier Jul 03 '18 at 22:09
  • I just wanted an explanation as to why this was not working before. – Sweeper Jul 04 '18 at 07:13

0 Answers0