Commit Graph

873 Commits

Author SHA1 Message Date
Holly Borla
7ce6504b93 [RequirementMachine] Avoid passing the requirement error vector through
initialization of the rewrite system.

Instead, the rewrite system can determine trivially redundant requirements
by finding structural requirements with no associated rewrite rules.
2022-03-10 13:13:50 -08:00
Holly Borla
0085eb0dfe [RequirementMachine] Separate setting the explicit bit and the requirement
ID for a rewrite rule.
2022-03-09 21:22:53 -08:00
Holly Borla
4b55c30fad [RequirementMachine] Instead of recording redundant requirements and other
diagnostics in the rewrite system, pass down the 'errors' vector from the
top-level requests.
2022-03-09 18:18:43 -08:00
Holly Borla
b5d7a0152b [RequirementMachine] Factor the 'rules once in empty context' computation out
into a method on RewritePath.
2022-03-09 16:17:55 -08:00
Holly Borla
2f7018b605 [RequirementMachine] Don't suppress redundancy diagnostics when the
non-explicit, non-redundant replacement rule is not in the rewrite
system's minimization domain.
2022-03-09 12:14:58 -08:00
Holly Borla
397684909b [RequirementMachine] Suppress redundancy warnings when an explicit, redundant
rule has a non-explicit, non-redundant rule in its rewrite path.

This fixes bogus redundancy diagnostics in cases where the canonical form
of a redundant rule is not explicit in source, e.g.

protocol Swappable2 {
  associatedtype A
  associatedtype B
  associatedtype Swapped : Swappable2
    where Swapped.B == A,
          Swapped.Swapped == Self
}

in the above case, the canonical rule for `Swapped.B == A` is the rule
[Swappable2:Swapped].[Swappable2:A] => [Swappable2:B], which is not
explicit.
2022-03-09 12:14:58 -08:00
Holly Borla
a154641288 [RequirementMachine] Propagate explicit requirement IDs from redundant
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.
2022-03-09 12:14:58 -08:00
Holly Borla
be30d76732 [RequirementMachine] Diagnose redundant requirements found during minimization
of the rewrite system.
2022-03-09 12:14:58 -08:00
Holly Borla
3c95cac5e8 [RequirementMachine] Store a requirement ID for explicit rules in the
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.
2022-03-09 12:14:58 -08:00
Holly Borla
b18e815436 [RequirementMachine] Preserve structural requirements during rule construction,
and diagnose trivially redundant rules in the rewrite system.
2022-03-09 12:14:58 -08:00
Slava Pestov
b6a641bc07 RequirementMachine: New way of introducing concrete conformance rules
Define the relation as

    [concrete: C].[P] =>> [concrete: C].[concrete: C : P]

instead of

    [concrete: C].[P] =>> [concrete: C : P]

This changes the rewrite loop recorded for a rule T.[concrete: C : P]
to have (T.[concrete: C] => T) appearing twice in context instead of
just once.

We don't ever want a concrete conformance rule to be able to imply a
concrete type rule. This became possible with loop normalization
because the single occurrence of (T.[concrete: C] => T).[P] could
cancel with a subsequent step (T => T.[concrete: C]).[P] in another
rewrite loop after substitution.
2022-03-08 23:21:58 -05:00
Slava Pestov
95f122f105 RequirementMachine: Add -enable-requirement-machine-loop-normalization flag 2022-03-08 22:47:22 -05:00
Slava Pestov
a0c3045709 RequirementMachine: Relax criterion for deleting a useless loop
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.
2022-03-08 22:47:22 -05:00
Slava Pestov
713e0a4a6d RequirementMachine: Reduce replacement paths for redundant rules to left-canonical normal form
This brings back the code I deleted in 1bf6102f1e
but repurposes it to simplify the replacement paths recorded for
redundant rewrite rules only.
2022-03-08 22:47:22 -05:00
Slava Pestov
86a4c9fdb0 RequirementMachine: Stricter invariants in RewriteSystem::verifyRewriteRules() 2022-03-07 23:20:41 -05:00
Slava Pestov
39d486a7fc RequirementMachine: Try to avoid introducing rules of the form T.[P] => T.[Q]
These rules would be fine since RHS simplification eliminates them,
but they cause problems for the minimal conformances algorithm.

To avoid introducing such rules, ensure that the critical pair of
two property-like rules is itself a property-like rule instead of
relying on subsequent simplifications sorting it out. See the
new comment in RewriteSystem::computeCriticalPair() for details.

