'T != Type' in where clause


#1

I'm also annoyed by this, so I second this proposal.

To give an explicit example of the kind of code that can lead to frustration and a desire for "T != Type":

protocol P1 {}

protocol P2 {
  // Now, any type conforming to P1 and P2 may not be added to itself
  static func +<T: P1>(lhs: Self, rhs: T) -> Self
  static func +<T: P1>(lhs: T, rhs: Self) -> Self
}

struct S: P1, P2 {
  static func +<T: P1>(lhs: S, rhs: T) -> S { return lhs }
  static func +<T: P1>(lhs: T, rhs: S) -> S { return rhs }
}

let s1 = S()
let s2 = S()

print(s1 + s2) // ambiguous use of operator '+'

If I understand, this would be the desired capability:

protocol P1 {}

protocol P2 {
  // Now, there's no ambiguity
  static func +<T: P1 where T != Self>(lhs: Self, rhs: T) -> Self
  static func +<T: P1 where T != Self>(lhs: T, rhs: Self) -> Self
  static func +(lhs: Self, rhs: Self) -> Self
}

struct S: P1, P2 {
  static func +<T: P1 where T != Self>(lhs: T, rhs: S) -> S {
    return rhs
  }
  static func +<T: P1 where T != Self>(lhs: S, rhs: T) -> S {
    return lhs
  }
  static func +(lhs: S, rhs: S) -> S {
    return lhs
  }
}

Some thought would have to be given to how to handle subtype relationships — probably you would use the polymorphic type of the object at the call site.


(Anton Zhilin) #2

But it already works without where T != Self. Moreover, I guess, this
solution is currently considered “good enough” not to introduce additional
complexity to type system.
Also, on and and or—the former already exists in the form of &, and the
latter is listed in commonly proposed rejected features.

···

2017-02-28 7:23 GMT+03:00 Robert Bennett via swift-evolution < swift-evolution@swift.org>:

protocol P1 {}

protocol P2 {
        // Now, there's no ambiguity
        static func +<T: P1 where T != Self>(lhs: Self, rhs: T) -> Self
        static func +<T: P1 where T != Self>(lhs: T, rhs: Self) -> Self
        static func +(lhs: Self, rhs: Self) -> Self
}

struct S: P1, P2 {
        static func +<T: P1 where T != Self>(lhs: T, rhs: S) -> S {
                return rhs
        }
        static func +<T: P1 where T != Self>(lhs: S, rhs: T) -> S {
                return lhs
        }
        static func +(lhs: S, rhs: S) -> S {
                return lhs
        }
}

Some thought would have to be given to how to handle subtype relationships
— probably you would use the polymorphic type of the object at the call
site.