Skip to content

Commit ee9f1dc

Browse files
committed
AST: Introduce ReplaceExistentialArchetypesWithConcreteTypes
1 parent cf1572c commit ee9f1dc

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

include/swift/AST/Types.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7082,6 +7082,32 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
70827082
bool isWholeModule() const { return inContextAndIsWholeModule.getInt(); }
70837083
};
70847084

7085+
/// A function object that can be used as a \c TypeSubstitutionFn and
7086+
/// \c LookupConformanceFn for \c Type::subst style APIs to map existential
7087+
/// archetypes in the given generic environment to known concrete types from
7088+
/// the given substitution map.
7089+
class ReplaceExistentialArchetypesWithConcreteTypes {
7090+
private:
7091+
GenericEnvironment *env;
7092+
SubstitutionMap subs;
7093+
7094+
Type getInterfaceType(ExistentialArchetypeType *type) const;
7095+
7096+
public:
7097+
ReplaceExistentialArchetypesWithConcreteTypes(GenericEnvironment *env,
7098+
SubstitutionMap subs)
7099+
: env(env), subs(subs) {}
7100+
7101+
/// TypeSubstitutionFn
7102+
Type operator()(SubstitutableType *type) const;
7103+
7104+
/// LookupConformanceFn
7105+
ProtocolConformanceRef operator()(CanType origType,
7106+
Type substType,
7107+
ProtocolDecl *protocol) const;
7108+
7109+
};
7110+
70857111
/// An archetype that's only valid in a portion of a local context.
70867112
class LocalArchetypeType : public ArchetypeType {
70877113
protected:

lib/AST/TypeSubstitution.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,3 +1200,35 @@ operator()(CanType maybeOpaqueType, Type replacementType,
12001200
}
12011201
return substRef;
12021202
}
1203+
1204+
Type ReplaceExistentialArchetypesWithConcreteTypes::getInterfaceType(
1205+
ExistentialArchetypeType *type) const {
1206+
return type->getInterfaceType().transformRec(
1207+
[&](TypeBase *type) -> std::optional<Type> {
1208+
if (isa<GenericTypeParamType>(type))
1209+
return type->getASTContext().TheSelfType;
1210+
return std::nullopt;
1211+
});
1212+
}
1213+
1214+
Type ReplaceExistentialArchetypesWithConcreteTypes::operator()(
1215+
SubstitutableType *type) const {
1216+
auto *existentialArchetype = dyn_cast<ExistentialArchetypeType>(type);
1217+
if (!existentialArchetype ||
1218+
existentialArchetype->getGenericEnvironment() != env)
1219+
return type;
1220+
1221+
auto interfaceType = getInterfaceType(existentialArchetype);
1222+
return interfaceType.subst(subs);
1223+
}
1224+
1225+
ProtocolConformanceRef ReplaceExistentialArchetypesWithConcreteTypes::operator()(
1226+
CanType origType, Type substType, ProtocolDecl *proto) const {
1227+
auto existentialArchetype = dyn_cast<ExistentialArchetypeType>(origType);
1228+
if (!existentialArchetype ||
1229+
existentialArchetype->getGenericEnvironment() != env)
1230+
return ProtocolConformanceRef::forAbstract(substType, proto);
1231+
1232+
return subs.lookupConformance(
1233+
getInterfaceType(existentialArchetype)->getCanonicalType(), proto);
1234+
}

0 commit comments

Comments
 (0)