I need to understand this problem better and either fix minimal
conformances or add stronger assertions, but for now this fixes
the last failure with -requirement-machine-abstract-signatures=verify.
2022-03-07 23:19:43 -05:00
Slava Pestov
0e4c398048 RequirementMachine: Tweak completion loop condition 2022-03-07 23:13:05 -05:00
Slava Pestov
69672ccfd2 RequirementMachine: Fix debug output 2022-03-07 23:13:05 -05:00
Holly Borla
80a2eee2bf [Diagnostics] Remove a few special cases of printing 'any' for specific
error messages.
2022-03-05 14:26:45 -08:00
Slava Pestov
64f049a3d8 RequirementMachine: Fix ConcreteContraction::substTypeParameter() for non-nominal base type
We can handle a non-nominal base type here as long as the DependentMemberType
we're substituting this into is resolved.
2022-03-03 14:05:02 -05:00
Slava Pestov
589c1a3c11 RequirementMachine: A couple of improvements to concrete contraction
- Allow duplicate concrete type and superclass requirements on the
  same generic parameter, as long as they're identical. This can
  arise if requirement inference infers a requirement which the
  user then explicitly re-states.

- If duplicate requirements are found that name different types, drop
  only that generic parameter from consideration without giving up
  entirely.

- If a generic parameter is subject to both a concrete type and a
  superclass requirement, proceed with the concrete type requirement
  since it is more specific instead of giving up.
2022-03-03 14:05:02 -05:00
Slava Pestov
0d094241d8 RequirementMachine: Fix rogue debug output when debug flag was disabled 2022-03-03 14:05:02 -05:00
Slava Pestov
517fb4568e RequirementMachine: Fix minimal conformances algorithm to cope with unordered concrete conformances 2022-03-03 14:05:02 -05:00
Slava Pestov
b497c790fa RequirementMachine: Check invariants in noassert builds 2022-03-03 14:05:02 -05:00
Slava Pestov
9c2d540e69 RequirementMachine: Check invariants using GenericSignature::verify()
Previously only the GenericSignatureBuilder would call this; to ensure
we get the same test coverage when the Requirement Machine is 'on' as
'verify', also call this from the Requirement Machine.

For now, we can't call this from RequirementSignatureRequestRQM due
to circularity issues; that will have to wait until this request is
folded into RequirementSignatureRequest.
2022-03-03 14:05:02 -05:00
Slava Pestov
bd5a437c39 Merge pull request #41615 from slavapestov/rqm-protocol-superclass-circular-conformance
RequirementMachine: Fix minimization when protocol is constrained to a class that conforms to the protocol
2022-03-02 12:17:12 -05:00
Slava Pestov
5281426569 RequirementMachine: Fix minimization when protocol is constrained to a class that conforms to the protocol
Consider this example:

    protocol P : C {}
    class C : P {}

    <T where T : P>

The GenericSignatureBuilder thinks the minimized signature is
<T where T : P>. The RequirementMachine would minimize it down to
<T where T : C>. The latter is more correct, since the conformance
here is concrete and no witness table needs to be passed in at
runtime, however for strict binary compatibility we need to produce
the same signature as the GenericSignatureBuilder.

Accomplish this by changing the minimal conformances algorithm to
detect "circular concrete conformance rules", which take the form

    [P].[concrete: C : Q]

Where Q : P. These rules are given special handling. Ordinarily a
protocol conformance rule is eliminated before a concrete conformance
rule; however concrete conformances derived from circular
conformances are considered to be redundant from the get-go,
preventing protocol conformances that can be written in terms of
such concrete conformances from themselves becoming redundant.

Fixes rdar://problem/89633532.
2022-03-02 03:13:41 -05:00
Slava Pestov
8570b5656c RequirementMachine: Fix compile error on Linux 2022-03-01 00:56:43 -05:00
Slava Pestov
d3c224bb26 RequirementMachine: RewriteSystem::hadError() should ignore rules outside our minimization domain 2022-02-28 18:43:53 -05:00
Slava Pestov
a57a418724 RequirementMachine: Make getTypeForSymbolRange() more robust when asserts are off 2022-02-28 18:42:30 -05:00
Slava Pestov
048a64d4c0 RequirementMachine: Tweak debug output and fix typo 2022-02-28 18:41:42 -05:00
Slava Pestov
8e09ba8b45 RequirementMachine: Introduce 'concrete contraction' pre-processing pass before building rewrite system
See the comment at the top of ConcreteContraction.cpp for a detailed explanation.

This can be turned off with the -disable-requirement-machine-concrete-contraction
pass, mostly meant for testing. A few tests now run with this pass both enabled
and disabled, to exercise code paths which are otherwise trivially avoided by
concrete contraction.

