Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous use of operator '-' in Swift with 'abs()'

Tags:

swift

I'm trying to do the following:

var i = -(abs(-3))

or

var i = -abs(-3)

or

var i = -abs(3)

or

var i = -(abs(3))

But I get an error saying that use of minus is ambiguous. Why?

like image 532
TpoM6oH Avatar asked Dec 12 '15 12:12

TpoM6oH


2 Answers

That looks like a compiler bug to me, the type of the literal 3 should be Int. But the compiler complains

error: ambiguous use of operator '-'
var i = -(abs(-3))
        ^
Swift.-:2:20: note: found this candidate
prefix public func -(x: Float) -> Float
                   ^
Swift.-:2:20: note: found this candidate
prefix public func -(x: Double) -> Double
                   ^
Swift.-:2:20: note: found this candidate
prefix public func -(x: Float80) -> Float80
                   ^
CoreGraphics.-:2:20: note: found this candidate
prefix public func -(x: CGFloat) -> CGFloat

You can solve it with an explicit Int as parameter:

var i = -(abs(-Int(3)))

or with a type annotation on the result:

var i : Int = -(abs(-3))

As @vacawama noticed, there are more possible solutions. Casting any subexpression to Int makes the compiler happy:

var i1 = -(abs(-(3 as Int)))
var i2 = -(abs((-3) as Int))
var i3 = -(abs(-3) as Int)
var i4 = -(abs(-3)) as Int
like image 74
Martin R Avatar answered Nov 09 '22 07:11

Martin R


I agree with @MartinR that this looks like a compiler bug. So where is the problem?

My experiments point toward unary minus being the culprit. Note that even:

var i = -(3)

fails with:

error: ambiguous use of operator '-'
var i = -(3)
        ^
Swift.-:2:20: note: found this candidate
prefix public func -(x: Float) -> Float
                   ^
Swift.-:2:20: note: found this candidate
prefix public func -(x: Double) -> Double
                   ^
Swift.-:2:20: note: found this candidate
prefix public func -(x: Float80) -> Float80
                   ^
CoreGraphics.-:2:20: note: found this candidate
prefix public func -(x: CoreGraphics.CGFloat) -> CoreGraphics.CGFloat**

This simple expression:

var i = -(3 + 2)

fails with:

error: ambiguous use of operator '+'
var i = -(3 + 2)
            ^
Swift.+:2:13: note: found this candidate
public func +(lhs: Float, rhs: Float) -> Float
            ^
Swift.+:2:13: note: found this candidate
public func +(lhs: Double, rhs: Double) -> Double
            ^
Swift.+:2:13: note: found this candidate
public func +(lhs: Float80, rhs: Float80) -> Float80
            ^
CoreGraphics.+:2:13: note: found this candidate
public func +(lhs: CoreGraphics.CGFloat, rhs: CoreGraphics.CGFloat) -> CoreGraphics.CGFloat

Each time, the four types Float, Double, Float80, and CoreGraphics.CGFloat are the types Swift is having trouble deciding amongst. Why just these four? Why isn't Int in there? Especially since Swift defaults to treating an integer literal as an Int.

like image 28
vacawama Avatar answered Nov 09 '22 06:11

vacawama