Type of Optionals Cannot Be Inferred Correctly in Swift 2.2

Type of optionals cannot be inferred correctly in swift 2.2

This seems to be a bug. The minimal example is the following:

func genericMethod<T>(property: T?) {
print(T) // String

let stringNil = Optional<String>.None

print(stringNil is String?) // true (warning - always true)
print(stringNil is T?) // true

let intNil = Optional<Int>.None

print(intNil is String?) // false (warning - always fails)
print(intNil is T?) // true - BUG
}

genericMethod("")

Cannot translate Swift 2.2 currying to future Swift format

The inner curly braces are wrong, it should be:

func handleDownload2(iCount:Int) -> (NSData?, NSError?) -> Void {
return { (data: NSData?, error: NSError?) -> Void in
// received image
print(iCount)
print(data!.length)
}
}

A guess for a mechanism behind Type Inference

The type inference engine doesn't know the bit-width of the Ints. It doesn't even know that Ints are numbers. The engine doesn't know anything about the "restrictedness" or "narrowness" of how types are implemented. It just knows how types relate to each other as supertypes and subtypes ("ISA" relationships), and tries to solve constraint problems by figuring out what it can plug into the type variables you've provided.

The type inference engine instead is basing its choice on the version of + that is selected. None of the Int-based + functions apply. They're all of the form:

public func +(lhs: Int8, rhs: Int8) -> Int8

And this doesn't have an Int8 on both sides. So it picks the next most specific one it can find:

public func +<T : Strideable>(lhs: T, rhs: T.Stride) -> T

Why this one? An Int8 is a SignedInteger. SignedInteger implements Strideable this way:

public protocol Strideable : Comparable {
associatedtype Stride : SignedNumber
public func distance(to other: Self) -> Self.Stride
public func advanced(by n: Self.Stride) -> Self
}

extension SignedInteger {
public func distance(to other: Self) -> Int
public func advanced(by n: Int) -> Self
}

By type-inference we see that Stride is Int. So our function is:

public func +(lhs: Int8, rhs: Int) -> Int8

And that of course overflows at runtime.

BTW, the best way to figure out what function Swift has chosen is to Option-Click the + symbol. It'll tell you what types it's using.

Determine if Any.Type is Optional

Assuming that what you are trying to do is something like this:

let anyType: Any.Type = Optional<String>.self
anyType is Optional<Any>.Type // false

Sadly swift currently (as of Swift 2) does not support covariance nor contravariance and type checks directly against Optional.Type cannot be done:

// Argument for generic parameter 'Wrapped' could not be inferred
anyType is Optional.Type // Causes error

An alternative is to make Optional extend an specific protocol, and check for that type:

protocol OptionalProtocol {}

extension Optional : OptionalProtocol {}

let anyType: Any.Type = Optional<String>.self
anyType is OptionalProtocol.Type // true


Related Topics



Leave a reply



Submit