Why doesn't eg `extension Array<Int> { ... }` compile even though using a typealias does?

I'm still on Xcode 13.2.1 at the moment, so sorry if this question is outdated. Asking here after a quick fruitless search.

Here's an example of how I'm used to writing same type constrained extensions:

extension Array where Element == Int {
  var sum: Int { reduce(0, +) }
}

I happened to notice that this also works:

typealias ArrayOfInts = Array<Int>
extension ArrayOfInts {
  var sum: Int { reduce(0, +) }
}

So why these errors for:

extension Array<Int> { // āŒ Constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause
  var sum: Int { reduce(0, +) } // āŒ Cannot convert value of type '(Int) -> Int' to expected argument type '(Int, Element) throws -> Int'
}

?

2 Likes

The inconsistency you are facing is part of what is being discussed in the lightweight same-type requirements for primary associated types thread. It's not the main topic of discussion, however it was discussed at one point iirc. Sadly I cannot find back the posts explicitly mentioning that inconsistency.

4 Likes

It's an artificial restriction that can be lifted by passing the -enable-experimental-bound-generic-extensions frontend flag. It just needs a proposal.

11 Likes

Here you go!

6 Likes

I like that pitch, except that it came before the long-existing underlying problem ever got fixed: if you want a property instead of a method or subscript, you either

  1. need to clutter the module with a typealias, as in this thread
  2. or, if you need constraints that reference an enclosing type, are out of luck.

The Future directions section is wonderful and would do a good job cloaking properties still being second-class, the way subscripts used to be.