Pitch: Allow generic functions to fulfill non-generic protocol requirements


(David Sweeris) #1

So, I’m working on a type, and would like to make it conform to `ExpressibleByArrayLiteral`. The thing is, I don’t actually care what type `Element` is as long as it conforms to `FixedWidthInteger` and `UnsignedInteger`. I tried writing this:
  public init <U: FixedWidthInteger & UnsignedInteger> (arrayLiteral elements: U...) { … }
But Xcode says my type doesn’t conform to `ExpressibleByArrayLiteral` unless I add an init that takes a concrete type:
  public init(arrayLiteral elements: UInt...) { … }

Does anyone else think the generic init should to be able to satisfy `ExpressibleByArrayLiteral` (especially since `UInt` meets the conformance requirements)? I suspect that the compiler is complaining because the generic init function implies that the `Element` associated type is a generic constraint, rather than a concrete type (which maybe makes this related to generic protocols?). I think that’s only an issue because of the current ExpressibleBy*Literal protocols’ reliance on associated types to specify the relevant init’s signature, though. If the protocols (or literal system) could be re-architected so they don't need those associated types, it might make implementing this easier. I don’t know how much work either approach would be. Nor am I sure if it’d be better for this to be a use-case for another proposal instead of its own thing.

- Dave Sweeris


(Xiaodi Wu) #2

So, I’m working on a type, and would like to make it conform to
`ExpressibleByArrayLiteral`. The thing is, I don’t actually care what type
`Element` is as long as it conforms to `FixedWidthInteger` and
`UnsignedInteger`. I tried writing this:
  public init <U: FixedWidthInteger & UnsignedInteger> (arrayLiteral
elements: U...) { … }
But Xcode says my type doesn’t conform to `ExpressibleByArrayLiteral`
unless I add an init that takes a concrete type:
  public init(arrayLiteral elements: UInt...) { … }

Does anyone else think the generic init should to be able to satisfy
`ExpressibleByArrayLiteral` (especially since `UInt` meets the conformance
requirements)?

Your type needs to be generic.

struct S<T : UnsignedInteger & FixedWidthInteger> {
  let x: [T]
}

extension S : ExpressibleByArrayLiteral {
  init(arrayLiteral: T...) {
    self.x = arrayLiteral
  }
}

I suspect that the compiler is complaining because the generic init

···

On Wed, May 24, 2017 at 3:32 PM, David Sweeris via swift-evolution < swift-evolution@swift.org> wrote:

function implies that the `Element` associated type is a generic
constraint, rather than a concrete type (which maybe makes this related to
generic protocols?). I think that’s only an issue because of the current
ExpressibleBy*Literal protocols’ reliance on associated types to specify
the relevant init’s signature, though. If the protocols (or literal system)
could be re-architected so they don't need those associated types, it might
make implementing this easier. I don’t know how much work either approach
would be. Nor am I sure if it’d be better for this to be a use-case for
another proposal instead of its own thing.


(Jordan Rose) #3

We just don’t allow any broader acceptance in this case—no superclasses, no optionals, and no generics. I think we just consider it a bug (SR-522 <https://bugs.swift.org/browse/SR-522>).

Jordan

···

On May 24, 2017, at 13:32, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

So, I’m working on a type, and would like to make it conform to `ExpressibleByArrayLiteral`. The thing is, I don’t actually care what type `Element` is as long as it conforms to `FixedWidthInteger` and `UnsignedInteger`. I tried writing this:
  public init <U: FixedWidthInteger & UnsignedInteger> (arrayLiteral elements: U...) { … }
But Xcode says my type doesn’t conform to `ExpressibleByArrayLiteral` unless I add an init that takes a concrete type:
  public init(arrayLiteral elements: UInt...) { … }

Does anyone else think the generic init should to be able to satisfy `ExpressibleByArrayLiteral` (especially since `UInt` meets the conformance requirements)? I suspect that the compiler is complaining because the generic init function implies that the `Element` associated type is a generic constraint, rather than a concrete type (which maybe makes this related to generic protocols?). I think that’s only an issue because of the current ExpressibleBy*Literal protocols’ reliance on associated types to specify the relevant init’s signature, though. If the protocols (or literal system) could be re-architected so they don't need those associated types, it might make implementing this easier. I don’t know how much work either approach would be. Nor am I sure if it’d be better for this to be a use-case for another proposal instead of its own thing.

- Dave Sweeris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Sweeris) #4

