基本运算符重载的奇怪类型错误

时间:2018-01-07 15:54:01

标签: swift types operator-overloading

我正在编写结构来表示向量和矩阵,有些运算符可以使用它们。但是这些运算符的一些示例用法会产生类型错误,我无法解释。

这是我的图书馆减少的排泄量(A是一种矩阵类型,B是一种矢量类型,对于那些感兴趣的人:

struct A { }
struct B { }

func *(left: A, right: A) -> A { return A() }
func *(left: A, right: B) -> B { return B() }

let a: A = A()
let b: B = (a * a) * B()

在Swift Playground中运行它会产生以下编译器错误:

error: Test.playground:2:20: error: 'A' is not convertible to 'B'
let b: B = (a * a) * B()
           ~~~~~~~~^~~~~

内联一些变量,在某些情况下将a * a作为单独的变量提取和/或从变量中删除类型注释,或者解决错误或产生不同的错误。

我不是在寻找一种解决方法,我正在努力了解这里发生了什么,我是在做错事还是在编译器中发现了一个错误。

我正在运行Xcode 9.2。

1 个答案:

答案 0 :(得分:4)

对我来说这看起来像个错误。如果我们省略类型注释(哪个 不管怎么说都不需要):

let a = A()
let b = (a * a) * B()

然后编译器抱怨"模糊使用":

main.swift:14:12: error: ambiguous reference to member '*'
let b = (a * a) * B()
           ^
main.swift:7:6: note: found this candidate
func *(left: A, right: A) -> A { return A() }
     ^
main.swift:8:6: note: found this candidate
func *(left: A, right: B) -> B { return B() }
     ^
Swift.Float:4:24: note: found this candidate
    public static func *(lhs: Float, rhs: Float) -> Float
                       ^
Swift.Double:4:24: note: found this candidate
    public static func *(lhs: Double, rhs: Double) -> Double

Swift.Float80:4:24: note: found this candidate
    public static func *(lhs: Float80, rhs: Float80) -> Float80
                       ^
Swift.UInt8:234:24: note: found this candidate
    public static func *(lhs: UInt8, rhs: UInt8) -> UInt8
                       ^
Swift.Int8:234:24: note: found this candidate
    public static func *(lhs: Int8, rhs: Int8) -> Int8

// ... and many more  ...

没有意义,因为那些重载不适用 两个A个操作数。

似乎编译器被混淆了#34;因为有这么多 *运算符的重载定义。问题不是 与自定义运算符一起发生,编译没有问题:

infix operator <*>: MultiplicationPrecedence

struct A { }
struct B { }

func <*>(left: A, right: A) -> A { return A() }
func <*>(left: A, right: B) -> B { return B() }

let a = A()
let b = (a <*> a) <*> B()

我建议在https://bugs.swift.org提交错误,并使用中间版 变量:

let a = A()
let a2 = a * a
let b = a2 * B()

或中间演员:

let a = A()
let b = ((a * a) as A) * B()

作为解决方法。