Skip to content

Commit c2a275e

Browse files
committed
AST: Factor out GenericSignature::getLocalRequirements() method
This encapsulates GenericEnvironment's usage of the GSB.
1 parent ba82053 commit c2a275e

File tree

4 files changed

+91
-57
lines changed

4 files changed

+91
-57
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+
SmallVector<ProtocolDecl *, 2> 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());

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);

lib/AST/GenericSignature.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,53 @@ GenericEnvironment *GenericSignatureImpl::getGenericEnvironment() const {
254254
return GenericEnv;
255255
}
256256

257+
GenericSignature::LocalRequirements
258+
GenericSignatureImpl::getLocalRequirements(Type depType) const {
259+
assert(depType->isTypeParameter() && "Expected a type parameter here");
260+
261+
GenericSignature::LocalRequirements result;
262+
263+
auto &builder = *getGenericSignatureBuilder();
264+
265+
auto resolved =
266+
builder.maybeResolveEquivalenceClass(
267+
depType,
268+
ArchetypeResolutionKind::CompleteWellFormed,
269+
/*wantExactPotentialArchetype=*/false);
270+
if (!resolved) {
271+
result.concreteType = ErrorType::get(depType);
272+
return result;
273+
}
274+
275+
if (auto concreteType = resolved.getAsConcreteType()) {
276+
result.concreteType = concreteType;
277+
return result;
278+
}
279+
280+
auto *equivClass = resolved.getEquivalenceClass(builder);
281+
282+
auto genericParams = getGenericParams();
283+
result.anchor = equivClass->getAnchor(builder, genericParams);
284+
285+
if (equivClass->concreteType) {
286+
result.concreteType = equivClass->concreteType;
287+
return result;
288+
}
289+
290+
result.superclass = equivClass->superclass;
291+
292+
for (const auto &conforms : equivClass->conformsTo) {
293+
auto proto = conforms.first;
294+
295+
if (!equivClass->isConformanceSatisfiedBySuperclass(proto))
296+
result.protos.push_back(proto);
297+
}
298+
299+
result.layout = equivClass->layout;
300+
301+
return result;
302+
}
303+
257304
ASTContext &GenericSignatureImpl::getASTContext() const {
258305
// Canonical signatures store the ASTContext directly.
259306
if (auto ctx = CanonicalSignatureOrASTContext.dyn_cast<ASTContext *>())

0 commit comments

Comments
 (0)