Skip to content

Conversation

@simanerush
Copy link
Member

@simanerush simanerush commented Dec 5, 2023

Resolves rdar://131630764.

This is the continuation of the original PR #67465 since I hope to fix the CI errors to be able to land the changes.

  • Fix CI errors
  • Address review feedback
  • Support concrete same-type requirements?

From the original PR:
SE-0393 supports same-element requirements. From the proposal:

A same-type requirement where one side is a type parameter pack and the other type is a scalar type that does not capture any type parameter packs is interpreted as constraining each element of the replacement type pack to the same scalar type:

func variadic<each S: Sequence, T>(_: repeat each S) where repeat (each S).Element == T {}

This is called a same-element requirement.

We represent pack elements in the requirement machine through a new singleton PackElement symbol, written [element]. Same-element requirements are mapped to re-write rules that prefix type parameter pack terms with the [element] symbol.

For example, given a protocol P with an associated type A, the generic signature <each T, U> where repeat each T: P, repeat (each T).A == U maps to the following re-write system:

Rewrite system: {
- [P].[P] => [P]
- [P].A => [P:A]
- [P].[P:A] => [P:A]
- [P:A].[shape] => [shape]
- τ_0_1.[shape] => [shape]
- each τ_0_0.[P] => each τ_0_0
- [element].each τ_0_0.A => τ_0_1
- each τ_0_0.A => each τ_0_0.[P:A]
- [element].each τ_0_0.[P:A] => τ_0_1
- [element].each τ_0_0.[shape] => [shape]
}

The implementation is gated behind -enable-experimental-feature SameElementRequirements because the minimal conformance computation doesn't yet support same-element requirements. The current rewrite rules also do not support deriving pack element conformance from a scalar type parameter conformance through same-element requirements. For example, the generic signature <each T, U> where U: P, repeat each T == U maps to the following rewrite system:

Rewrite system: {
- [P].[P] => [P]
- [P].A => [P:A]
- [P].[P:A] => [P:A]
- [P:A].[shape] => [shape]
- τ_0_1.[shape] => [shape]
- τ_0_1.[P] => τ_0_1
- [element].each τ_0_0 => τ_0_1
- τ_0_1.A => τ_0_1.[P:A]
}

The conformance rule τ_0_1.[P] => τ_0_1 and the same-element rule [element].each τ_0_0 => τ_0_1 do not provide a rewrite path to the pack conformance rule each τ_0_0.[P] => each τ_0_0. One possible solution is to use element symbols for all property rules, which would also allow the minimal conformance support to fallout naturally. However, this approach poses a problem for same-type-pack requirements. If we use [element] symbols for same-type-pack requirements, e.g. [element].each τ_0_0 => [element].each τ_0_1, then this rule no longer implies a same-shape rule each τ_0_0.[shape] => each τ_0_1.[shape]. Stripping the [element] symbols from same-type-pack rewrite rules creates a different set of problems for conformances, because the pack conformance rules contain [element] symbols, which would prohibit applying associated type rewrite rules to non-element pack terms. I'm still exploring strategies for resolving these issues, hence the experimental flag!

@simanerush simanerush force-pushed the same-element-requirements branch 3 times, most recently from 63a701c to 147c2b9 Compare January 12, 2024 01:02
@swiftlang swiftlang deleted a comment from AnthonyLatsis Jan 12, 2024
@simanerush simanerush force-pushed the same-element-requirements branch 2 times, most recently from 9d3be68 to 2ae722f Compare January 14, 2024 23:06
@simanerush
Copy link
Member Author

@swift-ci please clean smoke test

@martialln
Copy link

Thank you for continuing the work on this feature !

Does this PR will also allow construct like this:

protocol P {
    associatedtype A
}
struct Foo<each T> {
    func bar<each S: P>(s: repeat each S) 
        where repeat (each S).A == each T /* or something like (repeat (each S).A) == (repeat each T)*/ 
    { /**/ }
}

?

@simanerush
Copy link
Member Author

@martialln Yes, this construct will be allowed🙂

