Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A guess for a mechanism behind Type Inference

I've tried this code in the xCode: let bigNum = Int8.max + Int("1")! The compiler infers the variable bigNum of type Int8 and give me a overflow error.

For Int8.max + Int("1")!: the left side of "+" has the type of Int8 the right side has the type of Int. Why the compiler did not infer the bigNum as type of Int ?

Guess: Swift's compiler always infer the tye by the more narrow/restricted value types, because Int8 is a more small and narrow type compare to the Int, therefore adding an Int8 and an Int number would lead to an Int8 type inference.

Question: Am I right? or mostly right but not precise. If so, please correct me.

Thanks

like image 926
SLN Avatar asked Mar 12 '23 12:03

SLN


1 Answers

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.

like image 160
Rob Napier Avatar answered Mar 21 '23 01:03

Rob Napier