Commit Graph

137 Commits

Author SHA1 Message Date
Slava Pestov
e805339de4 RequirementMachine: Relax assertion in verifyRewriteSystem()
We can end up with a rule that has a protocol symbol on the right hand side:

    X.Y.Z => X.W.[P]

This will occur if X.W.[P] was obtained by simplifying a term X.W.U.V via
a rule (U.V => [P]), and before completion discovers a rule
(X.W.[P] => X.W).

Fixes rdar://problem/94854326, rdar://problem/94980084.
2022-06-17 16:13:42 -04:00
Slava Pestov
f901cc72b4 RequirementMachine: Move diagnostics code into a new Diagnostics.cpp 2022-05-10 01:49:56 -04:00
Slava Pestov
094130b9c7 RequirementMachine: Diagnose redundant concrete conformance requirements
A conformance requirement on a concrete type parameter is redundant if the
concrete type conforms to the protocol.

The replacement path for the conformance rule is based on a concrete
conformance rule introduced by the property map. Since the concrete
conformance rule is not associated with a requirement ID, this would
normally muffle the redundancy warning, because we don't want to
suggest removing a rule that depends on a non-redundant, non-explicit
rule.

However, concrete conformance rules don't actually appear in the
minimal signature, so skip them when computing the set of non-redundant,
non-explicit rules to ensure that the original conformance requirement
is still diagnosed as redundant.
2022-04-05 21:12:51 -04:00
Slava Pestov
4d15fa0087 RequirementMachine: Don't diagnose trivial circularity 'protocol P : P' as redundant
Every protocol gets an 'identity conformance' rule [P].[P] => [P].
A trivially-stated circularity is always redundant because of this
rule, and we diagnose circular inheritance elsewhere as a hard
error, so just add a special case to skip adding such a rule here
to avoid the useless warning on top of the existing error.
2022-04-05 21:12:51 -04:00
Slava Pestov
c0c109d3f5 RequirementMachine: Tighten verifyRewriteRules() further
We should never have a rule with a protocol symbol on the *right* hand
side, like (T => U.[P]).
2022-04-04 23:52:58 -04:00
Slava Pestov
7d51fa9f62 RequirementMachine: RewriteSystem::dump() prints out written requirements 2022-04-04 12:41:57 -04:00
Slava Pestov
22f0f40a30 RequirementMachine: Copy over GSB logic where inheritance of JSExport protocol can be re-stated redundantly 2022-04-01 01:04:54 -04:00
Holly Borla
85be43f18f [RequirementMachine] Omit duplicate conflict diagnostics. 2022-03-30 22:50:13 -07:00
Holly Borla
7e5c48382d [RequirementMachine] When computing requirements for conflict diagnostics,
adjust the concrete type symbol for the suffix rule by applying the prefix
from the subject rule.
2022-03-30 22:30:45 -07:00
Holly Borla
78b07565b6 [RequirementMachine] Use PropertyMap::getTypeFromSubstitutionSchema when
computing a concrete same-type or superclass for conflict diagnostics.

Otherwise, diagnostics will show fresh type parameters when the concrete
type is generic.
2022-03-30 14:09:06 -07:00
Holly Borla
5296fbdf45 [NFC][RequirementMachine] Stylistic changes for computing confict
diagnostics.

Move computing requirements from rules into a static function, make
a few variables const, etc.
2022-03-30 14:09:06 -07:00
Holly Borla
a4230a6061 [RequirementMachine] Simplify computing and emitting conflict diagnostics.
Instead of computing different combinations of conflicting requirement kinds,
emit the same error message for all of them.
2022-03-29 18:27:45 -07:00
Holly Borla
31028e5a9f [RequirementMachine] When computing conflict diagnostics, only compute the
type for the longer subject term between the two conflicting rules.
2022-03-29 18:27:45 -07:00
Holly Borla
964c11a4d0 [RequirementMachine] Consolidate the various RequirementError::Kind cases
that represent conflict diagnostics.
2022-03-29 18:27:45 -07:00
Holly Borla
caee699560 [RequirementMachine] Mention the type parameter that is the subject of
two conflicting requirements in diagnostics where possible.
2022-03-29 18:27:45 -07:00
Holly Borla
99f5e365cc [RequirementMachine] Compute and diagnose conflicting rules in the minimal
rewrite system of a generic/requirement signature.
2022-03-29 18:26:26 -07:00
Slava Pestov
4d097da73c RequirementMachine: Re-use requirement machines constructed by minimization for queries
Fixes rdar://problem/88135641.
2022-03-26 00:56:41 -04:00
Slava Pestov
3d2559f79e RequirementMachine: Don't skip subst-simplified rules when importing
Property map construction is still not incremental, and considers
all rules. Skipping subst-simplified rules here violates invariants
checked by the next commit.
2022-03-26 00:56:41 -04:00
Slava Pestov
d8215bb155 RequirementMachine: Rework 'implied rules' computation in computeRedundantRequirementDiagnostics()
For efficiency I want to keep replacement paths for redundant rules
unsubstituted, so that earlier replacement paths can reference
redundant rules that appear later in the RedundantRules array.

