Skip to content

Clean up duplicated opened existential archetype handling in SIL and more #81142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 30, 2025
8 changes: 0 additions & 8 deletions SwiftCompilerSources/Sources/AST/Type.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
public func subst(with substitutionMap: SubstitutionMap) -> Type {
return Type(bridged: bridged.subst(substitutionMap.bridged))
}

public func subst(type: Type, with targetType: Type) -> Type {
return Type(bridged: bridged.subst(type.bridged, targetType.bridged))
}
}

/// A Type that is statically known to be canonical.
Expand All @@ -88,10 +84,6 @@ public struct CanonicalType: TypeProperties, CustomStringConvertible, NoReflecti
public func subst(with substitutionMap: SubstitutionMap) -> CanonicalType {
return rawType.subst(with: substitutionMap).canonical
}

public func subst(type: CanonicalType, with targetType: CanonicalType) -> CanonicalType {
return self.rawType.subst(type: type.rawType, with: targetType.rawType).canonical
}
}

/// Implements the common members of `AST.Type`, `AST.CanonicalType` and `SIL.Type`.
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -3115,7 +3115,6 @@ struct BridgedASTType {
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getContextSubstitutionMap() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedGenericSignature getInvocationGenericSignatureOfFunctionType() const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType subst(BridgedSubstitutionMap substMap) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType subst(BridgedASTType fromType, BridgedASTType toType) const;
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance checkConformance(BridgedDeclObj proto) const;
};

Expand Down
11 changes: 0 additions & 11 deletions include/swift/AST/ASTBridgingImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,17 +596,6 @@ BridgedASTType BridgedASTType::subst(BridgedSubstitutionMap substMap) const {
return {unbridged().subst(substMap.unbridged()).getPointer()};
}


BridgedASTType BridgedASTType::subst(BridgedASTType fromType, BridgedASTType toType) const {
auto *fromTy = fromType.unbridged()->castTo<swift::SubstitutableType>();
swift::Type toTy = toType.unbridged();
return {unbridged().subst([fromTy, toTy](swift::SubstitutableType *t) -> swift::Type {
if (t == fromTy)
return toTy;
return t;
}, swift::LookUpConformanceInModule(), swift::SubstFlags::SubstituteLocalArchetypes).getPointer()};
}

