Commit Graph

54 Commits

Author SHA1 Message Date
Andrew Trick
754edc7b8c Type checker: ignore LifetimeDependenceRequest in cycle diagnostic
When reporting the declarations that lead to a cycle, we end up printing an
extra "through reference here" on the function declaration:

class C2: C1, P {
   |       |- note: through reference here
   |       `- note: through reference here
15 |     // expected-note@-1 2{{through reference here}}
16 |     override func run(a: A) {}
   |                   |   |  `- note: while resolving type 'A'
   |                   |   `- note: through reference here
   |                   |- error: circular reference
   |                   |- note: through reference here
   |                   `- note: through reference here
2025-05-21 00:25:00 -07: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
Slava Pestov
42053105de AST: Add Evaluator::getInnermostSourceLoc() 2024-01-20 17:44:12 -05:00
Holly Borla
2cc1204afe [Evaluator] Remove hasActiveResolveMacroRequest(). 2023-06-11 23:10:43 -07:00
Doug Gregor
f96240d2d8 [Macros] Do not look into macro expansions while resolving macro arguments.
Macros introduced a significant wrinkle into Swift's name lookup mechanism.
Specifically, when resolving names (and, really, anything else) within the
arguments to a macro expansion, name lookup must not try to expand any
macros, because doing so trivially creates a cyclic dependency amongst the
macro expansions that will be detected by the request-evaluator.

Our lookup requests don't always have enough information to answer the
question "is this part of an argument to a macro?", so we do a much simpler,
more efficient, and not-entirely-sound hack based on the request-evaluator.
Specifically, if we are in the process of resolving a macro (which is
determined by checking for the presence of a `ResolveMacroRequest` in the
request-evaluator stack), then we adjust the options used for the name
lookup request we are forming to exclude macro expansions. The evaluation
of that request will then avoid expanding any macros, and not produce any
results that involve entries in already-expanded macros. By adjusting the
request itself, we still distinguish between requests that can and cannot
look into macro expansions, so it doesn't break caching for those immediate
requests.

Over time, we should seek to replace this heuristic with a location-based
check, where we use ASTScope to determine whether we are inside a macro
argument. This existing check might still be useful because it's going to
be faster than a location-based query, but the location-based query can be
fully correct.

This addresses a class of cyclic dependencies that we've been seeing
with macros, and aligns the lookup behavior for module-level lookups
with that specified in the macros proposals. It is not fully complete
because lookup until nominal types does not yet support excluding
results from macro expansions.
2023-04-06 16:04:41 -07:00
Anthony Latsis
6d7c4e5fdf Merge pull request #35849 from AnthonyLatsis/fix-debug-cycles 2021-06-25 05:32:09 +03:00
Robert Widmann
d4673467af Switch the Subject of Dependency References to a DeclContext 2021-02-23 12:09:32 -08:00
Anthony Latsis
978db47337 Evaluator: Improve -debug-cycles output 2021-02-09 17:01:24 +03:00
Slava Pestov
52d8479275 AST: Remove AnyRequest 2021-01-08 23:17:12 -05:00
Slava Pestov
28e7ed03d0 AST: Remove the 'legacy' request dependency graph implementation 2021-01-08 23:17:12 -05:00
Slava Pestov
797813fda4 Frontend: Don't record request references in WMO builds
Part of <rdar://problem/72906325>.
2021-01-07 23:52:55 -05:00
Slava Pestov
f6cd8f2696 AST: Convert some methods on DependencyRecorder to templates
... instead of passing around an ActiveRequest.
2021-01-05 17:56:38 -05:00
Slava Pestov
e4437d2187 AST: Don't print cached request values when dumping dependencies
This becomes tricky with the new per-request cache representation.

We can add it back later if we need it, but I feel like this code
path isn't particularly useful right now anyway.
2021-01-05 17:56:38 -05:00
Slava Pestov
161d832140 AST: Refactor request evaluator dependency tracking a bit
Other than simplifying some code, the big improvement here is
that we 'freeze' the reference dependencies for a request down
to a simple vector. We only use a DenseSet to store dependencies
of active requests.
2020-12-22 16:12:04 -05:00
Robert Widmann
e37b378d4d Remove DependencyRecorder::Mode 2020-09-21 10:42:33 -06:00
Robert Widmann
8c913e385e Remove LegacyCascadingDependencies 2020-09-21 10:42:33 -06:00
Robert Widmann
9e7964f4a5 Remove Reference::cascades 2020-09-21 10:37:42 -06:00
Robert Widmann
7fb448071c Remove DependencyScope 2020-09-21 10:37:41 -06:00
Robert Widmann
3228a5903a [NFC] Rename Flags
-enable-experimental-private-intransitive-dependencies -> -enable-direct-intramodule-dependencies
-disable-experimental-private-intransitive-dependencies -> -disable-direct-intramodule-dependencies

While we're here, rename DependencyCollector::Mode's constants and clean
up the documentation.
2020-06-09 16:00:59 -07:00
Robert Widmann
975ff757bc Perform The Dependency Unioning Step During Replay
In order for private dependencies to be completely correct, it must perform the name lookup unioning step when a cached request is replayed - not just when lookups are first performed. In order to reduce the overhead of this union operation, it is not necessary to walk the entire active request stack, just walk to the nearest cached request in the stack and union into that. When it is popped, its replay step will itself union into the next cached request.

To see why, consider a request graph:

A* -> B -> C*
         |
          -> D*

where A, C, and D are cached.

If a caller were to force C and D, then force A independenty, today we would *only* replay the names looked up by C and D the first time A was evaluated. That is, subsequent evaluations of A do not replay the correct set of names. If we were to perform the union step during replay as well, requests that force A would also see C and D’s lookups.

Without this, callers that force requests like the DeclChecker have to be wary of the way they force the interface type request so other files see the right name sets.

rdar://64008262
2020-06-05 11:42:29 -07:00
Robert Widmann
1d0065d136 Merge pull request #32145 from CodaFi/port-of-call
[NFC] Miscellaneous Cleanups To Clang Module Loading
2020-06-03 00:11:53 -07:00
Robert Widmann
aca0dceb3b [NFC] Use The 'isPrimary' Bit 2020-06-02 15:20:13 -07:00
Robert Widmann
e7f38db235 [NFC] Have Evaluator's Constructor Read LangOptions
It's a touch cleaner to do this than passing around a pile of bools.
2020-06-02 09:51:04 -07:00
Robert Widmann
9a88bef29d Start Keeping Track of Files With Dependencies in the DependencyCollector
This completely obviates the need for the referenced name trackers

rdar://59076016
2020-05-21 18:54:14 -07:00
Robert Widmann
3e76ea74f7 Add the "cascading" bit to Reference
We'll be able to delete this once we cut over to private dependencies
2020-05-21 18:46:08 -07:00
Robert Widmann
0a7929e80f Refine Naive Dependency Collection Algorithm
Split off the notion of "recording" dependencies from the notion of
"collecting" dependencies. This corrects an oversight in the previous
design where dependency replay and recording were actually not "free" in
WMO where we actually never track dependencies. This architecture also
lays the groundwork for the removal of the referenced name trackers.

The algorithm builds upon the infrastructure for dependency sources and
sinks laid down during the cut over to request-based dependency tracking
in #30723.

The idea of the naive algorithm is this:

For a chain of requests A -> B* -> C -> D* -> ... -> L where L is a lookup
request and all starred requests are cached, once L writes into the
dependency collector, the active stack is walked and at each cache-point
the results of dependency collection are associated with the request
itself (in this example, B* and D* have all the names L found associated
with them). Subsequent evaluations of these cached requests (B* and D*
et al) will then *replay* the previous lookup results from L into the
active referenced name tracker. One complication is, suppose the
evaluation of a cached request involves multiple downstream name
lookups. More concretely, suppose we have the following request trace:

A* -> B -> L
      |
       -> C -> L
          |
           -> D -> L
              |
               -> ...

Then A* must see the union of the results of each L. If this reminds
anyone of a union-find, that is no accident! A persistent union-find
a la Conchon and Filliatre is probably in order to help bring down peak
heap usage...
2020-05-20 16:08:05 -07:00
Robert Widmann
115bd2855b Naive Dependency Replay
Finish off private intransitive dependencies with an implementation of
dependency replay.

For the sake of illustration, imagine a chain of requests

A -> B -> C -> ...

Supposing each request is never cached, then every invocation of the
compiler with the same inputs will always kick off the exact same set of
requests. For the purposes of dependency tracking, that also means every
single lookup request will run without issue, and all dependencies will
be accurately reported. But we live in a world with cached requests.
Suppose request B* is cached. The first time we encounter that request,
its evaluation order looks identical:

A -> B* -> C -> ...

If we are in a mode that compiles single primaries, this is not
a problem because every request graph will look like this.
But if we are in a mode where we are compiling multiple primaries, then
subsequent request graphs will *actually* hit the cache and never
execute request C or any of its dependent computations!

A -> B*

Supposing C was a lookup request, that means the name(s) looked up
downstream of B* will *never* be recorded in the referenced name tracker
which can lead to miscompilation. Note that this is not a problem
inherent to the design of the request evaluator - caches in the compiler
have *always* hidden dependent lookups. In fact, the request evaluator
provides us our first opportunity to resolve this correctness bug!
2020-05-20 10:41:19 -07:00
Robert Widmann
b06211eac4 Initial plumbing for private dependencies
Add a mode bit to the dependency collector that respects the frontend flag in the previous commit.

Notably, we now write over the dependency files at the end of the compiler pipeline when this flag is on so that dependency from SILGen and IRGen are properly written to disk.
2020-05-05 13:48:25 -07:00
Robert Widmann
7a724b1477 [NFC] Extract Dependency Registration to DependencyCollector
Define a new type DependencyCollector that abstracts over the
incremental dependency gathering logic. This will insulate the
request-based name tracking code from future work on private,
intransitive dependencies.
2020-04-22 21:01:20 -07:00
Hamish Knight
f081ae51d4 Revert "Revert "Don't heap allocate for active requests""
f8a1ad22e1
2020-01-23 11:03:32 -08:00
Saleem Abdulrasool
f8a1ad22e1 Revert "Don't heap allocate for active requests" 2020-01-23 08:33:31 -08:00
Hamish Knight
a1c490220b Enable the use of find_as with ActiveRequest
This avoids having to allocate a full AnyRequest
for a hash lookup.
2020-01-21 13:07:33 -08:00
Hamish Knight
4b698a5a31 [AST] Introduce ActiveRequest
This wrapper is used to type erase a reference to
a request on the stack, and can be converted into
an AnyRequest when persistent storage is required.

Switch the evaluator over to using ActiveRequest
for its stack of active requests, meaning it now
only needs to heap allocate requests when they
enter the cache, or if it's building the (disabled
by default) dependency graph.
2020-01-20 09:15:16 -08:00
Slava Pestov
0eb2484a93 AST: Only build request dependency graph if frontend is run with -build-request-dependency-graph
This adds a measurable amount of runtime overhead, but it's only
needed for debugging.
2020-01-08 22:35:55 -05:00
Jordan Rose
171ff440fc Remove swift::reversed in favor of llvm::reverse (#27610)
The former predates the latter, but we don't need it anymore! The
latter has more features anyway.

No functionality change.
2019-10-10 17:16:09 -07:00
Robert Widmann
a19a70e5c9 Switch all request infrastructure to SWIFT_REQUEST
Formally define the Zones in the TypeID header.  This is not its final
resting place.
2019-08-27 17:38:14 -07:00
Doug Gregor
df60b018d0 [Request-evaluator] Augment output with "fake" dependencies from source buffers
To help make the current GraphViz output of the dependency graph more
legible, introduce "fake" nodes for the source buffers we encounter,
and draw edges from those nodes to any requests associated with those
source buffers that have no other edges leading to them. This is a
temporary visualization hack, to be replaced by proper "top-level"
requests for things like type-checking an entire source file.
2019-07-10 23:17:06 -07:00
Doug Gregor
393e264f18 [Request-evaluator] Color-code Graphviz nodes by source buffer.
Use the "nearest source location" information on a request to map it
to a particular source buffer, then use that information in the
GraphViz dependency graphs so we can see cross-file dependencies more
clearly.
2019-07-10 22:36:38 -07:00
Slava Pestov
3f5a06bc3e AST: Always diagnose request evaluator cycles 2019-04-22 22:22:23 -04:00
Xi Ge
ce29c64964 [Evaluator] Refactor evaluator's GraphViz output to the destructor of the evaluator. NFC
This allows us to output dependency-graph while using the compiler in
other tools, like swift-ide-test, sourcekitd-test, etc.
2018-08-28 18:16:44 -07:00
Jordan Rose
c56f3c6a76 Request evaluator: Use DenseMap::find_as to look up Requests
...when we don't need to store them, to avoid copying the Request into
an AnyRequest heap box.
2018-08-10 10:23:40 -07:00
swift-ci
4d15dc1dad Merge remote-tracking branch 'origin/master' into master-next 2018-06-29 17:29:11 -07:00
Doug Gregor
a6f46584ec [Evaluator] Indirect evaluation of uncached requests through a separate table.
The bundling of the form of a request (e.g., the storage that makes up a request)
with the function that evaluates the request value requires us to perform
ad hoc indirection to address the AST —> Sema layering violation. For
example, ClassDecl::getSuperclass() calls through the LazyResolver (when
available) to form the appropriate request. This means that we cannot
use the the request-evaluator’s cache when LazyResolver is null, forcing
all cached state into the AST.

Provide the evaluator with a zone-based registration system, where each
request “zone” (e.g., the type checker’s requests) registers
callbacks to evaluate each kind of request within that zone. The
evaluator indirects through this table of function pointers, allowing
the request classes themselves to be available at a lower level (AST)
than the functions that perform the computation when the value isn’t
in the cache (e.g., Sema).

We are not taking advantage of the indirection yet; that’ll come in a
follow-up commit.
2018-06-29 15:41:55 -07:00
swift-ci
4538ce9818 Merge remote-tracking branch 'origin/master' into master-next 2018-06-17 15:38:24 -07:00
Doug Gregor
7ac0a5be14 [Request-evaluator] Improve dumping of dependencies and cycles.
When dumping dependencies, clean up the output in two ways:

* Elide redundant but (non-cyclic) references to the same dependency.
* When dumping a cycle, highlight the path to the cycle so it stands out.
2018-06-16 10:29:52 -07:00
Doug Gregor
b1b3c43c59 [Request-evaluator] Add -debug-cycles flag to print cycles.
As a debugging aid, introduce a new frontend flag `-debug-cycles` that
will emit a debug dump whenever the request-evaluator encounters a cyclic
dependency, while otherwise allowing compilation to continue.
2018-06-16 10:29:52 -07:00
swift-ci
bfe796b93e Merge remote-tracking branch 'origin/master' into master-next 2018-06-16 01:32:31 -07:00
Doug Gregor
9843190300 [Request-evaluator] Disable cycle diagnostics when used in the type checker.
The type checker has *lots* cycles, and producing diagnostics for them
at this point in the development of the request-evaluator is not
productive because it breaks currently-working code. Disable cycle
diagnostics for now when using the request-evaluator in the type
checker. We'll enable it later as things improve, or as a separate
logging mode in the interim.
2018-06-14 15:29:57 -07:00
Bob Wilson
3430fb4689 [master-next] Use renamed LLVM printEscapedString function
LLVM r333669 renamed the PrintEscapedString function to
printEscapedString. Adjust Swift to match.
2018-06-12 16:51:26 -07:00
Doug Gregor
b12d319c44 [Evaluator] Print cached value as part of dependency tree printing. 2018-06-01 08:56:18 -07:00