[swift-evolution] [Proposal] More Powerful Constraints for Associated Types

Tony Allevato allevato at google.com
Mon Apr 25 11:01:41 CDT 2016


I really like where this proposal is headed.

Would this syntax also support constraining associated types based on
"inheritability" (for lack of a better word)? For example, a couple times
I've hit a situation where I want to express a supertype/subtype
relationship. A contrived example:

protocol Foo {
  associatedtype Bar

  func f<Baz: Bar>(b: Baz.Type) -> Baz
}

This currently gives me the error "inheritance from non-protocol, non-class
type 'Self.Bar'." This makes sense in a way, because a type conforming to
Foo could define Bar to be anything, including a struct.

I see a few ways to address this:

(1) Allow users to write "associatedtype Bar: class" to indicate that the
conforming class must set Bar to be a class type, which would let the type
checker know that the Baz: Bar constraint is valid. This gets us partially
there, but is still somewhat limiting because other supertype/subtype
relationships could not be expressed, such as Bar being an arbitrary
protocol and Baz being any type that conforms to that protocol.

(2) Allow users to write "associatedtype Bar: _____", where _____ is some
way of expressing any arbitrary type that is inheritable: this would
include classes but also protocols. The difference here is instead of
specifying a specific protocol, conforming types could put any protocol
here, binding Bar in function f() to that protocol and then Baz would be
any type conforming to Bar.

(3) Allow the syntax above unchanged. If a conforming type defines Bar to
be a struct, loosen the check and still allow it such that the only
possible type that can satisfy Baz is Bar itself. This would be consistent
with other generic constraints that are class-based, where a constraint of
the form f<SomeClass: BaseClass> can still satisfy SomeClass by using
BaseClass itself.

While writing this, I noticed some other constructs that seem like they
should work, but don't:

protocol SomeProtocol {}
protocol Foo {
  associatedtype Bar: SomeProtocol
  func f<Baz: Bar>(b: Baz.Type) -> Baz
  // ^ inheritance from non-protocol, non-class type 'Self.Bar'
  // Shouldn't the compiler know that Bar is constrained by a protocol here?
}

class SomeClass {}
protocol Foo {
  associatedtype Bar: SomeClass
  func f<Baz: Bar>(b: Baz.Type) -> Baz
  // ^ inheritance from non-protocol, non-class type 'Self.Bar'
  // Same problem as above, essentially.
}

protocol A {}
protocol B {}
protocol Foo {
  associatedtype Bar: protocol<A, B>
  // ^ This one doesn't appear to even get past the parser, which is
unfortunate.
  // To express the notion of an associatedtype conforming to two
protocols, you
  // have to create a third protocol and extend the type you wish to use to
conform
  // to that protocol.
}

Some of these issues may have been addressed in "Completing generics", but
they seem like they would fit into this proposal as well.

On Mon, Apr 25, 2016 at 8:30 AM Matthew Johnson via swift-evolution <
swift-evolution at swift.org> wrote:

>
>
> Sent from my iPad
>
> On Apr 25, 2016, at 9:58 AM, Thorsten Seitz <tseitz42 at icloud.com> wrote:
>
>
> Am 25.04.2016 um 15:40 schrieb Matthew Johnson via swift-evolution <
> swift-evolution at swift.org>:
>
> I really like this proposal.  It is a nice step forward from current
> state.
>
> However, it looks like it doesn't allow us to express constraints that
> elate two or more associated types together, such as requiring both to have
> the same Element type.
>
>
> Did I miss something? I thought that was the exact example given in the
> motivation section?
>
>
> You are right.  I'm not sure how I missed that.  I think it is because the
> constraints are attached to a single associatedtype declaration rather than
> being at the top level of the protocol declaration.
>
> It feels slightly awkward to have to attach such constraints to one of the
> associatedtype declarations as they are effectively peers in the same type
> constraint.  Allowing such constraints to stand alone would look similar to
> Doug's example in the issues section.  I would prefer to look for a syntax
> for generic constraints on declarations that allows for freestanding and
> refined constraints in protocols.
>
>
> -Thorsten
>
>  I think it would be a good idea to solve the general problem of
> constraining associated types if possible.  The general case is an
> important part of completing generics IMO so it should be within the scope
> of Swift 3 to consider it.
>
> Matthew
>
> Sent from my iPad
>
> On Apr 24, 2016, at 3:34 PM, David Hart via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I wrote the proposal which was discussed to introduce generic constraints
> for associated types. I’d like to get some feedback on it and get it ready
> before submitting it:
>
> More Powerful Constraints for Associated Types
>
>    - Proposal: SE-XXXX
>    <https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md>
>    - Author(s): David Hart <http://github.com/hartbit>
>    - Status: *TBD*
>    - Review manager: TBD
>
>
> <https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md#introduction>
> Introduction
>
> This proposal seeks to introduce a where expression to associated types
> declarations to bring the same expressive power as generic type constraints.
>
> *This proposal was discussed on the Swift Evolution list in
> the [swift-evolution] [Completing Generics] Arbitrary requirements in
> protocols
> <http://thread.gmane.org/gmane.comp.lang.swift.evolution/14243> thread.*
>
> <https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md#motivation>
> Motivation
>
> Currently, associated type declarations can only express simple
> inheritance constraints and not the more sophisticated constraints
> available to generic types with the where expression. Some designs,
> including many in the Standard Library, require more powerful constraints
> for associated types to be truly elegant. For example, the SequenceType protocol
> can be declared as follows:
>
> protocol Sequence {
>     associatedtype Iterator : IteratorProtocol
>     associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
>     ...
> }
>
>
> <https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md#detail-design>Detail
> Design
>
> With this proposal, the grammar for protocols associated types would be
> modified to:
>
> *protocol-associated-type-declaration* → *attributesopt*
> *access-level-modifieropt* *associatedtype* *typealias-name*
> *­type-inheritance-clause­opt­* *typealias-assignment­opt*
> *requirement-clauseopt*
>
> The new requirement-clause is then used by the compiler to validate the
> associated types of conforming types.
>
> <https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md#issues>
> Issues
>
> Douglas Gregor argues that the proposed syntax is redundant when adding
> new constraints to an associated type declared in a parent protocol and
> proposes another syntax:
>
> protocol Collection : Sequence {
>     where SubSequence : Collection
> }
>
> But as Douglas notes himself, that syntax will become ambiguous if we
> adopt the generic where expression at the end of declarations like
> discussed in the following thread:
> http://thread.gmane.org/gmane.comp.lang.swift.evolution/13886/focus=14058.
> For those reasons, it might be wiser not to introduce the shorthand syntax.
>
> <https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md#acknowledgements>
> Acknowledgements
> Thanks to Dave Abrahams and Douglas Gregor for taking the time to help me
> through this proposal.
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160425/0b398ec4/attachment.html>


More information about the swift-evolution mailing list