I'm hitting a compiler error that is best illustrated by the small code snippet below.

My goal is be able to perform addition on instances of MyEnum directly along side CGFloat. Now for simple cases this works perfectly fine however for more complex statements as seen in let three example below it causes a compiler error. I understand there are several alternate architectures I can pick from including static let or enums with a RawValue but that is not what I'm asking here. I'd really like to understand what is causing the compiler problem in isolated code snippet I've included below.
I have a feeling the issue is coming down the precedence (compiler can't decide to evaluate the first+second parts first or the second+third parts first) but I'm not sure. I've tried several variations including,
- Moving the operator functions to global scope.
- Moving the two operator functions that take
CGFloat arguments to an extension CGFloat instead.
Here is an boiled down code snippet that illustrates the issue.
enum MyEnum {
case someOption
var value: CGFloat { ... }
}
extension MyEnum {
static func + (left: MyEnum, right: MyEnum) -> CGFloat {
return left.value + right.value
}
static func + (left: MyEnum, right: CGFloat) -> CGFloat {
return left.value + right
}
static func + (left: CGFloat, right: MyEnum) -> CGFloat {
return left + right.value
}
}
let one = MyEnum.someOption + 1
let two = MyEnum.someOption + MyEnum.someOption
let three = MyEnum.someOption + MyEnum.someOption + MyEnum.someOption // fails
let four = (MyEnum.someOption + MyEnum.someOption) + MyEnum.someOption // also fails
To add more confusion if I create a completely new custom operator called • for example and I mark it part of the AdditionPrecedence group everything works totally fine. Ultimately I want the + operator to make thing intuitive.
enum MyEnum {
case someOption
var value: CGFloat { ... }
}
infix operator •: AdditionPrecedence
extension MyEnum {
static func • (left: MyEnum, right: MyEnum) -> CGFloat {
return left.value + right.value
}
static func • (left: MyEnum, right: CGFloat) -> CGFloat {
return left.value + right
}
static func • (left: CGFloat, right: MyEnum) -> CGFloat {
return left + right.value
}
}
let one = MyEnum.someOption • 1
let two = MyEnum.someOption • MyEnum.someOption
let three = MyEnum.someOption • MyEnum.someOption • MyEnum.someOption // works totally fine now
2 Likes
hborla
(Holly Borla)
3
I'm almost certain this is another bug with the "favoring" hack described here:
xedin
(Pavel Yaskevich)
4
Unfortunately this is due to the performance hack we have in the solver that merges together types of arguments for + and other "homogeneous" operators that have (Self, Self) -> Self overloads.
2 Likes