Commit Graph

117 Commits

Author SHA1 Message Date
Slava Pestov
7f8175b3da RequirementMachine: Add two more completion termination checks for concrete type requirements
The concrete nesting limit, which defaults to 30, catches
things like A == G<A>. However, with something like
A == (A, A), you end up with an exponential problem size
before you hit the limit.

Add two new limits.

The first is the total size of the concrete type, counting
all leaves, which defaults to 4000. It can be set with the
-requirement-machine-max-concrete-size= frontend flag.

The second avoids an assertion in addTypeDifference() which
can be hit if a certain counter overflows before any other
limit is breached. This also defaults to 4000 and can be set
with the -requirement-machine-max-type-differences= frontend flag.
2025-06-17 17:51:25 -04:00
Hamish Knight
edca7c85ad Adopt ABORT throughout the compiler
Convert a bunch of places where we're dumping to stderr and calling
`abort` over to using `ABORT` such that the message gets printed to
the pretty stack trace. This ensures it gets picked up by
CrashReporter.
2025-05-19 20:55:01 +01:00
Slava Pestov
d77c6f413d RequirementMachine: Skip protocol type aliases that contain unbound dependent member types
In the below, 'Self.A.A' is not a type parameter; rather, since
'Self.A' is concretely known to be 'S', we resolve it as 'S.A',
which performs a name lookup and finds the concrete type alias 'A':

    public struct S {
      public typealias A = Int
    }

    public protocol P {
      typealias A = S
    }

    public struct G<T> {}

    public protocol Q: P {
      typealias B = G<Self.A.A>
    }

This is fine, but such a type alias should not participate in
the rewrite system. Let's exclude them like any other invalid
requirement.

The type alias itself is not an error; however, it is an error
to use it from a 'where' clause requirement. This is not
diagnosed yet, though.

Fixes rdar://136686001.
2025-03-26 10:55:23 -04:00
Slava Pestov
fbe3d71b19 RequirementMachine: Small cleanup 2024-09-14 23:33:11 -04:00
Holly Borla
2ea4586580 [Requirement Machine] Implement same-element requirements. 2024-07-15 10:19:32 -07:00
Slava Pestov
273c4b2b1a RequirementMachine: Convert to new assertions 2024-06-22 08:53:22 -04:00
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Slava Pestov
70c9f8a47e RequirementMachine: Leave behind conflicting requirements in the minimized signature
Requirement lowering only expects that it won't see two requirements
of the same kind (except for conformance requirements). So only mark
those as conflicting.

This addresses a crash-on-invalid and improves diagnostics for
move-only generics, because a conflict won't drop the copyability
of a generic parameter and expose a move-only-naive user to
confusing error messages.

Fixes #61031.
Fixes #63997.
Fixes rdar://problem/111991454.
2024-02-15 14:32:31 -05:00
Slava Pestov
dcca5ced0f RequirementMachine: Remove -warn-redundant-requirements flag 2024-02-02 14:57:19 -05:00
Slava Pestov
595a7a530b RequirementMachine: Fix potential 'pollution' from installing an invalid requirement machine
If the substitution terms of a concrete type symbol contain unresolved
name symbols, we have an invalid requirement that is dropped from the
minimized signature. In this case, the rewrite system used for minimization
cannot be installed as the official rewrite system for this generic
signature, because building a rewrite system from the signature will
produce a different result.

This might be the cause of the crash in rdar://114111159.
2023-08-21 23:36:37 -04:00
Evan Wilde
250082df25 [NFC] Reformat all the LLVMs
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
2023-06-27 09:03:52 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
                     bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".

I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
2023-06-27 09:03:52 -07:00
Erik Eckstein
ab1b343dad use new llvm::Optional API
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`

The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.

rdar://102362022
2022-11-21 19:44:24 +01:00
Slava Pestov
e3ab64afa7 RequirementMachine: Compute recursive rules 2022-08-11 14:10:01 -04:00
Slava Pestov
506cc356c1 RequirementMachine: New minimal conformances algorithm 2022-07-05 21:40:27 -04:00
Slava Pestov
6b48eb6549 RequirementMachine: More debug output from RewritePath::RewriteSystem::propagateRedundantRequirementIDs() 2022-04-04 12:41:57 -04:00
Slava Pestov
5bff2a02c5 RequirementMachine: Rename RewritePath::getRulesInEmptyContext() to findRulesAppearingOnceInEmptyContext() 2022-04-04 12:41:57 -04:00
Slava Pestov
d212041dfb RequirementMachine: Fold RewriteSystem::processConflicts() into recordConflict() and add debug output 2022-04-01 01:05:54 -04:00
Slava Pestov
ad2f73af44 RequirementMachine: More comments 2022-03-29 12:10:33 -04: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
6110866065 RequirementMachine: Propagate requirement IDs only once 2022-03-25 22:28:11 -04:00
Slava Pestov
06a25fa452 RequirementMachine: Don't normalize replacement paths for redundant rules 2022-03-25 22:28:11 -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
Holly Borla
6b64ac26f4 [RequirementMachine] Suppress redundant requirement warnings for inferred
requirements.
2022-03-15 21:14:43 -07:00
Slava Pestov
2a634ba468 RequirementMachine: Optimize RewriteSystem::normalizeRedundantRules() 2022-03-15 13:35:34 -04:00
Slava Pestov
d4732f5a19 RequirementMachine: Move RewritePath and RewriteLoop methods from HomotopyReduction.cpp to RewriteLoop.cpp 2022-03-15 13:35:34 -04:00
Slava Pestov
7b01ff60f0 RequirementMachine: Simplify RewriteSystem::processConflicts()
Remove the logic which incorrectly attempted to simulate the
GenericSignatureBuilder's minimization behavior in the presence
of conflicts, since it doesn't matter anymore.
2022-03-14 12:33:18 -04:00
Slava Pestov
f5b3d19703 RequirementMachine: Replace hadError() with getErrors() returning an OptionSet
This gives us more fine-grained information which will be plumbed
through the various requests.
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
1f83cd0b49 RequirementMachine: Don't eliminate a rule via a path involving a protocol typealias rule
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.
2022-03-11 17:28:01 -05:00
Slava Pestov
a259844803 RequirementMachine: Record those rewrite loops involving protocol typealiases 2022-03-11 17:28:01 -05:00
Slava Pestov
3641b77c21 RequirementMachine: Split up first pass of homotopy reduction into two
Add a separate pass to consider rules with unresolved names which are
not simplified.
2022-03-11 17:28:01 -05:00
Slava Pestov
f082c02e42 RequirementMachine: Plumb through the loop candidate to isRedundantRuleFn 2022-03-11 17:28:01 -05: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
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
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
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
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
b497c790fa RequirementMachine: Check invariants in noassert builds 2022-03-03 14:05:02 -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
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
ee410b4fe3 RequirementMachine: Another elimination order hack 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
991fe1dbd8 RequirementMachine: Preserve replacement paths for redundant rules 2022-02-16 16:28:08 -05:00
Slava Pestov
426df360b0 RequirementMachine: More elimination order tweaking
- Prefer rewrite loops not involving Decompose
- Prefer more deeply nested concrete types
2022-02-15 04:02:46 -05:00
Slava Pestov
0deacdc7b1 RequirementMachine: Fix silly typo in RewriteSystem::findRuleToDelete()
This was regressing a couple of validation tests after the
seemingly-unrelated introduction of protocol typealias support.
2022-02-13 09:50:16 -05:00