Overload Resolution of Binary Operators


(Toni Suter) #1

Hi,

I would have expected that the following code reports an error, because
of ambiguous function overloads:

infix operator ***: MultiplicationPrecedence
infix operator +++: AdditionPrecedence

func ***(x: Int, y: Int) -> String {
  print("f1")
  return ""
}

func ***(x: Int, y: Int) -> Int {
  print("f2")
  return 0
}

func +++(x: String, y: Int) -> Int {
  print("f3")
  return 0
}

func +++(x: Int, y: Int) -> Int {
  print("f4")
  return 0
}

let result = 0 *** 4 +++ 0 // prints f2 and f4

As far as I can tell, there are two possible overload resolutions: f1 + f3 or f2 + f4.
I thought that these two solutions get an "equivalent score" and therefore there would
be a compile error. However, that's not the case. Instead, the type checker picks
f2 and f4.

So, I guess my question is, whether there is some rule, that prefers
operators, which have the same argument types and the same return type
or whether this is simply a bug.

Thanks and best regards,
Toni


(Mark Lacey) #2

Hi,

I would have expected that the following code reports an error, because
of ambiguous function overloads:

infix operator ***: MultiplicationPrecedence
infix operator +++: AdditionPrecedence

func ***(x: Int, y: Int) -> String {
  print("f1")
  return ""
}

func ***(x: Int, y: Int) -> Int {
  print("f2")
  return 0
}

func +++(x: String, y: Int) -> Int {
  print("f3")
  return 0
}

func +++(x: Int, y: Int) -> Int {
  print("f4")
  return 0
}

let result = 0 *** 4 +++ 0 // prints f2 and f4

As far as I can tell, there are two possible overload resolutions: f1 + f3 or f2 + f4.
I thought that these two solutions get an "equivalent score" and therefore there would
be a compile error. However, that's not the case. Instead, the type checker picks
f2 and f4.

So, I guess my question is, whether there is some rule, that prefers
operators, which have the same argument types and the same return type
or whether this is simply a bug.

It’s a bug, and one that I’m aware of, but I’m not aware of anything in JIRA for it. Do you mind opening an issue there and assigning it to me?

Mark

···

On Nov 14, 2016, at 2:05 PM, Toni Suter via swift-users <swift-users@swift.org> wrote:

Thanks and best regards,
Toni
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(David Sweeris) #3

Odd... Perhaps the compiler is convinced the result of the *** operation needs to be an Int? Dunno why that would be, though.

What happens if you split it up into two statements?

- Dave Sweeris

···

On Nov 14, 2016, at 16:05, Toni Suter via swift-users <swift-users@swift.org> wrote:

Hi,

I would have expected that the following code reports an error, because
of ambiguous function overloads:

infix operator ***: MultiplicationPrecedence
infix operator +++: AdditionPrecedence

func ***(x: Int, y: Int) -> String {
  print("f1")
  return ""
}

func ***(x: Int, y: Int) -> Int {
  print("f2")
  return 0
}

func +++(x: String, y: Int) -> Int {
  print("f3")
  return 0
}

func +++(x: Int, y: Int) -> Int {
  print("f4")
  return 0
}

let result = 0 *** 4 +++ 0 // prints f2 and f4

As far as I can tell, there are two possible overload resolutions: f1 + f3 or f2 + f4.
I thought that these two solutions get an "equivalent score" and therefore there would
be a compile error. However, that's not the case. Instead, the type checker picks
f2 and f4.

So, I guess my question is, whether there is some rule, that prefers
operators, which have the same argument types and the same return type
or whether this is simply a bug.


(Rien) #4

I seem to remember that while it is possible to define, the compiler will yield an error if you try to use the functions (“cannot resolve”).

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

···

On 14 Nov 2016, at 23:05, Toni Suter via swift-users <swift-users@swift.org> wrote:

Hi,

I would have expected that the following code reports an error, because
of ambiguous function overloads:

infix operator ***: MultiplicationPrecedence
infix operator +++: AdditionPrecedence

func ***(x: Int, y: Int) -> String {
  print("f1")
  return ""
}

func ***(x: Int, y: Int) -> Int {
  print("f2")
  return 0
}

func +++(x: String, y: Int) -> Int {
  print("f3")
  return 0
}

func +++(x: Int, y: Int) -> Int {
  print("f4")
  return 0
}

let result = 0 *** 4 +++ 0 // prints f2 and f4

As far as I can tell, there are two possible overload resolutions: f1 + f3 or f2 + f4.
I thought that these two solutions get an "equivalent score" and therefore there would
be a compile error. However, that's not the case. Instead, the type checker picks
f2 and f4.

So, I guess my question is, whether there is some rule, that prefers
operators, which have the same argument types and the same return type
or whether this is simply a bug.

Thanks and best regards,
Toni
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Toni Suter) #5

@David
If you would split up the statement like this...

let x = 0 *** 4
let result = x +++ 0

... the compiler would report an ambiguity error, because both overloads of *** are valid and of equivalent priority.
You could do something like this though:

let x: Int = 0 *** 4 // picks f2
let result = x +++ 0 // picks f4

or this:

let x: String = 0 *** 4 // picks f1
let result = x +++ 0 // picks f3

Now the compiler has enough type information to know which overload to pick.

@Mark
Ok, thanks. I reported a bug at https://bugs.swift.org/browse/SR-3209 and assigned it to you.

@Rien
Yes, it is even possible to use the operators as the example above shows, but it is requires a bit more explicit
type information so that the type checker knows which overload to pick.

Thanks and best regards,
Toni

···

Am 15.11.2016 um 08:41 schrieb Rien <Rien@Balancingrock.nl>:

I seem to remember that while it is possible to define, the compiler will yield an error if you try to use the functions (“cannot resolve”).

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl

On 14 Nov 2016, at 23:05, Toni Suter via swift-users <swift-users@swift.org> wrote:

Hi,

I would have expected that the following code reports an error, because
of ambiguous function overloads:

infix operator ***: MultiplicationPrecedence
infix operator +++: AdditionPrecedence

func ***(x: Int, y: Int) -> String {
  print("f1")
  return ""
}

func ***(x: Int, y: Int) -> Int {
  print("f2")
  return 0
}

func +++(x: String, y: Int) -> Int {
  print("f3")
  return 0
}

func +++(x: Int, y: Int) -> Int {
  print("f4")
  return 0
}

let result = 0 *** 4 +++ 0 // prints f2 and f4

As far as I can tell, there are two possible overload resolutions: f1 + f3 or f2 + f4.
I thought that these two solutions get an "equivalent score" and therefore there would
be a compile error. However, that's not the case. Instead, the type checker picks
f2 and f4.

So, I guess my question is, whether there is some rule, that prefers
operators, which have the same argument types and the same return type
or whether this is simply a bug.

Thanks and best regards,
Toni
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users