Skip to content

Commit 4d875ee

Browse files
authored
Merge pull request #33096 from CodaFi/my-private-eyes
Drop Legacy Cascading Dependencies From the Frontend
2 parents 1345a2b + 4557b69 commit 4d875ee

File tree

431 files changed

+445
-10050
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

431 files changed

+445
-10050
lines changed

include/swift/AST/ASTScope.h

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,6 @@ class ASTScopeImpl {
417417
static llvm::SmallVector<LabeledStmt *, 4>
418418
lookupLabeledStmts(SourceFile *sourceFile, SourceLoc loc);
419419

420-
static Optional<bool>
421-
computeIsCascadingUse(ArrayRef<const ASTScopeImpl *> history,
422-
Optional<bool> initialIsCascadingUse);
423-
424420
static std::pair<CaseStmt *, CaseStmt *>
425421
lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc);
426422

@@ -448,7 +444,6 @@ class ASTScopeImpl {
448444
/// The main (recursive) lookup function:
449445
/// Tell DeclConsumer about all names found in this scope and if not done,
450446
/// recurse for enclosing scopes. Stop lookup if about to look in limit.
451-
/// Return final value for isCascadingUse
452447
///
453448
/// If the lookup depends on implicit self, selfDC is its context.
454449
/// (Names in extensions never depend on self.)
@@ -508,9 +503,6 @@ class ASTScopeImpl {
508503

509504
#pragma mark - - lookup- local bindings
510505
protected:
511-
virtual Optional<bool>
512-
resolveIsCascadingUseForThisScope(Optional<bool>) const;
513-
514506
// A local binding is a basically a local variable defined in that very scope
515507
// It is not an instance variable or inherited type.
516508

@@ -611,11 +603,11 @@ class Portion {
611603
virtual ASTScopeImpl *expandScope(GenericTypeOrExtensionScope *,
612604
ScopeCreator &) const = 0;
613605

606+
/// \Returns \c true if this lookup is done looking for results, else \c false.
614607
virtual SourceRange
615608
getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *scope,
616609
bool omitAssertions) const = 0;
617610

618-
/// Returns isDone and isCascadingUse
619611
virtual bool lookupMembersOf(const GenericTypeOrExtensionScope *scope,
620612
ArrayRef<const ASTScopeImpl *>,
621613
ASTScopeImpl::DeclConsumer consumer) const;
@@ -780,10 +772,6 @@ class GenericTypeOrExtensionScope : public ASTScopeImpl {
780772
virtual bool doesDeclHaveABody() const;
781773
const char *portionName() const { return portion->portionName; }
782774

783-
protected:
784-
Optional<bool> resolveIsCascadingUseForThisScope(
785-
Optional<bool> isCascadingUse) const override;
786-
787775
public:
788776
// Only for DeclScope, not BodyScope
789777
// Returns the where clause scope, or the parent if none
@@ -969,8 +957,6 @@ class GenericParamScope final : public ASTScopeImpl {
969957
protected:
970958
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
971959
DeclConsumer) const override;
972-
Optional<bool>
973-
resolveIsCascadingUseForThisScope(Optional<bool>) const override;
974960
};
975961

976962
/// Concrete class for a function/initializer/deinitializer
@@ -1014,9 +1000,6 @@ class AbstractFunctionDeclScope final : public ASTScopeImpl {
10141000

10151001
protected:
10161002
NullablePtr<const GenericParamList> genericParams() const override;
1017-
1018-
Optional<bool>
1019-
resolveIsCascadingUseForThisScope(Optional<bool>) const override;
10201003
};
10211004

10221005
/// The parameters for an abstract function (init/func/deinit)., subscript, and
@@ -1087,8 +1070,6 @@ class AbstractFunctionBodyScope : public ASTScopeImpl {
10871070
protected:
10881071
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
10891072
DeclConsumer) const override;
1090-
Optional<bool>
1091-
resolveIsCascadingUseForThisScope(Optional<bool>) const override;
10921073

10931074
public:
10941075
NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion() override;
@@ -1123,10 +1104,6 @@ class DefaultArgumentInitializerScope final : public ASTScopeImpl {
11231104
virtual NullablePtr<DeclContext> getDeclContext() const override;
11241105
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
11251106
Decl *getDecl() const { return decl; }
1126-
1127-
protected:
1128-
Optional<bool>
1129-
resolveIsCascadingUseForThisScope(Optional<bool>) const override;
11301107
};
11311108

11321109
/// Consider:
@@ -1274,9 +1251,6 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
12741251
protected:
12751252
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
12761253
DeclConsumer) const override;
1277-
1278-
Optional<bool>
1279-
resolveIsCascadingUseForThisScope(Optional<bool>) const override;
12801254
};
12811255

