[Pitch 2] Light-weight same-type requirement syntax

It might have to be on the maintainers’ side, though. Depends on why you want to support older tools. If clients are willing to update secondary tools as long as they don’t have to update the compiler and thus potentially their own code, then yeah, a client-side build step is fine. Otherwise it’s just as much of an imposition. I don’t think a general downgrade tool is likely to be small enough that people could just check it into their source trees.

1 Like

I see. But why not choose a simpler solution that does not require source rewriting and complex packaging solutions?

I would not advise looking for an SPM-only solution. There are other packaging systems in the eco-system, such as CocoaPods and Carthage, with many years of maturity, that SPM can not always fully replace. Opposing packaging systems is the last of our needs.

4 Likes

Spent some time with a recent snapshot and was really pleased with the experience! Great work, everyone! :smile:

One thing that came up was that composed protocols don't seem to be supported. E.g., should this work?

func f() -> some (A<Int> & B<Int>) { … }

This also made me wonder if "generic" type aliases should support primary associated types. E.g.:

typealias C<T> = (A<T> & B<T>)

func f() -> some C<Int> { … }

If so (or not), it would definitely be nice for the pitch to address things.

Edit: One other question is how does one document a primary associated type? Sequence can document Element as:

A type representing the sequence's elements.

But if it were redefined as Sequence<Element>, where would this documentation go?

7 Likes

Yeah, that doesn't work today because of implementation limitations. It's considered a bug.

Yep, that's another limitation I need to address.

I guess you would need to document it as part of the protocol itself, just as concrete types document their generic parameters.

2 Likes

This is how the documentation of associated types is currently accessible:

The typealias Element = Element makes it sound like you could maybe do something like this?

protocol Collection<Element> {
  /// A type representing the sequence's elements.
  typealias Element = Element

  ...
}

You're seeing the typealias Element inside the Array type, not the associated type in the protocol. Re-declaring a typealias with the same name as a (primary) associated type in the protocol should probably not be legal, because then it introduces an ambiguity in name lookup. The same scenario is not a problem for concrete types, because the generic parameter 'Element' on the right hand side of 'typealias Element = Element' is not semantically a member of Array; if it weren't for that typealias, I could not write 'Array.Element' to access the generic parameter.

2 Likes

Ah, is this something the compiler does automatically for concrete types that conform to protocols? There doesn't seem to be an explicit typealias in the source code for Array.

Yeah. An associatedtype constraint is a constraint that a member type exists, and a declaration for it is added if the associated type is inferred from witnesses.

1 Like

This is needed. SE-0358 documents the difficulty that will sometimes occur when choosing a primary associated type:

Unless "does not" is changed to "will never be able to"…

…I'd wait for that to get fixed, rather than potentially making a wrong choice that can never be corrected.

LazySequenceProtocol<Element: Int>
LazySequenceProtocol<Elements: [Int]>
3 Likes