A type parameter subject to an AnyObject requirement might also be subject
to a concrete type requirement. There are two cases to handle here:
- If the concrete type is a class, the layout requirement is redundant.
- If the concrete type is not a class, we have a conflict.
There is an existing test that's good enough; I just changed it to
run with -requirement-machine-inferred-signatures=verify.
It doesn't actually do this yet, but the idea is to look at the
total rule count before and after, instead of just looking at the
induced rules array (which I will delete in the next commit).
Conditional requirement inference needs to be able to add rewrite rules
from the requirement signatures of hitherto-unseen protocols, so to
help with that, extract out the RuleBuilder's ProtocolMap and move it
into the RewriteSystem.
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.
This will replace the 'concrete type in domain' hack. Instead of
finding some other type parameter with the same concrete type and a
compatible starting symbol, this finds a prefix of the original
term. This allows the induced same-type requirement to be described
with a rewrite path.
When minimizing a generic signature, we only care about loops
where the basepoint is a generic parameter symbol.
When minimizing protocol requirement signatures in a connected
component, we only care about loops where the basepoint is a
protocol symbol or associated type symbol whose protocol is
part of the connected component.
All other loops can be discarded since they do not encode
redundancies that are relevant to us.
A superclass requirement 'T : C' implies a layout requirement
'T : AnyObject' (if the class is @objc) or 'T : _NativeObject'
(if the class is not @objc).
In the latter case, there might already be a 'T : AnyObject'
requirement, in which case the type parameter 'T' is subject
to two layout requirements:
T : AnyObject
T : _NativeObject
The second requirement implies the first however. To encode this
in the world of rewrite loops, we the notion of a 'relation'
between property symbols, and a 'Relation' rewrite step.
Here, the relation is that _NativeObject < AnyObject. Once this
relation is recorded, the Relation rewrite step will transform
T.[layout: _NativeObject].[layout: AnyObject]
into
T.[layout: _NativeObject]
and vice versa.
This rewrite step allows us to construct a rewrite loop which
makes the first rewrite rule redundant via the second.
Using the qualified name is subtly different from scoping the function.
Use the latter, which correctly places the function into the namespace,
to enable building with VS2022.
First pass:
- Eliminate rules with unresolved name symbols in LHS
- Eliminate simplified non-conformance rules
Second pass:
- Eliminate non-minimal conformance rules
Third pass:
- Eliminate all other non-conformance rules
If you have a concrete requirement with a non-canonical substitution, like
A : P, A == G<B.T>
We add an induced rule for the abstract type witness,
A.T == B.T
This rule has a rewrite path in terms of the previous two rules, but we
want to try to eliminate the other two rules first.
This new ordering ensures we eliminate the simplified rule A == G<B.T> and
compute minimal conformances before we get around to considering A.T == B.T,
which can no longer be eliminated by that point.
If we eliminate A.T == B.T first, we end up with simplified concrete
type and concrete conformance rules which cannot be eliminated:
A.[concrete: G<B.T>] => A
A.[concrete: G<B.T> : P] => A
This changes the minimized signature in an incompatible way in two test cases.
In Generics/rdar83308672.swift, the signature becomes equivalent to what the
GSB used to output.
In Generics/sr10532.swift, the GSB would output an invalid signature anyway,
so it doesn't matter.