BridgedConformance BridgedASTType::checkConformance(BridgedDeclObj proto) const {
return swift::checkConformance(unbridged(), proto.getAs<swift::ProtocolDecl>(), /*allowMissing=*/ false);
}
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,9 @@ class ASTContext final {
const CanType TheUnconstrainedAnyType; /// This is 'any ~Copyable & ~Escapable',
/// the empty protocol composition
/// without any implicit constraints.
const CanGenericTypeParamType TheSelfType; /// The protocol 'Self' type;
/// a generic parameter with
/// depth 0 index 0
#define SINGLETON_TYPE(SHORT_ID, ID) \
const CanType The##SHORT_ID##Type;
#include "swift/AST/TypeNodes.def"
Expand Down
3 changes: 1 addition & 2 deletions include/swift/AST/InFlightSubstitution.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ class InFlightSubstitution {
Type substType(SubstitutableType *origType, unsigned level);

/// Perform primitive conformance lookup on the given type.
ProtocolConformanceRef lookupConformance(CanType dependentType,
Type conformingReplacementType,
ProtocolConformanceRef lookupConformance(Type dependentType,
ProtocolDecl *conformedProtocol,
unsigned level);

Expand Down
6 changes: 0 additions & 6 deletions include/swift/AST/SubstitutionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,6 @@ class SubstitutionMap {
/// subsystem.
SubstitutionMap subst(InFlightSubstitution &subs) const;

/// Apply type expansion lowering to all types in the substitution map. Opaque
/// archetypes will be lowered to their underlying types if the type expansion
/// context allows.
SubstitutionMap mapIntoTypeExpansionContext(
TypeExpansionContext context) const;

/// Create a substitution map for a protocol conformance.
static SubstitutionMap
getProtocolSubstitutions(ProtocolConformanceRef conformance);
Expand Down
32 changes: 32 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5032,9 +5032,15 @@ Type substOpaqueTypesWithUnderlyingTypes(Type type,

CanType substOpaqueTypesWithUnderlyingTypes(CanType type,
TypeExpansionContext context);

ProtocolConformanceRef
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref,
TypeExpansionContext context);

SubstitutionMap
substOpaqueTypesWithUnderlyingTypes(SubstitutionMap subs,
TypeExpansionContext context);

namespace Lowering {
class TypeConverter;
}
Expand Down Expand Up @@ -7082,6 +7088,32 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
bool isWholeModule() const { return inContextAndIsWholeModule.getInt(); }
};

/// A function object that can be used as a \c TypeSubstitutionFn and
/// \c LookupConformanceFn for \c Type::subst style APIs to map existential
/// archetypes in the given generic environment to known concrete types from
/// the given substitution map.
class ReplaceExistentialArchetypesWithConcreteTypes {
private:
GenericEnvironment *env;
SubstitutionMap subs;

Type getInterfaceType(ExistentialArchetypeType *type) const;

public:
ReplaceExistentialArchetypesWithConcreteTypes(GenericEnvironment *env,
SubstitutionMap subs)
: env(env), subs(subs) {}

/// TypeSubstitutionFn
Type operator()(SubstitutableType *type) const;

/// LookupConformanceFn
ProtocolConformanceRef operator()(CanType origType,
Type substType,
ProtocolDecl *protocol) const;

};

/// An archetype that's only valid in a portion of a local context.
class LocalArchetypeType : public ArchetypeType {
protected:
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
!context.shouldLookThroughOpaqueTypeArchetypes())
return Subs;

return Subs.mapIntoTypeExpansionContext(context);
return substOpaqueTypesWithUnderlyingTypes(Subs, context);
}

return Subs;
Expand Down
5 changes: 3 additions & 2 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,8 @@ ASTContext::ASTContext(
TheAnyType(ProtocolCompositionType::theAnyType(*this)),
TheUnconstrainedAnyType(
ProtocolCompositionType::theUnconstrainedAnyType(*this)),
TheSelfType(CanGenericTypeParamType(
GenericTypeParamType::getType(0, 0, *this))),
#define SINGLETON_TYPE(SHORT_ID, ID) \
The##SHORT_ID##Type(new (*this, AllocationArena::Permanent) \
ID##Type(*this)),
Expand Down Expand Up @@ -6639,8 +6641,7 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
if (auto theSig = getImpl().SingleGenericParameterSignature)
return theSig;

auto param = GenericTypeParamType::getType(/*depth*/ 0, /*index*/ 0, *this);
auto sig = GenericSignature::get(param, { });
auto sig = GenericSignature::get({TheSelfType}, { });
auto canonicalSig = CanGenericSignature(sig);
getImpl().SingleGenericParameterSignature = canonicalSig;
return canonicalSig;
Expand Down
10 changes: 3 additions & 7 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ std::string ASTMangler::mangleKeyPathGetterThunkHelper(
sub = sub.transformRec([](Type t) -> std::optional<Type> {
if (auto *openedExistential = t->getAs<ExistentialArchetypeType>()) {
auto &ctx = openedExistential->getASTContext();
return GenericTypeParamType::getType(0, 0, ctx);
return ctx.TheSelfType;
}
return std::nullopt;
});
Expand Down Expand Up @@ -431,7 +431,7 @@ std::string ASTMangler::mangleKeyPathSetterThunkHelper(
sub = sub.transformRec([](Type t) -> std::optional<Type> {
if (auto *openedExistential = t->getAs<ExistentialArchetypeType>()) {
auto &ctx = openedExistential->getASTContext();
return GenericTypeParamType::getType(0, 0, ctx);
return ctx.TheSelfType;
}
return std::nullopt;
});
Expand Down Expand Up @@ -5274,15 +5274,11 @@ static void extractExistentialInverseRequirements(

auto &ctx = PCT->getASTContext();

// Form a parameter referring to the existential's Self.
auto existentialSelf =
GenericTypeParamType::getType(/*depth=*/0, /*index=*/0, ctx);

for (auto ip : PCT->getInverses()) {
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
assert(proto);
ASSERT(!getABIDecl(proto) && "can't use @abi on inverse protocols");
inverses.push_back({existentialSelf, proto, SourceLoc()});
inverses.push_back({ctx.TheSelfType, proto, SourceLoc()});
}
}

Expand Down
13 changes: 7 additions & 6 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4334,13 +4334,14 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
if (proto && Options.TransformContext) {
auto BaseType = Options.TransformContext->getBaseType();
if (BaseType->getClassOrBoundGenericClass()) {
ResultTy = ResultTy.subst(
[&](Type t) -> Type {
if (t->isEqual(proto->getSelfInterfaceType()))
ResultTy = ResultTy.transformRec(
[&](TypeBase *t) -> std::optional<Type> {
if (isa<DependentMemberType>(t))
return t;
else if (t->isEqual(proto->getSelfInterfaceType()))
return DynamicSelfType::get(t, Ctx);
return t;
},
MakeAbstractConformanceForGenericType());
return std::nullopt;
});
ResultTyLoc = TypeLoc::withoutLoc(ResultTy);
}
}
Expand Down
4 changes: 1 addition & 3 deletions lib/AST/ProtocolConformanceRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ ProtocolConformanceRef::subst(InFlightSubstitution &IFS) const {

// Local conformance lookup into the substitution map.
// FIXME: Pack element level?
return IFS.lookupConformance(origType->getCanonicalType(),
origType.subst(IFS), proto,
/*level=*/0);
return IFS.lookupConformance(origType, proto, /*level=*/0);
}

ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const {
Expand Down
8 changes: 3 additions & 5 deletions lib/AST/RequirementEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ RequirementEnvironment::RequirementEnvironment(
// type.
if (type->isEqual(selfType)) {
if (covariantSelf)
return GenericTypeParamType::getType(/*depth=*/0, /*index=*/0, ctx);
return ctx.TheSelfType;
return substConcreteType;
}
// Other requirement generic parameters map 1:1 with their depth
Expand Down Expand Up @@ -173,8 +173,7 @@ RequirementEnvironment::RequirementEnvironment(
// If the conforming type is a class, add a class-constrained 'Self'
// parameter.
if (covariantSelf) {
auto paramTy = GenericTypeParamType::getType(/*depth=*/0, /*index=*/0, ctx);
genericParamTypes.push_back(paramTy);
genericParamTypes.push_back(ctx.TheSelfType);
}

// Now, add all generic parameters from the conforming type.
Expand All @@ -188,8 +187,7 @@ RequirementEnvironment::RequirementEnvironment(
// Next, add requirements.
SmallVector<Requirement, 2> requirements;
if (covariantSelf) {
auto paramTy = GenericTypeParamType::getType(/*depth=*/0, /*index=*/0, ctx);
Requirement reqt(RequirementKind::Superclass, paramTy, substConcreteType);
Requirement reqt(RequirementKind::Superclass, ctx.TheSelfType, substConcreteType);
requirements.push_back(reqt);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/AST/RequirementMachine/InterfaceType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,11 @@ getTypeForSymbolRange(const Symbol *begin, const Symbol *end,
continue;

case Symbol::Kind::Protocol:
handleRoot(GenericTypeParamType::getType(0, 0, ctx.getASTContext()));
handleRoot(ctx.getASTContext().TheSelfType);
continue;

case Symbol::Kind::AssociatedType:
handleRoot(GenericTypeParamType::getType(0, 0, ctx.getASTContext()));
handleRoot(ctx.getASTContext().TheSelfType);

// An associated type symbol at the root means we have a dependent
// member type rooted at Self; handle the associated type below.
Expand Down
24 changes: 11 additions & 13 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,12 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
// Form the stored conformances.
SmallVector<ProtocolConformanceRef, 4> conformances;
for (const auto &req : genericSig.getRequirements()) {
if (req.getKind() != RequirementKind::Conformance) continue;

Type depTy = req.getFirstType();
auto replacement = depTy.subst(IFS);
auto *proto = req.getProtocolDecl();
auto conformance = IFS.lookupConformance(
depTy->getCanonicalType(), replacement, proto, /*level=*/0);
conformances.push_back(conformance);
if (req.getKind() != RequirementKind::Conformance)
continue;

conformances.push_back(
IFS.lookupConformance(
req.getFirstType(), req.getProtocolDecl(), /*level=*/0));
}

return SubstitutionMap(genericSig, types, conformances);
Expand Down Expand Up @@ -653,14 +651,14 @@ bool SubstitutionMap::isIdentity() const {
return !hasNonIdentityReplacement;
}

SubstitutionMap SubstitutionMap::mapIntoTypeExpansionContext(
TypeExpansionContext context) const {
SubstitutionMap swift::substOpaqueTypesWithUnderlyingTypes(
SubstitutionMap subs, TypeExpansionContext context) {
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
context.getContext(), context.getResilienceExpansion(),
context.isWholeModuleContext());
return this->subst(replacer, replacer,
SubstFlags::SubstituteOpaqueArchetypes |
SubstFlags::PreservePackExpansionLevel);
return subs.subst(replacer, replacer,
SubstFlags::SubstituteOpaqueArchetypes |
SubstFlags::PreservePackExpansionLevel);
}

bool OuterSubstitutions::isUnsubstitutedTypeParameter(Type type) const {
Expand Down
Loading