Support for F-bounded polymorphism?

I am currently exploring the type system of Swift. Since within a class, a self type can only be used as the result type of methods, I tried out manual encodings using F-bounded type parameters to model classes that are open for covariant refinement. The class Point below abstracts over it's class type via parameter T. T is used in the equalsTo method to only allow comparing Points to Points.


class Point<T: Point<T>> {
  let x, y: Int
  init(x: Int, y: Int) {
    self.x = x
    self.y = y
  }
  func equalsTo(other: T) -> Bool {
    return self.x == other.x && self.y == other.y
  }
}


The Swift 2 compiler seems to accept the recursively-defined type parameter, but then fails with very strange errors:

line 4: Cannot assign a value of type 'Int' to a value of type 'Int'

line 5: Cannot assign a value of type 'Int' to a value of type 'Int'

line 8: Binary operator '==' cannot be applied to two 'Int' operands


This is clearly a compiler bug, but it's not clear whether, once the compiler is fixed, it will be possible to use F-bounds. Did I overlook any documentation that would explain what can be done with generic types and what isn't possible?


BTW, I tried various alternative encodings. They usually lead to random errors or compiler crashes. For instance, the following code deterministically crashes the Swift 2 compiler:


class Point<T where T: Self> {
...
}


Any help or references to related documentation is very welcome.


Thanks,

Matthias

Yes, those are poor error messages and I don't know whether that will work or not (with better error messages) in the future.


You might already know all this and I understand that it's just an example, but you would probably not want to use a reference type (class) for something like a Point.

Not sure if this is of any help:

protocol IntPointType {
    var x: Int { get }
    var y: Int { get }
}

struct BasicIntPoint : IntPointType {
    let x, y: Int
}

struct NamedIntPoint : IntPointType {
    let x, y: Int
    let name: String
}

extension IntPointType {
    func equals<T: IntPointType>(other: T) -> Bool {
        return self.x == other.x && self.y == other.y
    }
}

let a = BasicIntPoint(x: 123, y: 456)
let b = NamedIntPoint(x: 123, y: 456, name: "Equal to a")
let c = NamedIntPoint(x: 321, y: 654, name: "Not equal to a")

print(a.equals(b)) // Prints true
print(a.equals(c)) // Prints false

(It would be better to name that method sharesLocationWith(other) or similar, or have both types conform to the Equatable protocol instead, but there are several good reasons for why you would not want to have different types be equatable (having type A and B conform to Equatable doesn't mean something of type A can/should ever be equal to anything of type B). But anyway, the above does work and is perhaps kind of what I guess you were looking for.)


If you haven't already, you may want to watch these WWDC 2015 videos

What's new in Swift

Protocol-Oriented Programming with Swift

Building Better Apps with Value Types

Support for F-bounded polymorphism?
 
 
Q