The RequirementSignature generalizes the old ArrayRef<Requirement>
which stores the minimal requirements that a conforming type's
witnesses must satisfy, to also record the protocol typealiases
defined in the protocol.
Introduces rewrite rules for typealiases defined inside the protocol
itself.
Typealiases defined in protocol extensions do not participate
in the rewrite system, except for when they have the same name as
an associated type, as per the weird rule codified in the
TypeAliasRequirementsRequest for GSB compatibility.
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.
There are two kinds of protocol typealiases:
1) The underlying type is a type parameter. These rules look like
[P].A => X where X is the underlying type.
2) The underlying type is a concrete type. These rules look like
[P].A.[concrete: C] => [P].A.
The isProtocolTypeAliasRule() predicate detects both cases and
returns the type alias name ('A', in the above examples). For now
it's not used anywhere, since we don't actually introduce these
rules for any reason.
We want a term with more name symbols to order after a term with
fewer name symbols, even if the term with more name symbols is
shorter. That is,
[P].A > [P:X].[Q:Y].[R:Z]
This is in support of handling protocol typealiases.
I'm about to change the reduction order so that terms with more
name symbols always order after terms with fewer name symbols,
so for example
[P].A > [P:T].[Q:U].[R:V]
This will be used to implement protocol typealiases.
These come up in SIL and in the experimental named opaque result types
implementation. Pass the correct DeclContext here, instead of using
the ModuleDecl.
In the long run it doesn't really matter if we leave them in there, but for now
matching the GenericSignatureBuilder's behavior makes the tests pass with
-requirement-machine-inferred-signatures=verify.
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.
This logic was tricky and unsound.
Correct handling of concrete conformances requires rebuilding the
signature after dropping protocol conformance requiremnts made
redundant by concrete type requirements.
The old support for "derived-via-concrete" requirements in the
minimal conformances algorithm was causing other problems, and it
is the wrong approach anyway, so just remove it.
We can't actually rely on concretelySimplifyLeftHandSideSubstitutions()
to do this for us, because the less-simplified rule (the LHS rule)
might only apply to a suffix of the base term.
- Rename StepLimit to MaxRuleCount, DepthLimit to MaxRuleLength
- Rename command line flags to -requirement-machine-max-rule-{count,length}=
- Check limits outside of PropertyMap::buildPropertyMap()
- Simplify the logic in RequirementMachine::computeCompletion()
This doesn't record rewrite loops from most concrete unifications just yet,
only handling a case where two concrete types were identical except for an
adjustment.