It already is… I just don’t want to restrict it to being initialized from array literals containing that same generic type.

- Dave Sweeris

···

On May 24, 2017, at 5:11 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Wed, May 24, 2017 at 3:32 PM, David Sweeris via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
So, I’m working on a type, and would like to make it conform to `ExpressibleByArrayLiteral`. The thing is, I don’t actually care what type `Element` is as long as it conforms to `FixedWidthInteger` and `UnsignedInteger`. I tried writing this:
  public init <U: FixedWidthInteger & UnsignedInteger> (arrayLiteral elements: U...) { … }
But Xcode says my type doesn’t conform to `ExpressibleByArrayLiteral` unless I add an init that takes a concrete type:
  public init(arrayLiteral elements: UInt...) { … }

Does anyone else think the generic init should to be able to satisfy `ExpressibleByArrayLiteral` (especially since `UInt` meets the conformance requirements)?

Your type needs to be generic.


(Xiaodi Wu) #5

Not sure of your particular use case, but it sounds like you'd want to
write a type-erased AnyFixedWidthUnsignedInteger wrapper.

···

On Wed, May 24, 2017 at 7:21 PM, David Sweeris <davesweeris@mac.com> wrote:

On May 24, 2017, at 5:11 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Wed, May 24, 2017 at 3:32 PM, David Sweeris via swift-evolution < > swift-evolution@swift.org> wrote:

So, I’m working on a type, and would like to make it conform to
`ExpressibleByArrayLiteral`. The thing is, I don’t actually care what type
`Element` is as long as it conforms to `FixedWidthInteger` and
`UnsignedInteger`. I tried writing this:
  public init <U: FixedWidthInteger & UnsignedInteger> (arrayLiteral
elements: U...) { … }
But Xcode says my type doesn’t conform to `ExpressibleByArrayLiteral`
unless I add an init that takes a concrete type:
  public init(arrayLiteral elements: UInt...) { … }

Does anyone else think the generic init should to be able to satisfy
`ExpressibleByArrayLiteral` (especially since `UInt` meets the conformance
requirements)?

Your type needs to be generic.

It already is… I just don’t want to restrict it to being initialized from
array literals containing that same generic type.


(David Sweeris) #6

It’s just a arbitrary-width integer type. It's generic over a “chunk” type: UIntArb<UInt8>, UIntArb<UInt32>, etc. I was just wanting to be able initialize the chunk array using an array literal containing any FixedWidthInteger & UnsignedInteger type is all. I’ll look into the type-erased wrapper thing, but I doubt it’ll be worth the effort since it was just a minor convenience issue for me in the first place.

- Dave Sweeris

···

On May 24, 2017, at 5:52 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Wed, May 24, 2017 at 7:21 PM, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On May 24, 2017, at 5:11 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Wed, May 24, 2017 at 3:32 PM, David Sweeris via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
So, I’m working on a type, and would like to make it conform to `ExpressibleByArrayLiteral`. The thing is, I don’t actually care what type `Element` is as long as it conforms to `FixedWidthInteger` and `UnsignedInteger`. I tried writing this:
  public init <U: FixedWidthInteger & UnsignedInteger> (arrayLiteral elements: U...) { … }
But Xcode says my type doesn’t conform to `ExpressibleByArrayLiteral` unless I add an init that takes a concrete type:
  public init(arrayLiteral elements: UInt...) { … }

Does anyone else think the generic init should to be able to satisfy `ExpressibleByArrayLiteral` (especially since `UInt` meets the conformance requirements)?

Your type needs to be generic.

It already is… I just don’t want to restrict it to being initialized from array literals containing that same generic type.

Not sure of your particular use case, but it sounds like you'd want to write a type-erased AnyFixedWidthUnsignedInteger wrapper.