12821256
/// The scope introduced by a conditional clause in an if/guard/while
@@ -1402,8 +1376,6 @@ class ClosureParametersScope final : public ASTScopeImpl {
14021376
protected:
14031377
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
14041378
DeclConsumer) const override;
1405-
Optional<bool> resolveIsCascadingUseForThisScope(
1406-
Optional<bool> isCascadingUse) const override;
14071379
};
14081380

14091381
class TopLevelCodeScope final : public ASTScopeImpl {

include/swift/AST/DeclContext.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -508,14 +508,6 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
508508
/// FIXME: do this for Protocols, too someday
509509
bool canBeParentOfExtension() const;
510510

511-
/// Returns true if lookups within this context could affect downstream files.
512-
///
513-
/// \param functionsAreNonCascading If true, functions are considered non-
514-
/// cascading contexts. If false, functions are considered non-cascading only
515-
/// if implicitly or explicitly marked private. When concerned only with a
516-
/// function's body, pass true.
517-
bool isCascadingContextForLookup(bool functionsAreNonCascading) const;
518-
519511
/// Look for the set of declarations with the given name within a type,
520512
/// its extensions and, optionally, its supertypes.
521513
///

include/swift/AST/EvaluatorDependencies.h

Lines changed: 19 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/AnyRequest.h"
2222
#include "swift/AST/AttrKind.h"
2323
#include "swift/AST/SourceFile.h"
24+
#include "swift/Basic/NullablePtr.h"
2425
#include "llvm/ADT/PointerIntPair.h"
2526

2627
namespace swift {
@@ -32,80 +33,13 @@ namespace detail {
3233
template <typename...> using void_t = void;
3334
} // namespace detail
3435

35-
/// The "scope" of a dependency edge tracked by the evaluator.
36-
///
37-
/// Dependency scopes come in two flavors: cascading and private. A private
38-
/// edge captures dependencies discovered in contexts that are not visible to
39-
/// to other files. For example, a conformance to a private protocol, or the use
40-
/// of any names inside of a function body. A cascading edge, by contrast,
41-
/// captures dependencies discovered in the remaining visible contexts. These
42-
/// are types with at least \c internal visibility, names defined or used
43-
/// outside of function bodies with at least \c internal visibility, etc. A
44-
/// dependency that has cascading scope is so-named because upon traversing the
45-
/// edge, a reader such as the driver should continue transitively evaluating
46-
/// further dependency edges.
47-
///
48-
/// A cascading edge is always conservatively correct to produce, but it comes
49-
/// at the cost of increased resources spent (and possibly even wasted!) during
50-
/// incremental compilation. A private edge, by contrast, is more efficient for
51-
/// incremental compilation but it is harder to safely use.
52-
///
53-
/// To ensure that these edges are registered consistently with the correct
54-
/// scopes, requests that act as the source of dependency edges are required
55-
/// to specify a \c DependencyScope under which all evaluated sub-requests will
56-
/// register their dependency edges. In this way, \c DependencyScope values
57-
/// form a stack-like structure and are pushed and popped by the evaluator
58-
/// during the course of request evaluation.
59-
///
60-
/// When determining the kind of scope a request should use, always err on the
61-
/// side of a cascading scope unless there is absolute proof any discovered
62-
/// dependencies will be private. Inner requests may also defensively choose to
63-
/// flip the dependency scope from private to cascading in the name of safety.
64-
enum class DependencyScope : bool {
65-
Private = false,
66-
Cascading = true,
67-
};
68-
69-
/// Returns a \c DependencyScope appropriate for the given (formal) access level.
70-
///
71-
/// :warning: This function exists to bridge the old manual reference
72-
/// dependencies code to the new evaluator-based reference dependencies code.
73-
/// The manual code often made private/cascading scope judgements based on the
74-
/// access level of a declaration. While this makes some sense intuitively, it
75-
/// does not necessarily capture an accurate picture of where real incremental
76-
/// dependencies lie. For example, references to formally private types can
77-
/// "escape" to contexts that have no reference to the private name if, say,
78-
/// the layout of that private type is taken into consideration by
79-
/// SILGen or IRGen in a separate file that references the declaration
80-
/// transitively. However, due to the density of the current dependency
81-
/// graph, redundancy in registered dependency edges, and the liberal use of
82-
/// cascading edges, we may be saved from the worst consequences of this
83-
/// modelling choice.
84-
///
85-
/// The use of access-levels for dependency decisions is an anti-pattern that
86-
/// should be revisited once finer-grained dependencies are explored more
87-
/// thoroughly.
88-
inline DependencyScope getScopeForAccessLevel(AccessLevel l) {
89-
switch (l) {
90-
case AccessLevel::Private:
91-
case AccessLevel::FilePrivate:
92-
return DependencyScope::Private;
93-
case AccessLevel::Internal:
94-
case AccessLevel::Public:
95-
case AccessLevel::Open:
96-
return DependencyScope::Cascading;
97-
}
98-
llvm_unreachable("invalid access level kind");
99-
}
100-
101-
// A \c DependencySource is currently defined to be a parent source file and
102-
// an associated dependency scope.
36+
// A \c DependencySource is currently defined to be a primary source file.
10337
//
10438
// The \c SourceFile instance is an artifact of the current dependency system,
10539
// and should be scrapped if possible. It currently encodes the idea that
10640
// edges in the incremental dependency graph invalidate entire files instead
10741
// of individual contexts.
108-
using DependencySource = llvm::PointerIntPair<SourceFile *, 1, DependencyScope>;
42+
using DependencySource = swift::NullablePtr<SourceFile>;
10943

11044
struct DependencyRecorder;
11145

@@ -133,41 +67,38 @@ struct DependencyCollector {
13367

13468
NominalTypeDecl *subject;
13569
DeclBaseName name;
136-
bool cascades;
13770

13871
private:
139-
Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name,
140-
bool cascades)
141-
: kind(kind), subject(subject), name(name), cascades(cascades) {}
72+
Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name)
73+
: kind(kind), subject(subject), name(name) {}
14274

14375
public:
14476
static Reference empty() {
14577
return {Kind::Empty, llvm::DenseMapInfo<NominalTypeDecl *>::getEmptyKey(),
146-
llvm::DenseMapInfo<DeclBaseName>::getEmptyKey(), false};
78+
llvm::DenseMapInfo<DeclBaseName>::getEmptyKey()};
14779
}
14880

14981
static Reference tombstone() {
15082
return {Kind::Tombstone,
15183
llvm::DenseMapInfo<NominalTypeDecl *>::getTombstoneKey(),
152-
llvm::DenseMapInfo<DeclBaseName>::getTombstoneKey(), false};
84+
llvm::DenseMapInfo<DeclBaseName>::getTombstoneKey()};
15385
}
15486

15587
public:
156-
static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name,
157-
bool cascades) {
158-
return {Kind::UsedMember, subject, name, cascades};
88+
static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name) {
89+
return {Kind::UsedMember, subject, name};
15990
}
16091

161-
static Reference potentialMember(NominalTypeDecl *subject, bool cascades) {
162-
return {Kind::PotentialMember, subject, DeclBaseName(), cascades};
92+
static Reference potentialMember(NominalTypeDecl *subject) {
93+
return {Kind::PotentialMember, subject, DeclBaseName()};
16394
}
16495

165-
static Reference topLevel(DeclBaseName name, bool cascades) {
166-
return {Kind::TopLevel, nullptr, name, cascades};
96+
static Reference topLevel(DeclBaseName name) {
97+
return {Kind::TopLevel, nullptr, name};
16798
}
16899

169-
static Reference dynamic(DeclBaseName name, bool cascades) {
170-
return {Kind::Dynamic, nullptr, name, cascades};
100+
static Reference dynamic(DeclBaseName name) {
101+
return {Kind::Dynamic, nullptr, name};
171102
}
172103

173104
public:
@@ -248,34 +179,17 @@ struct DependencyCollector {
248179
struct DependencyRecorder {
249180
friend DependencyCollector;
250181

251-
enum class Mode {
252-
// Enables the status quo of recording direct dependencies.
253-
//
254-
// This mode restricts the dependency collector to ignore changes of
255-
// scope. This has practical effect of charging all unqualified lookups to
256-
// the primary file being acted upon instead of to the destination file.
257-
DirectDependencies,
258-
// Enables a legacy mode of dependency tracking that makes a distinction
259-
// between private and cascading edges, and does not directly capture
260-
// transitive dependencies.
261-
//
262-
// By default, the dependency collector moves to register dependencies in
263-
// the referenced name trackers at the top of the active dependency stack.
264-
LegacyCascadingDependencies,
265-
};
266-
267182
private:
268183
/// A stack of dependency sources in the order they were evaluated.
269184
llvm::SmallVector<evaluator::DependencySource, 8> dependencySources;
270185
llvm::DenseMap<SourceFile *, DependencyCollector::ReferenceSet>
271186
fileReferences;
272187
llvm::DenseMap<AnyRequest, DependencyCollector::ReferenceSet>
273188
requestReferences;
274-
Mode mode;
275189
bool isRecording;
276190

277191
public:
278-
explicit DependencyRecorder(Mode mode) : mode{mode}, isRecording{false} {};
192+
explicit DependencyRecorder() : isRecording{false} {};
279193

280194
private:
281195
/// Records the given \c Reference as a dependency of the current dependency
@@ -338,32 +252,17 @@ struct DependencyRecorder {
338252
ReferenceEnumerator f) const ;
339253

340254
public:
341-
/// Returns the scope of the current active scope.
342-
///
343-
/// If there is no active scope, the result always cascades.
344-
evaluator::DependencyScope getActiveSourceScope() const {
345-
if (dependencySources.empty()) {
346-
return evaluator::DependencyScope::Cascading;
347-
}
348-
return dependencySources.back().getInt();
349-
}
350-
351255
/// Returns the active dependency's source file, or \c nullptr if no
352256
/// dependency source is active.
353257
///
354258
/// The use of this accessor is strongly discouraged, as it implies that a
355259
/// dependency sink is seeking to filter out names based on the files they
356260
/// come from. Existing callers are being migrated to more reasonable ways
357261
/// of judging the relevancy of a dependency.
358-
SourceFile *getActiveDependencySourceOrNull() const {
262+
evaluator::DependencySource getActiveDependencySourceOrNull() const {
359263
if (dependencySources.empty())
360264
return nullptr;
361-
switch (mode) {
362-
case Mode::LegacyCascadingDependencies:
363-
return dependencySources.back().getPointer();
364-
case Mode::DirectDependencies:
365-
return dependencySources.front().getPointer();
366-
}
265+
return dependencySources.front();
367266
}
368267

369268
public:
@@ -382,7 +281,7 @@ struct DependencyRecorder {
382281
auto Source = Req.readDependencySource(coll);
383282
// If there is no source to introduce, bail. This can occur if
384283
// a request originates in the context of a module.
385-
if (!Source.getPointer()) {
284+
if (Source.isNull() || !Source.get()->isPrimary()) {
386285
return;
387286
}
388287
coll.dependencySources.emplace_back(Source);
@@ -394,20 +293,6 @@ struct DependencyRecorder {
394293
Coll.get()->dependencySources.pop_back();
395294
}
396295
};
397-
398-
private:
399-
/// Returns \c true if the scope of the current active source cascades.
400-
///
401-
/// If there is no active scope, the result always cascades.
402-
bool isActiveSourceCascading() const {
403-
switch (mode) {
404-
case Mode::LegacyCascadingDependencies:
405-
return getActiveSourceScope() == evaluator::DependencyScope::Cascading;
406-
case Mode::DirectDependencies:
407-
return false;
408-
}
409-
llvm_unreachable("invalid mode");
410-
}
411296
};
412297
} // end namespace evaluator
413298

0 commit comments

Comments
 (0)