Skip to content

RequirementMachine: Overhaul handling of protocol typealiases with concrete underlying type #41773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Mar 10, 2022

Consider this example:

protocol P {
  typealias A = Int
  associatedtype B
}

<T where T : P, T.A == T.B>

Recall that the concrete typealias introduces a rule of the form:

[P].A.[concrete: Int] => [P].A

This overlaps with the conformance rule (T.[P] => T) on the term T.[P].A to produce the rule T.A.[concrete: Int] => T.A.

Now the generic signature equates the associated type T.[P:B] with the typealias T.A via an abstract same-type requirement, which introduces a rewrite rule of the form:

T.A => T.[P:B]

This overlaps with T.A.[concrete: Int] => T.A on T.A.[concrete: Int], so we get a new rule:

T.[P:B].[concrete: Int] => T.[P:B]

For compatibility with the GenericSignatureBuilder, this final rule is the one we want to turn into a requirement in the minimal signature (T.B == Int); we don't want to keep (T.B == T.A) around.

To get this behavior, don't consider eliminating (T.[P:B].[concrete: Int] => T.[P:B]) via a rewrite loop containing any protocol typealias rules, in this case, ([P].A.[concrete: Int] => [P].A).

This trick only works because the left hand side of a protocol typelias rule is always greater than an associated type in the reduction order, since terms with name symbols are always greater than terms without name symbols.

There is a more general problem here where we fail to produce a signature compatible with the GenericSignatureBuilder in other similar cases that do not involve protocol typealiases, for example here we should transform U.Element == Character:

<T, U where T : Collection, U : Collection, T.SubSequence == Substring, T.Element == U.Element>

A solution to the above problem will subsume this hack, but for now, let's land it to move forward.

Fixes https://bugs.swift.org/browse/SR-15924 / rdar://problem/89641526.

@slavapestov slavapestov force-pushed the rqm-concrete-protocol-typealias-minimization branch from 355f538 to 8b61863 Compare March 10, 2022 21:46
Add a separate pass to consider rules with unresolved names which are
not simplified.
…tocol typealias rule

If a rule is not a protocol typealias rule, and does not contain any unresolved
symbols, do not attempt to eliminate it via a protocol typealias rule.

This fixes a bunch of cases where the RequirementMachine was overly-eager to
remove rules.
@slavapestov slavapestov force-pushed the rqm-concrete-protocol-typealias-minimization branch from d025bb9 to 1f83cd0 Compare March 11, 2022 22:28
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test Linux

2 similar comments
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test Linux

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test Linux

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.

1 participant