Skip to content

Commit ec1a218

Browse files
authored
Merge pull request #3252 from slavapestov/cleanup-map-type-in-and-out-of-context
Cleanup mapType{Into,OutOf}Context()
2 parents 1e85e1b + f038281 commit ec1a218

29 files changed

+363
-404
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3212,9 +3212,7 @@ class ClassDecl : public NominalTypeDecl {
32123212
ClassDecl *getSuperclassDecl() const;
32133213

32143214
/// Set the superclass of this class.
3215-
void setSuperclass(Type superclass) {
3216-
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
3217-
}
3215+
void setSuperclass(Type superclass);
32183216

32193217
/// Retrieve the status of circularity checking for class inheritance.
32203218
CircularityCheck getCircularityCheck() const {

include/swift/AST/ParameterList.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,14 @@ class alignas(ParamDecl *) ParameterList final :
142142
/// null type if one of the ParamDecls does not have a type set for it yet.
143143
Type getType(const ASTContext &C) const;
144144

145+
/// Return a TupleType or ParenType for this parameter list written in terms
146+
/// of interface types.
147+
Type getInterfaceType(DeclContext *DC) const;
148+
145149
/// Return the full function type for a set of curried parameter lists that
146-
/// returns the specified result type. This returns a null type if one of the
147-
/// ParamDecls does not have a type set for it yet.
148-
///
149-
static Type getFullType(Type resultType, ArrayRef<ParameterList*> PL);
150+
/// returns the specified result type written in terms of interface types.
151+
static Type getFullInterfaceType(Type resultType, ArrayRef<ParameterList*> PL,
152+
DeclContext *DC);
150153

151154

152155
/// Return the full source range of this parameter.

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2622,8 +2622,6 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
26222622
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
26232623
llvm::FoldingSetNodeID ID;
26242624
RecursiveTypeProperties properties;
2625-
if (Parent)
2626-
properties |= Parent->getRecursiveProperties();
26272625
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs, properties);
26282626

26292627
auto arena = getArena(properties);
@@ -2657,8 +2655,8 @@ BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
26572655
} else {
26582656
auto theEnum = cast<EnumDecl>(TheDecl);
26592657
newType = new (C, arena) BoundGenericEnumType(theEnum, Parent, ArgsCopy,
2660-
IsCanonical ? &C : 0,
2661-
properties);
2658+
IsCanonical ? &C : 0,
2659+
properties);
26622660
}
26632661
C.Impl.getArena(arena).BoundGenericTypes.InsertNode(newType, InsertPos);
26642662

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ void ASTPrinter::printTypeRef(Type T, const TypeDecl *RefTo, Identifier Name) {
843843
if (GP->isProtocolSelf())
844844
Context = PrintNameContext::GenericParameter;
845845
} else if (T && T->is<DynamicSelfType>()) {
846-
assert(T->getAs<DynamicSelfType>()->getSelfType()->getAnyNominal() &&
846+
assert(T->castTo<DynamicSelfType>()->getSelfType()->getAnyNominal() &&
847847
"protocol Self handled as GenericTypeParamDecl");
848848
Context = PrintNameContext::ClassDynamicSelf;
849849
}

lib/AST/ArchetypeBuilder.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,13 +2020,7 @@ void ArchetypeBuilder::dump(llvm::raw_ostream &out) {
20202020

20212021
Type ArchetypeBuilder::mapTypeIntoContext(const DeclContext *dc, Type type,
20222022
LazyResolver *resolver) {
2023-
// If the type is not dependent, there's nothing to map.
2024-
if (!type->hasTypeParameter())
2025-
return type;
2026-
20272023
auto genericParams = dc->getGenericParamsOfContext();
2028-
assert(genericParams && "Missing generic parameters for dependent context");
2029-
20302024
return mapTypeIntoContext(dc->getParentModule(), genericParams, type,
20312025
resolver);
20322026
}
@@ -2035,13 +2029,15 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M,
20352029
GenericParamList *genericParams,
20362030
Type type,
20372031
LazyResolver *resolver) {
2038-
// If the type is not dependent, or we have no generic params, there's nothing
2039-
// to map.
2040-
if (!genericParams || !type->hasTypeParameter())
2032+
auto canType = type->getCanonicalType();
2033+
assert(!canType->hasArchetype() && "already have a contextual type");
2034+
if (!canType->hasTypeParameter())
20412035
return type;
20422036

2037+
assert(genericParams && "dependent type in non-generic context");
2038+
20432039
unsigned genericParamsDepth = genericParams->getDepth();
2044-
return type.transform([&](Type type) -> Type {
2040+
type = type.transform([&](Type type) -> Type {
20452041
// Map a generic parameter type to its archetype.
20462042
if (auto gpType = type->getAs<GenericTypeParamType>()) {
20472043
auto index = gpType->getIndex();
@@ -2064,7 +2060,7 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M,
20642060
if (!myGenericParams->getAllArchetypes().empty())
20652061
return myGenericParams->getPrimaryArchetypes()[index];
20662062

2067-
// During type-checking, we may try to mapTypeInContext before
2063+
// During type-checking, we may try to mapTypeIntoContext before
20682064
// AllArchetypes has been built, so fall back to the generic params.
20692065
return myGenericParams->getParams()[index]->getArchetype();
20702066
}
@@ -2078,6 +2074,9 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M,
20782074

20792075
return type;
20802076
});
2077+
2078+
assert(!type->hasTypeParameter() && "not fully substituted");
2079+
return type;
20812080
}
20822081

20832082
Type
@@ -2089,10 +2088,13 @@ ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) {
20892088
Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
20902089
GenericParamList *genericParams,
20912090
Type type) {
2092-
// If the context is non-generic, we're done.
2093-
if (!genericParams)
2091+
auto canType = type->getCanonicalType();
2092+
assert(!canType->hasTypeParameter() && "already have an interface type");
2093+
if (!canType->hasArchetype())
20942094
return type;
20952095

2096+
assert(genericParams && "dependent type in non-generic context");
2097+
20962098
// Capture the archetype -> interface type mapping.
20972099
TypeSubstitutionMap subs;
20982100
for (auto params = genericParams; params != nullptr;
@@ -2102,7 +2104,10 @@ Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M,
21022104
}
21032105
}
21042106

2105-
return type.subst(M, subs, SubstFlags::AllowLoweredTypes);
2107+
type = type.subst(M, subs, SubstFlags::AllowLoweredTypes);
2108+
2109+
assert(!type->hasArchetype() && "not fully substituted");
2110+
return type;
21062111
}
21072112

21082113
bool ArchetypeBuilder::addGenericSignature(GenericSignature *sig,

lib/AST/Decl.cpp

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,10 +1690,9 @@ Type ValueDecl::getInterfaceType() const {
16901690

16911691
if (auto assocType = dyn_cast<AssociatedTypeDecl>(this)) {
16921692
auto proto = cast<ProtocolDecl>(getDeclContext());
1693-
if (!proto->getProtocolSelf())
1693+
auto selfTy = proto->getSelfInterfaceType();
1694+
if (!selfTy)
16941695
return Type();
1695-
auto selfTy = proto->getProtocolSelf()->getDeclaredType();
1696-
assert(selfTy);
16971696
auto &ctx = getASTContext();
16981697
InterfaceTy = DependentMemberType::get(
16991698
selfTy,
@@ -2584,7 +2583,7 @@ bool ProtocolDecl::existentialConformsToSelfSlow() {
25842583
/// Determine whether the given type is the 'Self' generic parameter
25852584
/// of a protocol.
25862585
static bool isProtocolSelf(const ProtocolDecl *proto, Type type) {
2587-
return proto->getProtocolSelf()->getDeclaredType()->isEqual(type);
2586+
return proto->getSelfInterfaceType()->isEqual(type);
25882587
}
25892588

25902589
/// Classify usages of Self in the given type.
@@ -3600,6 +3599,8 @@ ParamDecl::ParamDecl(ParamDecl *PD)
36003599

36013600
/// \brief Retrieve the type of 'self' for the given context.
36023601
Type DeclContext::getSelfTypeInContext() const {
3602+
assert(isTypeContext());
3603+
36033604
// For a protocol or extension thereof, the type is 'Self'.
36043605
if (getAsProtocolOrProtocolExtensionContext()) {
36053606
// In the parser, generic parameters won't be wired up yet, just give up on
@@ -3613,6 +3614,8 @@ Type DeclContext::getSelfTypeInContext() const {
36133614

36143615
/// \brief Retrieve the interface type of 'self' for the given context.
36153616
Type DeclContext::getSelfInterfaceType() const {
3617+
assert(isTypeContext());
3618+
36163619
// For a protocol or extension thereof, the type is 'Self'.
36173620
if (getAsProtocolOrProtocolExtensionContext()) {
36183621
// In the parser, generic parameters won't be wired up yet, just give up on
@@ -3684,21 +3687,28 @@ ParamDecl *ParamDecl::createSelf(SourceLoc loc, DeclContext *DC,
36843687
bool isStaticMethod, bool isInOut) {
36853688
ASTContext &C = DC->getASTContext();
36863689
auto selfType = DC->getSelfTypeInContext();
3690+
auto selfInterfaceType = DC->getSelfInterfaceType();
3691+
3692+
assert(!!selfType == !!selfInterfaceType);
36873693

36883694
// If we have a selfType (i.e. we're not in the parser before we know such
36893695
// things, configure it.
3690-
if (selfType) {
3691-
if (isStaticMethod)
3696+
if (selfType && selfInterfaceType) {
3697+
if (isStaticMethod) {
36923698
selfType = MetatypeType::get(selfType);
3699+
selfInterfaceType = MetatypeType::get(selfInterfaceType);
3700+
}
36933701

3694-
if (isInOut)
3702+
if (isInOut) {
36953703
selfType = InOutType::get(selfType);
3704+
selfInterfaceType = InOutType::get(selfInterfaceType);
3705+
}
36963706
}
3697-
3707+
36983708
auto *selfDecl = new (C) ParamDecl(/*IsLet*/!isInOut, SourceLoc(),SourceLoc(),
36993709
Identifier(), loc, C.Id_self, selfType,DC);
37003710
selfDecl->setImplicit();
3701-
selfDecl->setInterfaceType(DC->getSelfInterfaceType());
3711+
selfDecl->setInterfaceType(selfInterfaceType);
37023712
return selfDecl;
37033713
}
37043714

@@ -3876,12 +3886,10 @@ static Type getSelfTypeForContainer(AbstractFunctionDecl *theMethod,
38763886
// For a protocol, the type of 'self' is the parameter type 'Self', not
38773887
// the protocol itself.
38783888
if (containerTy->is<ProtocolType>()) {
3879-
if (auto self = dc->getProtocolSelf()) {
3880-
if (wantInterfaceType)
3881-
selfTy = self->getDeclaredType();
3882-
else
3883-
selfTy = self->getArchetype();
3884-
}
3889+
if (wantInterfaceType)
3890+
selfTy = dc->getSelfInterfaceType();
3891+
else
3892+
selfTy = dc->getSelfTypeInContext();
38853893
} else
38863894
selfTy = containerTy;
38873895
}
@@ -4419,26 +4427,16 @@ DynamicSelfType *FuncDecl::getDynamicSelf() const {
44194427
if (!hasDynamicSelf())
44204428
return nullptr;
44214429

4422-
auto extType = getExtensionType();
4423-
if (extType->is<ProtocolType>())
4424-
return DynamicSelfType::get(getDeclContext()->getProtocolSelf()
4425-
->getArchetype(),
4426-
getASTContext());
4427-
4428-
return DynamicSelfType::get(extType, getASTContext());
4430+
return DynamicSelfType::get(getDeclContext()->getSelfTypeInContext(),
4431+
getASTContext());
44294432
}
44304433

44314434
DynamicSelfType *FuncDecl::getDynamicSelfInterface() const {
44324435
if (!hasDynamicSelf())
44334436
return nullptr;
44344437

4435-
auto extType = getDeclContext()->getDeclaredInterfaceType();
4436-
if (extType->is<ProtocolType>())
4437-
return DynamicSelfType::get(getDeclContext()->getProtocolSelf()
4438-
->getDeclaredType(),
4439-
getASTContext());
4440-
4441-
return DynamicSelfType::get(extType, getASTContext());
4438+
return DynamicSelfType::get(getDeclContext()->getSelfInterfaceType(),
4439+
getASTContext());
44424440
}
44434441

44444442
SourceRange FuncDecl::getSourceRange() const {
@@ -4771,3 +4769,9 @@ ClassDecl *ClassDecl::getSuperclassDecl() const {
47714769
return superclass->getClassOrBoundGenericClass();
47724770
return nullptr;
47734771
}
4772+
4773+
void ClassDecl::setSuperclass(Type superclass) {
4774+
assert((!superclass || !superclass->hasArchetype())
4775+
&& "superclass must be interface type");
4776+
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
4777+
}

lib/AST/LookupVisibleDecls.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
716716
}
717717

718718
// Does it make sense to substitute types?
719-
bool shouldSubst = !isa<UnboundGenericType>(BaseTy.getPointer()) &&
719+
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
720720
!isa<AnyMetatypeType>(BaseTy.getPointer()) &&
721721
!BaseTy->isAnyExistentialType();
722722
ModuleDecl *M = DC->getParentModule();
@@ -831,7 +831,7 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
831831
DC = DC->getParent();
832832

833833
if (DC->getAsProtocolExtensionContext())
834-
ExtendedType = DC->getProtocolSelf()->getArchetype();
834+
ExtendedType = DC->getSelfTypeInContext();
835835

836836
if (auto *FD = dyn_cast<FuncDecl>(AFD))
837837
if (FD->isStatic())

lib/AST/NameLookup.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
436436

437437
if (AFD->getExtensionType()) {
438438
if (AFD->getDeclContext()->getAsProtocolOrProtocolExtensionContext()) {
439-
ExtendedType = AFD->getDeclContext()->getProtocolSelf()
440-
->getArchetype();
439+
ExtendedType = AFD->getDeclContext()->getSelfTypeInContext();
441440

442441
// Fallback path.
443442
if (!ExtendedType)
@@ -481,11 +480,7 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
481480
if (!isCascadingUse.hasValue())
482481
isCascadingUse = ACE->isCascadingContextForLookup(false);
483482
} else if (ExtensionDecl *ED = dyn_cast<ExtensionDecl>(DC)) {
484-
if (ED->getAsProtocolOrProtocolExtensionContext()) {
485-
ExtendedType = ED->getProtocolSelf()->getArchetype();
486-
} else {
487-
ExtendedType = ED->getExtendedType();
488-
}
483+
ExtendedType = ED->getSelfTypeInContext();
489484

490485
BaseDecl = ED->getAsNominalTypeOrNominalTypeExtensionContext();
491486
MetaBaseDecl = BaseDecl;

lib/AST/Parameter.cpp

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,23 +131,54 @@ Type ParameterList::getType(const ASTContext &C) const {
131131
return TupleType::get(argumentInfo, C);
132132
}
133133

134+
/// Hack to deal with the fact that Sema/CodeSynthesis.cpp creates ParamDecls
135+
/// containing contextual types.
136+
Type ParameterList::getInterfaceType(DeclContext *DC) const {
137+
auto &C = DC->getASTContext();
138+
139+
if (size() == 0)
140+
return TupleType::getEmpty(C);
141+
142+
SmallVector<TupleTypeElt, 8> argumentInfo;
143+
144+
for (auto P : *this) {
145+
assert(P->hasType());
146+
147+
Type type;
148+
if (P->hasInterfaceType())
149+
type = P->getInterfaceType();
150+
else if (!P->getTypeLoc().hasLocation())
151+
type = ArchetypeBuilder::mapTypeOutOfContext(DC, P->getType());
152+
else
153+
type = P->getType();
154+
assert(!type->hasArchetype());
155+
156+
argumentInfo.push_back({
157+
type, P->getArgumentName(),
158+
P->getDefaultArgumentKind(), P->isVariadic()
159+
});
160+
}
161+
162+
return TupleType::get(argumentInfo, C);
163+
}
164+
134165

135166
/// Return the full function type for a set of curried parameter lists that
136167
/// returns the specified result type. This returns a null type if one of the
137168
/// ParamDecls does not have a type set for it yet.
138169
///
139-
Type ParameterList::getFullType(Type resultType, ArrayRef<ParameterList*> PLL) {
170+
Type ParameterList::getFullInterfaceType(Type resultType,
171+
ArrayRef<ParameterList*> PLL,
172+
DeclContext *DC) {
140173
auto result = resultType;
141-
auto &C = result->getASTContext();
142-
143174
for (auto PL : reversed(PLL)) {
144-
auto paramType = PL->getType(C);
145-
if (!paramType) return Type();
175+
auto paramType = PL->getInterfaceType(DC);
146176
result = FunctionType::get(paramType, result);
147177
}
148178
return result;
149179
}
150180

181+
151182
/// Return the full source range of this parameter list.
152183
SourceRange ParameterList::getSourceRange() const {
153184
// If we have locations for the parens, then they define our range.

0 commit comments

Comments
 (0)