Skip to content

RequirementMachine: Implement some generic signature queries #38147

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

Merged
merged 18 commits into from
Jun 30, 2021

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Jun 29, 2021

This PR implements the following queries on top of the rewrite system:

  • requiresClass()
  • getLayoutConstraint()
  • requiresProtocol()
  • getRequiredProtocols()
  • isConcreteType()
  • areSameTypeParametersInContext()

All but the last one of the above queries are implemented using the "equivalence class map", which is described below. The areSameTypeParametersInContext() query is implemented directly by reducing the left hand side and right hand side, and then comparing the reduced terms for equality.

In asserts builds, the -enable-requirement-machine flag cross-checks the result of each query against the old implementation of the query that uses the GSB. In no-asserts builds, the requirement machine result is returned without checking when the flag is enabled.

In both asserts and no-asserts builds, the flag is off by default, and the new code does not run when the flag is not passed in.

The equivalence class map

In the rewrite system, a conformance requirement T : P is represented as rewrite rule of the form:

T.[P] => T

Similarly, layout, superclass, and concrete-type requirements are represented by a rewrite rule of the form:

T.[p] => T

Where [p] is a "property atom": [layout: L], [superclass: Foo], [concrete: Bar].

Given an arbitrary type T and a property [p], we can check if T satisfies the property by checking if the two terms T.[p] and T reduce to the same term T'. That is, if our rewrite rules allow us to eliminate the [p] suffix, we know
the type satisfies [p].

However, the question then becomes, given an arbitrary type T, how do we find all properties [p] satisfied by T?

The trick is that we can take advantage of confluence here.

If T.[p] => T', and T => T'', then it must follow that T''.[p] => T'. Furthermore, since T'' is fully reduced, T'' == T'. So T'' == UV for some terms U and V, and there exist be a rewrite rule V.[p] => V' in the system.

Therefore, in order to find all [p] satisfied by T, we start by fully reducing T, then we look for rules of the form V.[p] => V' where V is fully reduced, and a suffix of T.

This is the idea behind the equivalence class map. We collect all rules of the form V.[p] => V' into a multi-map keyed by V. Then given an arbitrary type T, we can reduce it and look up successive suffixes to find all properties [p] satisfied by T.

The `if (other.size() > size())` check was bogus; we can still have an
overlap of the second kind if the other term is longer than this term.

Remove this check, and rewrite the algorithm to be clearer in general.
@slavapestov slavapestov force-pushed the requirement-machine-queries branch from 37440c4 to 0bdeb98 Compare June 29, 2021 03:35
@slavapestov slavapestov requested review from CodaFi and DougGregor June 29, 2021 03:37
If you have a same-type requirement like 'Self.Foo == Self' inside a
protocol P, we add a rewrite rule:

[P].Foo => [P]

Simplification turns this into

[P:Foo] => [P]

Previously, the order was backwards so we would end up with

[P] => [P:Foo]

Which would mess up the conformance information in the equivalence class map.
@slavapestov slavapestov force-pushed the requirement-machine-queries branch from 0bdeb98 to f7a1d06 Compare June 29, 2021 17:10
@slavapestov slavapestov force-pushed the requirement-machine-queries branch from f7a1d06 to 8ffe44f Compare June 30, 2021 05:34
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please clean smoke test macOS

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test macOS

@slavapestov
Copy link
Contributor Author

swiftlang/llvm-project#3065
@swift-ci Please smoke test macOS

@slavapestov slavapestov merged commit f44d1f7 into swiftlang:main Jun 30, 2021
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