Remove the logic which incorrectly attempted to simulate the
GenericSignatureBuilder's minimization behavior in the presence
of conflicts, since it doesn't matter anymore.
Preserves concrete type rules on associated types that were derived
from rules indirectly formed from protocol typealias rules.
That is, if you have a pair of rules in another minimization domain:
[P].A.[concrete: C] => [P].A
[Q:T].[P] => [Q:T]
Then completion will introduce a new rule:
[Q:T].A.[concrete: C] => [Q:T].A
Since this rule is outside of our minimization domain, we don't record
a rewrite loop for it, and it will never become redundant.
Now if we have a rule in our own minimization domain:
T.[Q:T].A => T.[Q:U]
Then we get a new rule:
T.[Q:U].[concrete: C] => T.[Q:U]
Make sure we keep this rule around on account of it being derived from
([Q:T].A.[concrete: C] => [Q:T].A).
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.
rules in a separate pass after homotopy reduction.
RewriteSystem::propagateExplicitBits was too eager in propagating
IDs from explicit rules within rewrite loops, which resulted in bogus
redundancy warnings when the canonical form of an explicit rule was
given a different requirement ID. Instead, propagate requirement IDs
after homotopy reduction when redundant rules are computed and rewrite
loops are simplified.
rewrite system.
This ID can be used to index into the WrittenRequirements array in the
rewrite system to retrieve the structural requirement, e.g. for the
purpose of diagnostics.
Distinguish a loop with elimination candidates, which are rules
appearing in empty context and exactly once, from a useful loop,
which contains at least one rule in empty context (but the same
rule might appear more than once).
Normalizing a useful loop might produce a loop with elimination
candidates, but normalizing a useless loop never does.
We want to prefer explicit rules when an explicit rule and non-explicit
rule conflict. Since the explicit bit hasn't been computed yet when
building the property map, save conflicting rule pairs in a side table,
and then process them later in homotopy reduction.
The side table will also be useful for diagnostics later.
Now that we can detect protocol typealias rules, collect and keep
track of them so that they can be recorded in protocol requirement
signatures.
For now, this is all NFC since nothing introduces such rules into
the rewrite system, except for invalid requirements which are
diagnosed anyway.
We want to prefer to eliminate rules that are not concrete type rules,
unless non-concrete type rule in question is a projection. For example,
suppose that this rule comes from a protocol:
T.T == G<T.U, T.V>
And these three rules are in our minimization domain:
a) T.T == G<Int, W>
b) T.U == Int
c) T.V == W
Then a) implies both b) and c), and vice versa.
In this case, we want to keep T.U == Int and T.V == W, and eliminate
T.T == G<Int, W>.
T.T == G<Int, W> is concrete and T.V == W is not, but because T.V == W
is defined by a projection, we still prefer to eliminate T.T == G<Int, W>
over T.V == W.
We have three simplification passes, give each one its own predicate:
- Left hand side simplification
- Right hand side simplification
- Substitution simplification
This is for debugging output and will also allow me to tighten up
some invariants.
We can end up with two redundant concrete type rules on the same
term, but we would crash in homotopy reduction because the rules
were incomparable due to the concrete type symbol at the end.
If one of them is conflicting though, we don't really care about
the homotopy reduction order, so skip the check if the other
rule was already marked conflicting.