Skip to content

Commit b6ffc85

Browse files
authored
Merge pull request #38457 from slavapestov/requirement-machine-archetypes
Use RequirementMachine to build archetypes when enabled
2 parents 62c62bb + 02db632 commit b6ffc85

25 files changed

+1181
-813
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
namespace swift {
3232

3333
class ArchetypeType;
34-
class GenericSignatureBuilder;
3534
class ASTContext;
3635
class GenericTypeParamType;
3736
class SILModule;
@@ -60,7 +59,6 @@ class QueryInterfaceTypeSubstitutions {
6059
class alignas(1 << DeclAlignInBits) GenericEnvironment final
6160
: private llvm::TrailingObjects<GenericEnvironment, Type> {
6261
GenericSignature Signature = GenericSignature();
63-
GenericSignatureBuilder *Builder = nullptr;
6462

6563
friend TrailingObjects;
6664

@@ -79,10 +77,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
7977
explicit GenericEnvironment(GenericSignature signature);
8078

8179
friend ArchetypeType;
82-
friend GenericSignatureBuilder;
83-
84-
GenericSignatureBuilder *getGenericSignatureBuilder() const;
85-
8680
friend QueryInterfaceTypeSubstitutions;
8781

8882
Type getOrCreateArchetypeFromInterfaceType(Type depType);

include/swift/AST/GenericSignature.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,18 @@ class GenericSignature {
165165
public:
166166
using RequiredProtocols = SmallVector<ProtocolDecl *, 2>;
167167

168+
/// Stores a set of requirements on a type parameter. Used by
169+
/// GenericEnvironment for building archetypes.
170+
struct LocalRequirements {
171+
Type anchor;
172+
173+
Type concreteType;
174+
Type superclass;
175+
176+
RequiredProtocols protos;
177+
LayoutConstraint layout;
178+
};
179+
168180
private:
169181
// Direct comparison is disabled for generic signatures. Canonicalize them
170182
// first, or use isEqual.
@@ -314,6 +326,10 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
314326
/// signature.
315327
GenericEnvironment *getGenericEnvironment() const;
316328

329+
/// Collects a set of requirements on a type parameter. Used by
330+
/// GenericEnvironment for building archetypes.
331+
GenericSignature::LocalRequirements getLocalRequirements(Type depType) const;
332+
317333
/// Uniquing for the ASTContext.
318334
void Profile(llvm::FoldingSetNodeID &ID) const {
319335
Profile(ID, getGenericParams(), getRequirements());

include/swift/AST/RequirementMachine.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class raw_ostream;
2121

2222
namespace swift {
2323

24+
namespace rewriting {
25+
class RewriteContext;
26+
}
27+
2428
class ASTContext;
2529
class AssociatedTypeDecl;
2630
class CanType;
@@ -40,7 +44,7 @@ class RequirementMachine final {
4044
ASTContext &Context;
4145
Implementation *Impl;
4246

43-
explicit RequirementMachine(ASTContext &ctx);
47+
explicit RequirementMachine(rewriting::RewriteContext &rewriteCtx);
4448

4549
RequirementMachine(const RequirementMachine &) = delete;
4650
RequirementMachine(RequirementMachine &&) = delete;
@@ -58,6 +62,8 @@ class RequirementMachine final {
5862
// Generic signature queries. Generally you shouldn't have to construct a
5963
// RequirementMachine instance; instead, call the corresponding methods on
6064
// GenericSignature, which lazily create a RequirementMachine for you.
65+
GenericSignature::LocalRequirements getLocalRequirements(Type depType,
66+
TypeArrayView<GenericTypeParamType> genericParams) const;
6167
bool requiresClass(Type depType) const;
6268
LayoutConstraint getLayoutConstraint(Type depType) const;
6369
bool requiresProtocol(Type depType, const ProtocolDecl *proto) const;

include/swift/Basic/LangOptions.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ namespace swift {
7878
ErrorOnFailureRemarkOnSuccess
7979
};
8080

81+
/// Value for LangOptions::EnableRequirementMachine.
82+
enum class RequirementMachineMode {
83+
/// Use the GenericSignatureBuilder for all queries.
84+
Disabled = 0,
85+
86+
/// Use the RequirementMachine for all queries.
87+
Enabled = 1,
88+
89+
/// Use both and assert if the results do not match.
90+
Verify = 2
91+
};
92+
8193
/// A collection of options that affect the language dialect and
8294
/// provide compiler debugging facilities.
8395
class LangOptions final {
@@ -446,7 +458,8 @@ namespace swift {
446458
ASTVerifierOverrideKind::NoOverride;
447459

448460
/// Whether the new experimental generics implementation is enabled.
449-
bool EnableRequirementMachine = false;
461+
RequirementMachineMode EnableRequirementMachine =
462+
RequirementMachineMode::Disabled;
450463

451464
/// Enables debugging output from the requirement machine.
452465
bool DebugRequirementMachine = false;

include/swift/Option/FrontendOptions.td

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,8 @@ def debug_constraints_on_line_EQ : Joined<["-"], "debug-constraints-on-line=">,
277277
def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
278278
HelpText<"Disable per-name lazy member loading">;
279279

280-
def enable_requirement_machine : Flag<["-"], "enable-requirement-machine">,
281-
HelpText<"Enable experimental generics implementation">;
282-
283-
def disable_requirement_machine : Flag<["-"], "disable-requirement-machine">,
284-
HelpText<"Disable experimental generics implementation">;
280+
def requirement_machine_EQ : Joined<["-"], "requirement-machine=">,
281+
HelpText<"Control usage of experimental generics implementation: 'on', 'off', or 'verify'">;
285282

286283
def debug_requirement_machine : Flag<["-"], "debug-requirement-machine">,
287284
HelpText<"Enables debugging output from the generics implementation">;

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
#include <algorithm>
6868
#include <memory>
6969

70+
#include "RequirementMachine/RewriteContext.h"
71+
7072
using namespace swift;
7173

7274
#define DEBUG_TYPE "ASTContext"
@@ -531,6 +533,9 @@ struct ASTContext::Implementation {
531533
/// The scratch context used to allocate intrinsic data on behalf of \c swift::IntrinsicInfo
532534
std::unique_ptr<llvm::LLVMContext> IntrinsicScratchContext;
533535
#endif
536+
537+
/// Memory allocation arena for the term rewriting system.
538+
std::unique_ptr<rewriting::RewriteContext> TheRewriteContext;
534539
};
535540

536541
ASTContext::Implementation::Implementation()
@@ -1771,15 +1776,20 @@ static AllocationArena getArena(GenericSignature genericSig) {
17711776
if (!genericSig)
17721777
return AllocationArena::Permanent;
17731778

1774-
if (genericSig->hasTypeVariable())
1779+
if (genericSig->hasTypeVariable()) {
1780+
assert(false && "What's going on");
17751781
return AllocationArena::ConstraintSolver;
1782+
}
17761783

17771784
return AllocationArena::Permanent;
17781785
}
17791786

17801787
void ASTContext::registerGenericSignatureBuilder(
17811788
GenericSignature sig,
17821789
GenericSignatureBuilder &&builder) {
1790+
if (LangOpts.EnableRequirementMachine == RequirementMachineMode::Enabled)
1791+
return;
1792+
17831793
auto canSig = sig.getCanonicalSignature();
17841794
auto arena = getArena(sig);
17851795
auto &genericSignatureBuilders =
@@ -1797,9 +1807,11 @@ void ASTContext::registerGenericSignatureBuilder(
17971807

17981808
GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
17991809
CanGenericSignature sig) {
1800-
if (LangOpts.EnableRequirementMachine) {
1801-
(void) getOrCreateRequirementMachine(sig);
1802-
}
1810+
// We should only create GenericSignatureBuilders if the requirement machine
1811+
// mode is ::Disabled or ::Verify.
1812+
assert(LangOpts.EnableRequirementMachine != RequirementMachineMode::Enabled &&
1813+
"Shouldn't create GenericSignatureBuilder when RequirementMachine "
1814+
"is enabled");
18031815

18041816
// Check whether we already have a generic signature builder for this
18051817
// signature and module.
@@ -1883,6 +1895,12 @@ GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
18831895

18841896
RequirementMachine *ASTContext::getOrCreateRequirementMachine(
18851897
CanGenericSignature sig) {
1898+
assert(!sig->hasTypeVariable());
1899+
1900+
auto &rewriteCtx = getImpl().TheRewriteContext;
1901+
if (!rewriteCtx)
1902+
rewriteCtx.reset(new rewriting::RewriteContext(*this));
1903+
18861904
// Check whether we already have a requirement machine for this
18871905
// signature.
18881906
auto arena = getArena(sig);
@@ -1900,12 +1918,12 @@ RequirementMachine *ASTContext::getOrCreateRequirementMachine(
19001918
return machine;
19011919
}
19021920

1903-
auto *machine = new RequirementMachine(*this);
1921+
auto *machine = new RequirementMachine(*rewriteCtx);
19041922

19051923
// Store this requirement machine before adding the signature,
19061924
// to catch re-entrant construction via addGenericSignature()
19071925
// below.
1908-
machinePtr = std::unique_ptr<RequirementMachine>(machine);
1926+
machinePtr.reset(machine);
19091927

19101928
machine->addGenericSignature(sig);
19111929

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ add_swift_host_library(swiftAST STATIC
7474
RawComment.cpp
7575
RequirementEnvironment.cpp
7676
RequirementMachine/EquivalenceClassMap.cpp
77+
RequirementMachine/GenericSignatureQueries.cpp
7778
RequirementMachine/ProtocolGraph.cpp
7879
RequirementMachine/RequirementMachine.cpp
7980
RequirementMachine/RewriteContext.cpp

lib/AST/GenericEnvironment.cpp

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "swift/AST/GenericEnvironment.h"
18+
#include "swift/AST/GenericSignature.h"
1819
#include "swift/AST/ASTContext.h"
19-
#include "swift/AST/GenericSignatureBuilder.h"
2020
#include "swift/AST/ProtocolConformance.h"
2121
#include "swift/Basic/Defer.h"
22-
#include "GenericSignatureBuilderImpl.h"
2322

2423
using namespace swift;
2524

@@ -56,16 +55,6 @@ GenericEnvironment::GenericEnvironment(GenericSignature signature)
5655
Type());
5756
}
5857

59-
GenericSignatureBuilder *GenericEnvironment::getGenericSignatureBuilder() const {
60-
if (Builder)
61-
return Builder;
62-
63-
const_cast<GenericEnvironment *>(this)->Builder
64-
= Signature->getGenericSignatureBuilder();
65-
66-
return Builder;
67-
}
68-
6958
void GenericEnvironment::addMapping(GenericParamKey key,
7059
Type contextType) {
7160
// Find the index into the parallel arrays of generic parameters and
@@ -122,33 +111,30 @@ Type TypeBase::mapTypeOutOfContext() {
122111

123112
Type
124113
GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
125-
auto &builder = *getGenericSignatureBuilder();
126-
auto &ctx = builder.getASTContext();
127-
128-
auto resolved =
129-
builder.maybeResolveEquivalenceClass(
130-
depType,
131-
ArchetypeResolutionKind::CompleteWellFormed,
132-
/*wantExactPotentialArchetype=*/false);
133-
if (!resolved)
134-
return ErrorType::get(depType);
135-
136-
if (auto concrete = resolved.getAsConcreteType()) {
137-
return mapTypeIntoContext(concrete,
138-
builder.getLookupConformanceFn());
114+
auto genericSig = getGenericSignature();
115+
LookUpConformanceInSignature conformanceLookupFn(genericSig.getPointer());
116+
117+
auto requirements = genericSig->getLocalRequirements(depType);
118+
119+
// FIXME: With the RequirementMachine, we will always have an anchor.
120+
if (requirements.concreteType && !requirements.anchor) {
121+
if (requirements.concreteType->is<ErrorType>())
122+
return requirements.concreteType;
123+
124+
return mapTypeIntoContext(requirements.concreteType,
125+
conformanceLookupFn);
139126
}
140127

141-
auto *equivClass = resolved.getEquivalenceClass(builder);
128+
assert(requirements.anchor && "No anchor or concrete type?");
142129

143-
auto genericParams = getGenericParams();
144-
Type anchor = equivClass->getAnchor(builder, genericParams);
130+
auto &ctx = genericSig->getASTContext();
145131

146132
// First, write an ErrorType to the location where this type is cached,
147133
// to catch re-entrant lookups that might arise from an invalid generic
148134
// signature (eg, <X where X == Array<X>>).
149135
ArchetypeType *parentArchetype = nullptr;
150136
GenericTypeParamType *genericParam = nullptr;
151-
if (auto depMemTy = anchor->getAs<DependentMemberType>()) {
137+
if (auto depMemTy = requirements.anchor->getAs<DependentMemberType>()) {
152138
parentArchetype =
153139
getOrCreateArchetypeFromInterfaceType(depMemTy->getBase())
154140
->getAs<ArchetypeType>();
@@ -161,7 +147,7 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
161147

162148
parentArchetype->registerNestedType(name, ErrorType::get(ctx));
163149
} else {
164-
genericParam = anchor->castTo<GenericTypeParamType>();
150+
genericParam = requirements.anchor->castTo<GenericTypeParamType>();
165151
if (auto type = getMappingIfPresent(genericParam))
166152
return *type;
167153
addMapping(genericParam, ErrorType::get(ctx));
@@ -171,42 +157,33 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
171157

172158
// If this equivalence class is mapped to a concrete type, produce that
173159
// type.
174-
if (equivClass->concreteType) {
175-
result = mapTypeIntoContext(equivClass->concreteType,
176-
builder.getLookupConformanceFn());
160+
if (requirements.concreteType) {
161+
result = mapTypeIntoContext(requirements.concreteType,
162+
conformanceLookupFn);
177163
} else {
178164
// Substitute into the superclass.
179-
Type superclass = equivClass->superclass;
165+
Type superclass = requirements.superclass;
180166
if (superclass && superclass->hasTypeParameter()) {
181167
superclass = mapTypeIntoContext(superclass,
182-
builder.getLookupConformanceFn());
168+
conformanceLookupFn);
183169
if (superclass->is<ErrorType>())
184170
superclass = Type();
185171
}
186172

187-
// Collect the protocol conformances for the archetype.
188-
SmallVector<ProtocolDecl *, 4> protos;
189-
for (const auto &conforms : equivClass->conformsTo) {
190-
auto proto = conforms.first;
191-
192-
if (!equivClass->isConformanceSatisfiedBySuperclass(proto))
193-
protos.push_back(proto);
194-
}
195-
196173
if (parentArchetype) {
197-
auto *depMemTy = anchor->castTo<DependentMemberType>();
174+
auto *depMemTy = requirements.anchor->castTo<DependentMemberType>();
198175
result = NestedArchetypeType::getNew(ctx, parentArchetype, depMemTy,
199-
protos, superclass,
200-
equivClass->layout);
176+
requirements.protos, superclass,
177+
requirements.layout);
201178
} else {
202179
result = PrimaryArchetypeType::getNew(ctx, this, genericParam,
203-
protos, superclass,
204-
equivClass->layout);
180+
requirements.protos, superclass,
181+
requirements.layout);
205182
}
206183
}
207184

208185
// Cache the new archetype for future lookups.
209-
if (auto depMemTy = anchor->getAs<DependentMemberType>()) {
186+
if (auto depMemTy = requirements.anchor->getAs<DependentMemberType>()) {
210187
parentArchetype->registerNestedType(depMemTy->getName(), result);
211188
} else {
212189
addMapping(genericParam, result);

0 commit comments

Comments
 (0)