Fixes rdar://problem/88135912.
2022-02-25 11:48:38 -05:00
Slava Pestov
bbbbfbac89 RequirementMachine: Fix assertion when protocol Self is constrained to a non-conforming type
The conflicting rule here is the permanent 'identity conformance'
([P].[P] => [P]). Permanent rules cannot be marked as conflicting,
so just check for this condition first.
2022-02-25 11:48:38 -05:00
Slava Pestov
aa210d29ae RequirementMachine: Prefer to eliminate concrete type requirements over superclass requirements again
If you have something like this:

    protocol P {
      associatedtype A : Q where Self == Self.A.B
    }

    protocol Q {
      associatedtype B
    }

    class C : P {
      typealias A = D
    }

    class D : P {
      typealias B = C
    }

The GSB would minimize the generic signature <T where T : P, T : C>
to <T where T == C>, because of the same-type requirement in
protocol P.

However in reality, the conformance 'C : P' is unsound, because it
is no longer covariant. I added a warning in commit d831eff74879cb.

Because the upcoming 'concrete contraction' pass eliminates 'T : P'
before homotopy reduction gets a chance to run, I'm changing the
Requirement Machine to produce a different minimization from the
GSB. This is technically an ABI break, but it should not impact any
real code in practice. If it does, I'll need to come up with a
different workaround in concrete contraction.
2022-02-25 11:48:38 -05:00
Slava Pestov
ae1ef6d50d RequirementMachine: Eliminate RequirementMachine::initWithAbstractRequirements() 2022-02-23 00:20:57 -05:00
Slava Pestov
e326c01f9b RequirementMachine: Write some comments 2022-02-23 00:20:57 -05:00
Slava Pestov
a3ab5f4cd4 RequirementMachine: Remove no-longer used DebugFlags::Merge 2022-02-23 00:17:56 -05:00
Slava Pestov
c75337c986 RequirementMachine: Remove lookupMemberType() in favor of existing substBaseType() 2022-02-18 22:24:25 -05:00
Slava Pestov
d7f8f2067a Sema: Generalize ProtocolDecl::getPrimaryAssociatedType() to ProtocolDecl::getPrimaryAssociatedTypes() 2022-02-18 22:24:25 -05:00
Slava Pestov
7e5d6f4cb0 AST: Rework ParameterizedProtocolTypes to store multiple argument types
For now, this is NFC since we still assume one argument elsewhere.
2022-02-18 18:22:20 -05:00
Slava Pestov
a69ac78482 RequirementMachine: Rework PropertyMap::recordConflict() for GSB compatibility
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.
2022-02-17 19:40:58 -05:00
Slava Pestov
966620bbaa RequirementMachine: Swap reduction order of ConcreteType and Superclass symbols
This ensures we produce the same minimal signature as the GSB
in a couple of really silly examples where a superclass requirement
and a concrete type requirement imply each other.
2022-02-17 19:40:58 -05:00
Slava Pestov
93727490df RequirementMachine: Remove old PropertyMap::unifyConcreteTypes() 2022-02-17 19:40:58 -05:00
Slava Pestov
b90dae1f15 RequirementMachine: Unify every pair of superclass requirements that apply to a term 2022-02-17 19:40:58 -05:00
Slava Pestov
2f16ca38e5 RequirementMachine: Unify every pair of concrete type rules that apply to a term
Instead of keeping track of the best one so far, and unifying subsequent rules
against it.

This allows us to record more identities, fixing a regression from an earlier
change where we were unable to eliminate an obviously-redundant rule.
2022-02-17 19:40:58 -05:00
Slava Pestov
ee410b4fe3 RequirementMachine: Another elimination order hack 2022-02-17 19:40:58 -05:00
Slava Pestov
86d47d951d RequirementMachine: Re-visit substitution-simplified rules for concrete unification 2022-02-17 19:40:58 -05:00
Slava Pestov
46d07fc739 RequirementMachine: Add new assertion to ConcreteTypeMatcher::verify() 2022-02-17 19:40:58 -05:00
Slava Pestov
e8503021fd RequirementMachine: Add a check to RewriteSystem::verifyMinimizedRules() 2022-02-17 19:40:58 -05:00
Slava Pestov
ef1292e1ce RequirementMachine: Don't filter out redundant superclass conformances when building archetypes
This was a hack to maintain exact compatibility with the GSB's
results when constructing archetypes, but it no longer appears
to be necessary.
2022-02-17 19:40:58 -05:00