@simanerush simanerush force-pushed the same-element-requirements branch from 2ae722f to a2b97a8 Compare February 5, 2024 05:41
@simanerush simanerush marked this pull request as ready for review February 11, 2024 07:25
@simanerush simanerush force-pushed the same-element-requirements branch from cc9030a to 7d4eebf Compare February 12, 2024 00:59
@simanerush
Copy link
Member Author

@swift-ci Please smoke test

@AnthonyLatsis
Copy link
Collaborator

@swift-ci Please smoke test macOS

@simanerush simanerush requested a review from hborla February 19, 2024 23:23
@shaps80
Copy link

shaps80 commented Apr 22, 2024

Amazing to see this making progress. Just curious when we might see this available? Thanks!

@simanerush
Copy link
Member Author

@shaps80 Currently, this implementation is missing concrete same-element requirements, and unfortunately I can't provide an estimate of when this will be ready.
cc @slavapestov

@shaps80
Copy link

shaps80 commented Apr 24, 2024

Ok fair enough. Thanks for letting me know

@Lancelotbronner
Copy link

Will this be part of Swift 6?

@vanvoorden
Copy link
Contributor

struct Variadic<each T> {}

extension Variadic where T == {Int, String} {} // {Int, String} is a concrete pack

extension Variadic where T == Never {} // client passed no parameter pack

Hi! I'm looking for (someday in the future) using something like this to enable an "optional" parameter pack. Do we think this diff would also implement the "Explicit type pack syntax" from SE-03931 or would that land in another diff? Thanks!

Footnotes

  1. https://github.com/swiftlang/swift-evolution/blob/main/proposals/0393-parameter-packs.md#explicit-type-pack-syntax

@simanerush simanerush force-pushed the same-element-requirements branch from 17fc634 to 5893cf6 Compare July 12, 2024 18:40
@simanerush simanerush requested a review from DougGregor as a code owner July 12, 2024 18:40
@simanerush
Copy link
Member Author

@swift-ci please smoke test

@simanerush simanerush force-pushed the same-element-requirements branch from 5893cf6 to f4e8a40 Compare July 12, 2024 19:43
@simanerush
Copy link
Member Author

@swift-ci please smoke test

@simanerush simanerush force-pushed the same-element-requirements branch from f4e8a40 to c5daf7d Compare July 12, 2024 20:17
@simanerush
Copy link
Member Author

@swift-ci please smoke test

@simanerush
Copy link
Member Author

@swift-ci please smoke test macOS

@simanerush simanerush force-pushed the same-element-requirements branch from c5daf7d to 0dc6719 Compare July 15, 2024 17:19
@simanerush
Copy link
Member Author

@swift-ci please smoke test

@dehesa
Copy link

dehesa commented Aug 5, 2024

We are hitting this limitation constantly at raycast. We would jump of joy if it could reach Swift 6 by this September 😆

In any case, thank you for working on this.

@hborla
Copy link
Member

hborla commented Aug 5, 2024

We are hitting this limitation constantly at raycast. We would jump of joy if it could reach Swift 6 by this September

This change will not be included in Swift 6. I understand that people are hitting this limitation frequently and would like for it to be lifted, but there are still open technical challenges with this change. As noted in the PR description, the implementation is gated behind an experimental flag because there are issues with how same-element requirements are represented that we're not happy with. These issues impact the user-facing semantics; they're not just implementation challenges.

@hborla
Copy link
Member

hborla commented Aug 5, 2024

@swift-ci please smoke test

@dehesa
Copy link

dehesa commented Aug 5, 2024

I see! Thank you for the openness and setting expectations. I am sad to hear it won’t be there for Swift 6, but if it is not ready, it is not ready 😅
I just wanted to express my strong interest in this feature and my love for the new variadic generics.

@slavapestov
Copy link
Contributor

@simanerush IMO we should merge this with the user-visible requirement desugaring change behind an experimental flag.

@simanerush simanerush merged commit 6400a29 into swiftlang:main Aug 6, 2024
@simanerush simanerush deleted the same-element-requirements branch August 6, 2024 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants