Commit Graph

28 Commits

Author SHA1 Message Date
Slava Pestov
b999cea0f7 RequirementMachine: Try to minimize away concrete conformances first 2021-12-08 00:53:35 -05:00
Slava Pestov
96bdef9f50 RequirementMachine: Move generating conformances algorithm into its own class 2021-12-08 00:53:35 -05:00
Slava Pestov
86c15ad5c1 RequirementMachine: Generating conformances can reason about concrete conformances now 2021-12-08 00:53:35 -05:00
Slava Pestov
0686cd5aef RequirementMachine: Better assertions for generating conformances 2021-12-08 00:53:35 -05:00
Slava Pestov
2f2249cef1 RequirementMachine: Fix various RewriteSteps to work when re-contextualized
When a rewrite rule is replaced with a path containing ::Adjust, ::Decompose,
::ConcreteConformance or ::SuperclassConformance rewrite steps, the steps
will get a non-zero EndOffset if the original rule appears in a step with a
non-zero EndOffset.

For this reason, these steps must work with a non-zero EndOffset, which
primarily means computing correct offsets into the term being manipulated.
2021-12-08 00:53:35 -05:00
Slava Pestov
34cbfd23a5 RequirementMachine: Don't assert if a rewrite system has unresolved rules
This is a source-level error, not an invariant violation. Instead, plumb
a new hadError() flag, which in the future will assert if no diagnostic
was produced.
2021-12-08 00:53:34 -05:00
Slava Pestov
8e7a9b0f9f RequirementMachine: Add a couple of histograms 2021-12-07 15:31:47 -05:00
Slava Pestov
7427b68785 RequirementMachine: Introduce RewriteStep::ConcreteConformance and ::SuperclassConformance 2021-12-06 23:04:46 -05:00
Slava Pestov
e9b94c1bf1 RequirementMachine: Move some methods from RewriteStep to RewritePathEvaluator
This better encapsulates the evaluator state into a single struct.
2021-12-06 23:04:46 -05:00
Slava Pestov
d19b15b66c RequirementMachine: Introduce Symbol::Kind::ConcreteConformance 2021-12-06 23:04:46 -05:00
Slava Pestov
2c4cfdcb1f RequirementMachine: Generating conformances prefers to delete non-explicit rules
This is a heuristic to ensure that conformance requirements remain in
their original protocol if possible, when the protocol is part of a
connected component consisting of multiple protocols.
2021-11-10 00:18:57 -05:00
Slava Pestov
1057b56395 RequirementMachine: Rename HomotopyGenerator to RewriteLoop
Also, stop talking about 2-cells and 3-cells.
2021-10-27 01:28:24 -04:00
Slava Pestov
c0154d4d4e RequirementMachine: Try to delete less canonical conformance rules first
Just like in homotopy reduction, when finding a minimal set of generating
conformances, we should try to eliminate less canonical conformance rules
first.

This fixes a test case where we would delete a more canonical conformance
requirement, triggering an assertion that simplifed rules must be
redundant, because the less canonical conformance was simplified, whereas
the more canonical one was redundant and not simplified.
2021-10-27 01:28:24 -04:00
Slava Pestov
2687e93800 RequirementMachine: Proper handling of identity conformances when computing generating conformances
Consider this example:

  protocol P {
    associatedtype X : P where X == Self
  }

Clearly the conformance requirement 'X : P' is redundant, but previously
nothing in our formulation would make it so.

Here is the rewrite system:

  (1) [P:X].[P] => [P:X]
  (2) [P:X] => [P]

These two terms overlap on [P:X].[P]; resolving the critical pair introduces
the 'identity conformance' [P].[P] => [P]. Homotopy reduction would delete
this conformance, but at this point, [P:X].[P] => [P:X] would no longer be
redundant, since nothing else proves that [P].[P] => [P].

Now that [P].[P] => [P] is a permanent rule, we can handle this properly;
any conformance that appears in a rewrite loop together with an identity
conformance without context is completely redundant; it is equivalent to the
empty generating conformance path.
2021-10-27 00:44:26 -04:00
Slava Pestov
745acea7ce RequirementMachine: Introduce Rule::isIdentityConformanceRule() 2021-10-27 00:39:07 -04:00
Slava Pestov
a8bc8a86fb RequirementMachine: Add assertion to generating conformances algorithm 2021-10-27 00:38:35 -04:00
Slava Pestov
b01e97f2c6 RequirementMachine: Rewrite steps are instructions for a two-stack machine
I need to simplify concrete substitutions when adding a rewrite rule, so
for example if X.Y => Z, we want to simplify

  A.[concrete: G<τ_0_0, τ_0_1> with <X.Y, X>] => A

