Skip to content

Commit 4923521

Browse files
committed
AST: Re-implement GenericEnvironment::mapTypeIntoContext() using TypeTransform
1 parent a19ee63 commit 4923521

File tree

5 files changed

+148
-101
lines changed

5 files changed

+148
-101
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,14 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
157157
friend ArchetypeType;
158158
friend QueryInterfaceTypeSubstitutions;
159159

160-
/// Add a mapping of a generic parameter to a specific type (which may be
161-
/// an archetype)
162-
void addMapping(GenericParamKey key, Type contextType);
160+
/// Add a mapping of a type parameter to a contextual type, usually
161+
/// an archetype.
162+
void addMapping(CanType depType, Type contextType);
163163

164-
/// Retrieve the mapping for the given generic parameter, if present.
164+
/// Retrieve the mapping for the given type parameter, if present.
165165
///
166166
/// This is only useful when lazily populating a generic environment.
167-
std::optional<Type> getMappingIfPresent(GenericParamKey key) const;
167+
Type getMappingIfPresent(CanType depType) const;
168168

169169
public:
170170
GenericSignature getGenericSignature() const {

lib/AST/GenericEnvironment.cpp

Lines changed: 131 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/ASTContext.h"
2020
#include "swift/AST/ExistentialLayout.h"
2121
#include "swift/AST/ProtocolConformance.h"
22+
#include "swift/AST/TypeTransform.h"
2223
#include "swift/Basic/Assertions.h"
2324
#include "swift/Basic/Defer.h"
2425

@@ -262,33 +263,49 @@ GenericEnvironment::GenericEnvironment(GenericSignature signature,
262263
assert(i == openedPacksBuffer.size());
263264
}
264265

265-
void GenericEnvironment::addMapping(GenericParamKey key,
266-
Type contextType) {
267-
// Find the index into the parallel arrays of generic parameters and
268-
// context types.
269-
auto genericParams = getGenericParams();
270-
unsigned index = key.findIndexIn(genericParams);
271-
assert(genericParams[index] == key && "Bad generic parameter");
266+
class GenericEnvironment::NestedTypeStorage
267+
: public llvm::DenseMap<CanType, Type> { };
268+
269+
void GenericEnvironment::addMapping(CanType depType, Type contextType) {
270+
if (auto genericParam = dyn_cast<GenericTypeParamType>(depType)) {
271+
GenericParamKey key(genericParam);
272272

273-
// Add the mapping from the generic parameter to the context type.
274-
assert(getContextTypes()[index].isNull() ||
275-
getContextTypes()[index]->is<ErrorType>() &&
276-
"Already recoded this mapping");
277-
getContextTypes()[index] = contextType;
273+
// Find the index into the parallel arrays of generic parameters and
274+
// context types.
275+
auto genericParams = getGenericParams();
276+
unsigned index = key.findIndexIn(genericParams);
277+
assert(genericParams[index] == key && "Bad generic parameter");
278+
279+
// Add the mapping from the generic parameter to the context type.
280+
assert(getContextTypes()[index].isNull() ||
281+
getContextTypes()[index]->is<ErrorType>() &&
282+
"Already recoded this mapping");
283+
getContextTypes()[index] = contextType;
284+
} else {
285+
getOrCreateNestedTypeStorage()[depType] = contextType;
286+
}
278287
}
279288

280-
std::optional<Type>
281-
GenericEnvironment::getMappingIfPresent(GenericParamKey key) const {
282-
// Find the index into the parallel arrays of generic parameters and
283-
// context types.
284-
auto genericParams = getGenericParams();
285-
unsigned index = key.findIndexIn(genericParams);
286-
assert(genericParams[index] == key && "Bad generic parameter");
289+
Type GenericEnvironment::getMappingIfPresent(CanType depType) const {
290+
if (auto genericParam = dyn_cast<GenericTypeParamType>(depType)) {
291+
GenericParamKey key(genericParam);
287292

288-
if (auto type = getContextTypes()[index])
289-
return type;
293+
// Find the index into the parallel arrays of generic parameters and
294+
// context types.
295+
auto genericParams = getGenericParams();
296+
unsigned index = key.findIndexIn(genericParams);
297+
assert(genericParams[index] == key && "Bad generic parameter");
290298

291-
return std::nullopt;
299+
return getContextTypes()[index];
300+
} else {
301+
auto &storage = const_cast<GenericEnvironment *>(this)
302+
->getOrCreateNestedTypeStorage();
303+
auto found = storage.find(depType);
304+
if (found != storage.end())
305+
return found->second;
306+
307+
return Type();
308+
}
292309
}
293310

294311
Type
@@ -337,9 +354,6 @@ Type TypeBase::mapTypeOutOfContext() {
337354
SubstFlags::SubstitutePrimaryArchetypes);
338355
}
339356

340-
class GenericEnvironment::NestedTypeStorage
341-
: public llvm::DenseMap<CanType, Type> { };
342-
343357
auto GenericEnvironment::getOrCreateNestedTypeStorage() -> NestedTypeStorage & {
344358
if (nestedTypeStorage)
345359
return *nestedTypeStorage;
@@ -355,35 +369,41 @@ auto GenericEnvironment::getOrCreateNestedTypeStorage() -> NestedTypeStorage & {
355369

356370
Type
357371
GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
372+
auto canType = depType->getCanonicalType();
373+
374+
// Have we seen this exact type parameter before?
375+
if (auto type = getMappingIfPresent(canType))
376+
return type;
377+
358378
auto genericSig = getGenericSignature();
359-
auto requirements = genericSig->getLocalRequirements(depType);
360379

361-
if (requirements.concreteType)
362-
return mapTypeIntoContext(requirements.concreteType);
380+
// Reduce it.
381+
auto reducedType = genericSig.getReducedType(canType);
363382

364-
assert(requirements.anchor && "No anchor or concrete type?");
383+
// If this type parameter is equivalent to a concrete type,
384+
// map the concrete type into context and cache the result.
385+
if (!reducedType->isTypeParameter()) {
386+
auto result = mapTypeIntoContext(reducedType);
387+
addMapping(canType, result);
388+
return result;
389+
}
365390

366391
auto &ctx = genericSig->getASTContext();
367392

368-
// First, write an ErrorType to the location where this type is cached,
369-
// to catch re-entrant lookups that might arise from an invalid generic
370-
// signature (eg, <X where X == Array<X>>).
371-
CanDependentMemberType nestedType;
372-
GenericTypeParamType *genericParam = nullptr;
373-
if (auto depMemTy = requirements.anchor->getAs<DependentMemberType>()) {
374-
nestedType = cast<DependentMemberType>(depMemTy->getCanonicalType());
375-
auto &entry = getOrCreateNestedTypeStorage()[nestedType];
376-
if (entry)
377-
return entry;
378-
379-
entry = ErrorType::get(ctx);
380-
} else {
381-
genericParam = requirements.anchor->castTo<GenericTypeParamType>();
382-
if (auto type = getMappingIfPresent(genericParam))
383-
return *type;
384-
addMapping(genericParam, ErrorType::get(ctx));
393+
// If the original type parameter was not reduced, see if we have an
394+
// archetype for the reduced type parameter.
395+
if (canType != reducedType) {
396+
if (auto type = getMappingIfPresent(reducedType)) {
397+
// Cache the result.
398+
addMapping(canType, type);
399+
return type;
400+
}
385401
}
386402

403+
// Otherwise, we're going to create a new archetype. Look up its
404+
// requirements.
405+
auto requirements = genericSig->getLocalRequirements(reducedType);
406+
387407
// Substitute into the superclass.
388408
Type superclass = requirements.superclass;
389409
if (superclass && superclass->hasTypeParameter()) {
@@ -394,16 +414,18 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
394414

395415
Type result;
396416

397-
auto rootGP = requirements.anchor->getRootGenericParam();
417+
auto sugaredType = genericSig->getSugaredType(reducedType);
418+
419+
auto rootGP = reducedType->getRootGenericParam();
398420
switch (getKind()) {
399421
case Kind::Primary:
400422
if (rootGP->isParameterPack()) {
401-
result = PackArchetypeType::get(ctx, this, requirements.anchor,
423+
result = PackArchetypeType::get(ctx, this, sugaredType,
402424
requirements.packShape,
403425
requirements.protos, superclass,
404426
requirements.layout);
405427
} else {
406-
result = PrimaryArchetypeType::getNew(ctx, this, requirements.anchor,
428+
result = PrimaryArchetypeType::getNew(ctx, this, sugaredType,
407429
requirements.protos, superclass,
408430
requirements.layout);
409431
}
@@ -415,19 +437,19 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
415437
// represents an opaque declaration, then apply the outer substitutions.
416438
// It would be incorrect to build an opaque type archetype here.
417439
if (rootGP->getDepth() < genericSig->getMaxDepth()) {
418-
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
440+
result = maybeApplyOuterContextSubstitutions(reducedType);
419441
break;
420442
}
421443

422-
result = OpaqueTypeArchetypeType::getNew(this, requirements.anchor,
444+
result = OpaqueTypeArchetypeType::getNew(this, sugaredType,
423445
requirements.protos, superclass,
424446
requirements.layout);
425447
break;
426448
}
427449

428450
case Kind::OpenedExistential: {
429451
if (rootGP->getDepth() < genericSig->getMaxDepth()) {
430-
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
452+
result = maybeApplyOuterContextSubstitutions(reducedType);
431453
break;
432454
}
433455

@@ -439,16 +461,16 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
439461
// For compatibility, continue using the existential layout's version when
440462
// the interface type is a generic parameter. We should align these at
441463
// some point.
442-
if (depType->is<GenericTypeParamType>()) {
464+
if (isa<GenericTypeParamType>(reducedType)) {
443465
auto layout = getOpenedExistentialType()->getExistentialLayout();
444466
SmallVector<ProtocolDecl *, 2> protos;
445467
for (auto proto : layout.getProtocols())
446468
protos.push_back(proto);
447469

448-
result = OpenedArchetypeType::getNew(this, requirements.anchor, protos,
470+
result = OpenedArchetypeType::getNew(this, sugaredType, protos,
449471
superclass, requirements.layout);
450472
} else {
451-
result = OpenedArchetypeType::getNew(this, requirements.anchor,
473+
result = OpenedArchetypeType::getNew(this, sugaredType,
452474
requirements.protos, superclass,
453475
requirements.layout);
454476
}
@@ -458,71 +480,87 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
458480

459481
case Kind::OpenedElement: {
460482
if (rootGP->getDepth() < genericSig->getMaxDepth()) {
461-
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
483+
result = maybeApplyOuterContextSubstitutions(reducedType);
462484
break;
463485
}
464486

465-
result = ElementArchetypeType::getNew(this, requirements.anchor,
487+
result = ElementArchetypeType::getNew(this, sugaredType,
466488
requirements.protos, superclass,
467489
requirements.layout);
468490
break;
469491
}
470492
}
471493

472-
if (genericParam)
473-
addMapping(genericParam, result);
474-
else
475-
getOrCreateNestedTypeStorage()[nestedType] = result;
494+
// Cache the result.
495+
addMapping(canType, result);
496+
if (canType != reducedType)
497+
addMapping(reducedType, result);
476498

477499
return result;
478500
}
479501

480502
Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
481-
if (auto gp = type->getAs<GenericTypeParamType>()) {
482-
// Find the index into the parallel arrays of generic parameters and
483-
// context types.
484-
auto genericParams = self->getGenericParams();
485-
GenericParamKey key(gp);
503+
auto gp = type->castTo<GenericTypeParamType>();
486504

487-
// Make sure that this generic parameter is from this environment.
488-
unsigned index = key.findIndexIn(genericParams);
489-
if (index == genericParams.size() || genericParams[index] != key)
490-
return Type();
505+
// Find the index into the parallel arrays of generic parameters and
506+
// context types.
507+
auto genericParams = self->getGenericParams();
508+
GenericParamKey key(gp);
491509

492-
// If the context type isn't already known, lazily create it.
493-
auto mutableSelf = const_cast<GenericEnvironment *>(self);
494-
Type &contextType = mutableSelf->getContextTypes()[index];
495-
if (contextType)
496-
return contextType;
510+
// Make sure that this generic parameter is from this environment and
511+
// return substitution failure if not.
512+
unsigned index = key.findIndexIn(genericParams);
513+
if (index == genericParams.size())
514+
return Type();
497515

498-
auto result = mutableSelf->getOrCreateArchetypeFromInterfaceType(type);
516+
// If the context type isn't already known, lazily create it.
517+
if (auto contextType = self->getContextTypes()[index])
518+
return contextType;
499519

500-
assert (!contextType ||
501-
contextType->isEqual(result) ||
502-
contextType->is<ErrorType>());
503-
contextType = result;
504-
return result;
520+
return const_cast<GenericEnvironment *>(self)
521+
->getOrCreateArchetypeFromInterfaceType(gp);
522+
}
523+
524+
namespace {
525+
526+
struct MapTypeIntoContext: TypeTransform<MapTypeIntoContext> {
527+
GenericEnvironment *env;
528+
529+
explicit MapTypeIntoContext(GenericEnvironment *env) : env(env) {}
530+
531+
std::optional<Type> transform(TypeBase *type, TypePosition pos) {
532+
if (!type->hasTypeParameter())
533+
return Type(type);
534+
535+
return std::nullopt;
505536
}
506537

507-
return Type();
538+
Type transformGenericTypeParamType(GenericTypeParamType *param,
539+
TypePosition pos) {
540+
return env->getOrCreateArchetypeFromInterfaceType(param);
541+
}
542+
543+
Type transformDependentMemberType(DependentMemberType *dependent,
544+
TypePosition pos) {
545+
return env->getOrCreateArchetypeFromInterfaceType(dependent);
546+
}
547+
548+
CanType transformSILField(CanType fieldTy, TypePosition pos) {
549+
return fieldTy;
550+
}
551+
};
552+
508553
}
509554

510555
Type GenericEnvironment::mapTypeIntoContext(Type type) const {
511556
assert(!type->hasPrimaryArchetype() && "already have a contextual type");
512-
513-
Type result = type.subst(QueryInterfaceTypeSubstitutions(this),
514-
LookUpConformanceInModule(),
515-
SubstFlags::PreservePackExpansionLevel);
516-
ASSERT(getKind() != Kind::Primary || !result->hasTypeParameter());
517-
return result;
557+
return MapTypeIntoContext(const_cast<GenericEnvironment *>(this))
558+
.doIt(type, TypePosition::Invariant);
518559
}
519560

520561
Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
521-
auto self = const_cast<GenericEnvironment *>(this);
522-
Type result = QueryInterfaceTypeSubstitutions(self)(type);
523-
if (!result)
524-
return ErrorType::get(type);
525-
return result;
562+
return const_cast<GenericEnvironment *>(this)
563+
->getOrCreateArchetypeFromInterfaceType(type);
526564
}
527565

528566
namespace {

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2051,7 +2051,7 @@ static void bindArchetypesFromContext(
20512051
// Find the innermost non-type context.
20522052
for (const auto *parentDC = outerDC;
20532053
!parentDC->isModuleScopeContext();
2054-
parentDC = parentDC->getParent()) {
2054+
parentDC = parentDC->getParentForLookup()) {
20552055
if (parentDC->isTypeContext()) {
20562056
if (parentDC != outerDC && parentDC->getSelfProtocolDecl()) {
20572057
auto selfTy = parentDC->getSelfInterfaceType();

lib/Sema/IDETypeCheckingRequests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ static bool isMemberDeclAppliedInternal(const DeclContext *DC, Type BaseTy,
203203
// The context substitution map for the base type fixes the declaration's
204204
// outer generic parameters.
205205
auto substMap = BaseTy->getContextSubstitutionMap(
206-
VD->getDeclContext(), genericDecl->getGenericEnvironment());
206+
VD->getDeclContext(),
207+
VD->getDeclContext()->getGenericEnvironmentOfContext());
207208

208209
// The innermost generic parameters are mapped to error types.
209210
unsigned innerDepth = genericSig->getMaxDepth();

lib/Sema/TypeCheckType.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,15 @@ Type TypeResolution::applyUnboundGenericArguments(
12201220
if (result->hasTypeParameter()) {
12211221
if (const auto contextSig = getGenericSignature()) {
12221222
auto *genericEnv = contextSig.getGenericEnvironment();
1223-
return genericEnv->mapTypeIntoContext(result);
1223+
// FIXME: This should just use mapTypeIntoContext(), but we can't yet
1224+
// because we sometimes have type parameters here that are invalid for
1225+
// our generic signature. This can happen if the type parameter was
1226+
// found via unqualified lookup, but the current context's
1227+
// generic signature failed to build because of circularity or
1228+
// completion failure.
1229+
return result.subst(QueryInterfaceTypeSubstitutions{genericEnv},
1230+
LookUpConformanceInModule(),
1231+
SubstFlags::PreservePackExpansionLevel);
12241232
}
12251233
}
12261234
return result;

0 commit comments

Comments
 (0)