Right now we expand replacement paths so that their RewriteSteps
only mention non-redundant rules.

This patch refactors the computeRedundantRequirementDiagnostics()
method a bit:

The impliedRequirements set is now named nonExplicitNonRedundantRules,
and in addition to storing these rules themselves, the set also
stores any _redundant_ rules that reference these rules via their
replacement paths.

Since this is computing a transitive closure, we walk the
RedundantRules array in reverse. A replacement path can only
reference a redundant rule if that redundant rule appears later
in the array.
2022-03-25 22:28:03 -04:00
Slava Pestov
7d0215e6e0 RequirementMachine: Tweak rule limit non-termination heuristic
Add the length of the longest *initial* rule to the rule length limit
before comparing.

Fixes https://bugs.swift.org/browse/SR-16024.
2022-03-25 01:00:49 -04:00
Slava Pestov
fb487f80e7 RequirementMachine: Factor out RewriteSystem::addRules() from RewriteSystem::initialize() 2022-03-16 12:24:20 -04:00
Slava Pestov
c25cd24fe9 RequirementMachine: RewriteSystem::initialize() takes writtenRequirements as an rvalue 2022-03-16 12:24:20 -04:00
Holly Borla
98beadf8f5 Merge pull request #41833 from hborla/redundant-requirement-tweak
[RequirementMachine] Suppress redundant requirement warnings for inferred requirements.
2022-03-16 09:00:24 -07:00
Slava Pestov
9704168351 RequirementMachine: Skip imported rules in various places when iterating over all rules 2022-03-16 00:58:30 -04:00
Slava Pestov
327e7e580b RequirementMachine: Add importedRules parameter to RewriteSystem::initialize() 2022-03-16 00:58:30 -04:00
Holly Borla
6b64ac26f4 [RequirementMachine] Suppress redundant requirement warnings for inferred
requirements.
2022-03-15 21:14:43 -07:00
Slava Pestov
755941c21f RequirementMachine: Split off Rule.cpp from RewriteSystem.cpp 2022-03-15 13:35:34 -04:00
Slava Pestov
e0c10d412e RequirementMachine: Tweak debug output 2022-03-14 12:33:18 -04:00
Slava Pestov
762bf1e7d0 RequirementMachine: Refine 'derived via protocol typealias' criterion
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).
2022-03-14 12:33:18 -04:00
Slava Pestov
a259844803 RequirementMachine: Record those rewrite loops involving protocol typealiases 2022-03-11 17:28:01 -05:00
Slava Pestov
5cfee4e9ab RequirementMachine: Stricter invariants in verifyRewriteRules() 2022-03-11 17:28:01 -05:00
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
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
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
b497c790fa RequirementMachine: Check invariants in noassert builds 2022-03-03 14:05:02 -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
e478ced1ce RequirementMachine: Move some code into a new SimplifySubstitutions.cpp 2022-02-15 04:02:46 -05:00
Slava Pestov
530bee5235 RequirementMachine: Loosen check in RewriteSystem::verifyRewriteRules() to allow protocol typealias rules 2022-02-13 00:24:23 -05:00
Slava Pestov
f9c2d9fd7c RequirementMachine: Introduce Rule::isProtocolTypeAliasRule()
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.
2022-02-13 00:24:23 -05:00
Slava Pestov
6685e55135 RequirementMachine: Print loop numbers in RewriteSystem::dump() 2022-02-09 10:45:09 -05:00
Slava Pestov
0d0bcb2ff1 RequirementMachine: Simplify the Symbol API for removal of merged associated types 2022-02-07 18:57:45 -05:00