to

  A.[concrete: G<τ_0_0, τ_0_1> with <Z, X>] => A

The requirement machine used to do this, but I took it out, because it
didn't fit with the rewrite path representation. However, I found a case
where this is needed so I need to bring it back.

Until now, a rewrite path was a composition of rewrite steps where each
step would transform a source term into a destination term.

The question then becomes, how do we represent concrete substitution
simplification with such a scheme.

One approach is to rework rewrite paths to a 'nested' representation,
where a new kind of rewrite step applies a sequence of rewrite paths to
the concrete substitution terms. Unfortunately this would complicate
memory management and require recursion when visiting the steps of a
rewrite path.

Another, simpler approach that I'm going with here is to generalize a
rewrite path to a stack machine program instead.

I'm adding two new kinds of rewrite steps which manipulate a pair of
stacks, called 'A' and 'B':

- Decompose, which takes a term ending in a superclass or concrete type
  symbol, and pushes each concrete substitution on the 'A' stack.

- A>B, which pops the top of the 'A' stack and pushes it onto the 'B'
  stack.

Since all rewrite steps are invertible, the inverse of the two new
step kinds are as follows:

- Compose, which pops a series of terms from the 'A' stack, and replaces
  the concrete substitutions in the term ending in a superclass or
  concrete type symbol underneath.

- B>A, which pops the top of the 'B' stack and pushes it onto the
  'B' stack.

Both Decompose and Compose take an operand, which is the number of
concrete substitutions to expect. This is encoded in the RuleID field
of RewriteStep.

The two existing rewrite steps ApplyRewriteRule and AdjustConcreteType
simply pop and push the term at the top of the 'A' stack.

Now, if addRule() wishes to transform

  A.[concrete: G<τ_0_0, τ_0_1> with <X.Y, X>] => A

into

  A.[concrete: G<τ_0_0, τ_0_1> with <Z, X>] => A

it can construct the rewrite path

  Decompose(2) ⊗ A>B ⊗ <<rewrite path from X.Y to Z>> ⊗ B>A ⊗ Compose(2)

This commit lays down the plumbing for these new rewrite steps, and
replaces the existing 'evaluation' walks over rewrite paths that
mutate a single MutableTerm with a new RewritePathEvaluator type, that
stores the two stacks.

The changes to addRule() are coming in a subsequent commit.
2021-10-27 00:11:16 -04:00
Slava Pestov
3ee99d6619 RequirementMachine: NFC cleanups for generating conformances 2021-10-09 19:11:15 -04:00
Slava Pestov
94e9ab6713 RequirementMachine: Track parent paths when computing generating conformances 2021-10-08 14:28:27 -04:00
Slava Pestov
b47b2d3b03 RequirementMachine: Fix generating conformances 2021-10-08 14:28:27 -04:00
Slava Pestov
70233aceb7 RequirementMachine: Teach generating conformances to understand protocol refinement
For implementation reasons we want the requirement signature of a
protocol to directly include all protocol refinement relationships,
even if they can be derived via same-type requirements between Self
and some nested type.

Therefore, a protocol refinement rule [P].[Q] => [P] can only be
replaced with a generating conformance equation that consists
entirely of other conformance rules.

This exactly simulates the existing behavior of the GSB's redundant
requirements algorithm.
2021-10-08 14:28:27 -04:00
Slava Pestov
371366eb4b RequirementMachine: Assert that non-redundant rules are fully resolved 2021-10-08 14:28:27 -04:00
Slava Pestov
62de909801 RequirementMachine: Some comments 2021-10-06 00:20:18 -04:00
Slava Pestov
acb12fa750 RequirementMachine: More complete implementation of findProtocolConformanceRules() 2021-10-06 00:11:21 -04:00
Slava Pestov
62c9347d3b RequirementMachine: Overhaul generating conformances algorithm 2021-10-01 00:57:44 -04:00
Slava Pestov
86ee6c2f55 RequirementMachine: Add some comments 2021-10-01 00:56:50 -04:00
Slava Pestov
34592cb2fa RequirementMachine: Fix generating conformances algorithm for rules of the form [P].[P] => [P] 2021-10-01 00:56:50 -04:00
Slava Pestov
64d1931e15 RequirementMachine: Sketch out "generating conformances" algorithm 2021-09-27 19:04:16 -04:00