diff --git a/SwiftCompilerSources/Sources/AST/Type.swift b/SwiftCompilerSources/Sources/AST/Type.swift index 8dc0123ec50aa..3ab4275d543e0 100644 --- a/SwiftCompilerSources/Sources/AST/Type.swift +++ b/SwiftCompilerSources/Sources/AST/Type.swift @@ -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. @@ -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`. diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index d443bdbc97b6f..ec6d9a1d0b52c 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -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; }; diff --git a/include/swift/AST/ASTBridgingImpl.h b/include/swift/AST/ASTBridgingImpl.h index 7547f6ab5f9c8..ee035de31fb81 100644 --- a/include/swift/AST/ASTBridgingImpl.h +++ b/include/swift/AST/ASTBridgingImpl.h @@ -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::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(), /*allowMissing=*/ false); } diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index e980d009d73f5..d14baec95329a 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -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" diff --git a/include/swift/AST/InFlightSubstitution.h b/include/swift/AST/InFlightSubstitution.h index f4188366f6f62..bbfc9e00dae2b 100644 --- a/include/swift/AST/InFlightSubstitution.h +++ b/include/swift/AST/InFlightSubstitution.h @@ -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); diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h index 41a3ae3d9e6e4..99cb5ecebf9d6 100644 --- a/include/swift/AST/SubstitutionMap.h +++ b/include/swift/AST/SubstitutionMap.h @@ -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); diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 249dbbad06879..109ee7c150c9e 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -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; } @@ -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: diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index d4003606ebc38..d54a395188c1e 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -590,7 +590,7 @@ class SILCloner : protected SILInstructionVisitor { !context.shouldLookThroughOpaqueTypeArchetypes()) return Subs; - return Subs.mapIntoTypeExpansionContext(context); + return substOpaqueTypesWithUnderlyingTypes(Subs, context); } return Subs; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a9c3d88e332c8..741bcf35bd171 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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)), @@ -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; diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index e46fef7352f64..740afb108789d 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -395,7 +395,7 @@ std::string ASTMangler::mangleKeyPathGetterThunkHelper( sub = sub.transformRec([](Type t) -> std::optional { if (auto *openedExistential = t->getAs()) { auto &ctx = openedExistential->getASTContext(); - return GenericTypeParamType::getType(0, 0, ctx); + return ctx.TheSelfType; } return std::nullopt; }); @@ -431,7 +431,7 @@ std::string ASTMangler::mangleKeyPathSetterThunkHelper( sub = sub.transformRec([](Type t) -> std::optional { if (auto *openedExistential = t->getAs()) { auto &ctx = openedExistential->getASTContext(); - return GenericTypeParamType::getType(0, 0, ctx); + return ctx.TheSelfType; } return std::nullopt; }); @@ -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()}); } } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 3a9b306189951..06f14058ff9eb 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -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 { + if (isa(t)) + return t; + else if (t->isEqual(proto->getSelfInterfaceType())) return DynamicSelfType::get(t, Ctx); - return t; - }, - MakeAbstractConformanceForGenericType()); + return std::nullopt; + }); ResultTyLoc = TypeLoc::withoutLoc(ResultTy); } } diff --git a/lib/AST/ProtocolConformanceRef.cpp b/lib/AST/ProtocolConformanceRef.cpp index b6193d6d90fdd..10192b85c1333 100644 --- a/lib/AST/ProtocolConformanceRef.cpp +++ b/lib/AST/ProtocolConformanceRef.cpp @@ -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 { diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp index d60ea83df6f69..b71e630f4e7b4 100644 --- a/lib/AST/RequirementEnvironment.cpp +++ b/lib/AST/RequirementEnvironment.cpp @@ -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 @@ -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. @@ -188,8 +187,7 @@ RequirementEnvironment::RequirementEnvironment( // Next, add requirements. SmallVector 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); } diff --git a/lib/AST/RequirementMachine/InterfaceType.cpp b/lib/AST/RequirementMachine/InterfaceType.cpp index 874edccdba7fe..48f96f84adafe 100644 --- a/lib/AST/RequirementMachine/InterfaceType.cpp +++ b/lib/AST/RequirementMachine/InterfaceType.cpp @@ -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. diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 2e35984f245ce..6ff407d7ce2fe 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -174,14 +174,12 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig, // Form the stored conformances. SmallVector 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); @@ -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 { diff --git a/lib/AST/TypeSubstitution.cpp b/lib/AST/TypeSubstitution.cpp index ab816121b71fe..36f6aa7659789 100644 --- a/lib/AST/TypeSubstitution.cpp +++ b/lib/AST/TypeSubstitution.cpp @@ -273,13 +273,13 @@ Type InFlightSubstitution::substType(SubstitutableType *origType, } ProtocolConformanceRef -InFlightSubstitution::lookupConformance(CanType dependentType, - Type conformingReplacementType, +InFlightSubstitution::lookupConformance(Type dependentType, ProtocolDecl *conformedProtocol, unsigned level) { - auto substConfRef = BaselineLookupConformance(dependentType, - conformingReplacementType, - conformedProtocol); + auto substConfRef = BaselineLookupConformance( + dependentType->getCanonicalType(), + dependentType.subst(*this), + conformedProtocol); if (!substConfRef || ActivePackExpansions.empty() || !substConfRef.isPack()) @@ -430,22 +430,18 @@ Type TypeSubstituter::transformPackElementType(PackElementType *element, Type TypeSubstituter::transformDependentMemberType(DependentMemberType *dependent, TypePosition pos) { auto origBase = dependent->getBase(); - auto substBase = doIt(origBase, TypePosition::Invariant); - - if (auto *selfType = substBase->getAs()) - substBase = selfType->getSelfType(); auto *assocType = dependent->getAssocType(); ASSERT(assocType); - auto proto = assocType->getProtocol(); - ProtocolConformanceRef conformance = - IFS.lookupConformance(origBase->getCanonicalType(), substBase, - proto, level); + auto *proto = assocType->getProtocol(); + auto conformance = IFS.lookupConformance(origBase, proto, level); auto result = conformance.getTypeWitness(assocType, IFS.getOptions()); - if (result->is()) + if (result->is()) { + auto substBase = origBase.subst(IFS); return DependentMemberType::get(ErrorType::get(substBase), assocType); + } return result; } @@ -1123,7 +1119,7 @@ operator()(CanType maybeOpaqueType, Type replacementType, ProtocolDecl *protocol) const { auto archetype = dyn_cast(maybeOpaqueType); if (!archetype) - return lookupConformance(replacementType, protocol); + return ProtocolConformanceRef::forAbstract(maybeOpaqueType, protocol); auto *genericEnv = archetype->getGenericEnvironment(); auto *decl = genericEnv->getOpaqueTypeDecl(); @@ -1131,13 +1127,13 @@ operator()(CanType maybeOpaqueType, Type replacementType, auto substitutionKind = shouldPerformSubstitution(decl); if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) - return lookupConformance(replacementType, protocol); + return ProtocolConformanceRef::forAbstract(replacementType, protocol); auto subs = decl->getUniqueUnderlyingTypeSubstitutions(); // If the body of the opaque decl providing decl has not been type checked we // don't have a underlying substitution. if (!subs.has_value()) - return lookupConformance(replacementType, protocol); + return ProtocolConformanceRef::forAbstract(replacementType, protocol); // Apply the underlying type substitutions to the interface type of the // archetype in question. This will map the inner generic signature of the @@ -1158,13 +1154,7 @@ operator()(CanType maybeOpaqueType, Type replacementType, return true; return false; })) - return lookupConformance(replacementType, protocol); - - // Then apply the substitutions from the root opaque archetype, to specialize - // for its type arguments. We perform this substitution after checking for - // visibility, since we do not want the result of the visibility check to - // depend on the substitutions previously applied. - auto substTy = partialSubstTy.subst(outerSubs); + return ProtocolConformanceRef::forAbstract(replacementType, protocol); auto partialSubstRef = subs->lookupConformance(archetype->getInterfaceType()->getCanonicalType(), @@ -1172,7 +1162,7 @@ operator()(CanType maybeOpaqueType, Type replacementType, auto substRef = partialSubstRef.subst(outerSubs); // If the type still contains opaque types, recur. - if (substTy->hasOpaqueArchetype()) { + if (substRef.getType()->hasOpaqueArchetype()) { SeenDecl seenKey(decl, outerSubs); if (auto *alreadySeen = this->seenDecls) { @@ -1200,3 +1190,35 @@ operator()(CanType maybeOpaqueType, Type replacementType, } return substRef; } + +Type ReplaceExistentialArchetypesWithConcreteTypes::getInterfaceType( + ExistentialArchetypeType *type) const { + return type->getInterfaceType().transformRec( + [&](TypeBase *type) -> std::optional { + if (isa(type)) + return type->getASTContext().TheSelfType; + return std::nullopt; + }); +} + +Type ReplaceExistentialArchetypesWithConcreteTypes::operator()( + SubstitutableType *type) const { + auto *existentialArchetype = dyn_cast(type); + if (!existentialArchetype || + existentialArchetype->getGenericEnvironment() != env) + return type; + + auto interfaceType = getInterfaceType(existentialArchetype); + return interfaceType.subst(subs); +} + +ProtocolConformanceRef ReplaceExistentialArchetypesWithConcreteTypes::operator()( + CanType origType, Type substType, ProtocolDecl *proto) const { + auto existentialArchetype = dyn_cast(origType); + if (!existentialArchetype || + existentialArchetype->getGenericEnvironment() != env) + return ProtocolConformanceRef::forAbstract(substType, proto); + + return subs.lookupConformance( + getInterfaceType(existentialArchetype)->getCanonicalType(), proto); +} \ No newline at end of file diff --git a/lib/IRGen/GenDistributed.cpp b/lib/IRGen/GenDistributed.cpp index 3a63725dc2897..929de6ebaa72f 100644 --- a/lib/IRGen/GenDistributed.cpp +++ b/lib/IRGen/GenDistributed.cpp @@ -277,8 +277,7 @@ static CanSILFunctionType getAccessorType(IRGenModule &IGM) { SmallVector parameters; // A generic parameter that represents instance of invocation decoder. - auto *decoderType = - GenericTypeParamType::getType(/*depth=*/ 0, /*index=*/ 0, Context); + auto decoderType = Context.TheSelfType; // decoder parameters.push_back(GenericFunctionType::Param( diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index a14ade624eaa7..67dc0386ec997 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -1587,7 +1587,7 @@ class FixedBoxTypeInfoBase : public BoxTypeInfo { .transformRec([](Type t) -> std::optional { if (auto *openedExistential = t->getAs()) { auto &ctx = openedExistential->getASTContext(); - return GenericTypeParamType::getType(0, 0, ctx); + return ctx.TheSelfType; } return std::nullopt; }) diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 7d022357c2169..be52b4379009b 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -783,7 +783,7 @@ emitKeyPathComponent(IRGenModule &IGM, if (auto *openedExistential = t->getAs()) { auto &ctx = openedExistential->getASTContext(); - return GenericTypeParamType::getType(0, 0, ctx); + return ctx.TheSelfType; } return std::nullopt; }) diff --git a/lib/SIL/IR/SILTypeSubstitution.cpp b/lib/SIL/IR/SILTypeSubstitution.cpp index 3346cbfa87a47..b6e8698689dd5 100644 --- a/lib/SIL/IR/SILTypeSubstitution.cpp +++ b/lib/SIL/IR/SILTypeSubstitution.cpp @@ -68,7 +68,7 @@ class SILTypeSubstituter : if (!typeExpansionContext.shouldLookThroughOpaqueTypeArchetypes()) return subs; - return subs.mapIntoTypeExpansionContext(typeExpansionContext); + return substOpaqueTypesWithUnderlyingTypes(subs, typeExpansionContext); } // Substitute a function type. diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 0705584a057b5..25036add6efee 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -452,7 +452,7 @@ class Callee { auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); return Callee( SGF, c, ci.FormalPattern, ci.FormalType, - subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), + substOpaqueTypesWithUnderlyingTypes(subs, SGF.getTypeExpansionContext()), subs, l, callPreviousDynamicReplaceableImpl); @@ -465,7 +465,7 @@ class Callee { auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); return Callee( Kind::EnumElement, SGF, c, ci.FormalPattern, ci.FormalType, - subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); + substOpaqueTypesWithUnderlyingTypes(subs, SGF.getTypeExpansionContext()), l); } static Callee forClassMethod(SILGenFunction &SGF, SILDeclRef c, SubstitutionMap subs, @@ -473,7 +473,7 @@ class Callee { auto base = c.getOverriddenVTableEntry(); auto &baseCI = SGF.getConstantInfo(SGF.getTypeExpansionContext(), base); auto &derivedCI = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); - subs = subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()); + subs = substOpaqueTypesWithUnderlyingTypes(subs, SGF.getTypeExpansionContext()); // We use an orig function type based on the overridden vtable entry, but // the substitutions we have are for the current function. To get subs @@ -497,7 +497,7 @@ class Callee { SILDeclRef c, SubstitutionMap subs, SILLocation l) { auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); - subs = subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()); + subs = substOpaqueTypesWithUnderlyingTypes(subs, SGF.getTypeExpansionContext()); auto origFunctionType = ci.FormalPattern.withSubstitutions(subs); return Callee( Kind::SuperMethod, SGF, c, origFunctionType, ci.FormalType, subs, l); @@ -524,7 +524,7 @@ class Callee { auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); return Callee( Kind::WitnessMethod, SGF, c, ci.FormalPattern, ci.FormalType, - subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); + substOpaqueTypesWithUnderlyingTypes(subs, SGF.getTypeExpansionContext()), l); } static Callee forDynamic(SILGenFunction &SGF, SILDeclRef c, SubstitutionMap constantSubs, @@ -550,7 +550,7 @@ class Callee { return Callee( Kind::DynamicMethod, SGF, c, origFormalType, substFormalType, - subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); + substOpaqueTypesWithUnderlyingTypes(subs, SGF.getTypeExpansionContext()), l); } static Callee formCallee(SILGenFunction &SGF, AbstractFunctionDecl *decl, diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp index 89653c1720954..e02a87385ea74 100644 --- a/lib/SILGen/SILGenBuiltin.cpp +++ b/lib/SILGen/SILGenBuiltin.cpp @@ -1667,8 +1667,7 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc, .build(); auto genericSig = subs.getGenericSignature().getCanonicalSignature(); - auto genericResult = GenericTypeParamType::getType(/*depth*/ 0, /*index*/ 0, - SGF.getASTContext()); + auto genericResult = SGF.getASTContext().TheSelfType; // () async throws -> T CanType functionTy = diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 79415697c5a85..47f05172086d8 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -1576,9 +1576,7 @@ RValueEmitter::visitConditionalBridgeFromObjCExpr( auto conversion = cast(conversionRef.getDecl()); auto subs = conversionRef.getSubstitutions(); - auto nativeType = Type(GenericTypeParamType::getType(/*depth*/ 0, /*index*/ 0, - SGF.getASTContext())) - .subst(subs); + auto nativeType = Type(SGF.getASTContext().TheSelfType).subst(subs); auto metatypeType = SGF.getLoweredType(MetatypeType::get(nativeType)); auto metatype = ManagedValue::forObjectRValueWithoutOwnership( @@ -4153,9 +4151,7 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, auto formalCanTy = formalTy->getCanonicalType(); // Get the Equatable conformance from the Hashable conformance. - auto equatable = hashable.getAssociatedConformance( - GenericTypeParamType::getType(/*depth*/ 0, /*index*/ 0, C), - equatableProtocol); + auto equatable = hashable.getAssociatedConformance(C.TheSelfType, equatableProtocol); assert(equatable.isAbstract() == hashable.isAbstract()); if (equatable.isConcrete()) diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index 49b6e762f0f9d..f737ec484e0d6 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -1222,23 +1222,11 @@ SILInstruction *SILCombiner::createApplyWithConcreteType( NewArgs.push_back(cast); // Form a new set of substitutions where the argument is // replaced with a concrete type. - NewCallSubs = NewCallSubs.subst( - [&](SubstitutableType *type) -> Type { - if (type == OAI.OpenedArchetype) - return CEI.ConcreteType; - return type; - }, - [&](CanType origTy, Type substTy, - ProtocolDecl *proto) -> ProtocolConformanceRef { - if (origTy->isEqual(OAI.OpenedArchetype)) { - assert(substTy->isEqual(CEI.ConcreteType)); - // Do a conformance lookup on this witness requirement using the - // existential's conformances. The witness requirement may be a - // base type of the existential's requirements. - return CEI.lookupExistentialConformance(proto); - } - return ProtocolConformanceRef::forAbstract(substTy, proto); - }, SubstFlags::SubstituteLocalArchetypes); + ReplaceExistentialArchetypesWithConcreteTypes replacer( + OAI.OpenedArchetype->getGenericEnvironment(), + CEI.ExistentialSubs); + NewCallSubs = NewCallSubs.subst(replacer, replacer, + SubstFlags::SubstituteLocalArchetypes); continue; } // Otherwise, use the original argument. @@ -1263,23 +1251,11 @@ SILInstruction *SILCombiner::createApplyWithConcreteType( // Form a new set of substitutions where the argument is // replaced with a concrete type. - NewCallSubs = NewCallSubs.subst( - [&](SubstitutableType *type) -> Type { - if (type == OAI.OpenedArchetype) - return CEI.ConcreteType; - return type; - }, - [&](CanType origTy, Type substTy, - ProtocolDecl *proto) -> ProtocolConformanceRef { - if (origTy->isEqual(OAI.OpenedArchetype)) { - assert(substTy->isEqual(CEI.ConcreteType)); - // Do a conformance lookup on this witness requirement using the - // existential's conformances. The witness requirement may be a - // base type of the existential's requirements. - return CEI.lookupExistentialConformance(proto); - } - return ProtocolConformanceRef::forAbstract(substTy, proto); - }, SubstFlags::SubstituteLocalArchetypes); + ReplaceExistentialArchetypesWithConcreteTypes replacer( + OAI.OpenedArchetype->getGenericEnvironment(), + CEI.ExistentialSubs); + NewCallSubs = NewCallSubs.subst(replacer, replacer, + SubstFlags::SubstituteLocalArchetypes); } // We need to make sure that we can a) update Apply to use the new args and b) diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp index 4de4eeac6423b..789550e71d50c 100644 --- a/lib/SILOptimizer/Transforms/CSE.cpp +++ b/lib/SILOptimizer/Transforms/CSE.cpp @@ -839,8 +839,7 @@ bool CSE::processLazyPropertyGetters(SILFunction &F) { /// archetypes. Replace such types by performing type substitutions /// according to the provided type substitution map. static void updateBasicBlockArgTypes(SILBasicBlock *BB, - ArchetypeType *OldOpenedArchetype, - ArchetypeType *NewOpenedArchetype, + InstructionCloner &Cloner, InstructionWorklist &usersToHandle) { // Check types of all BB arguments. for (auto *Arg : BB->getSILPhiArguments()) { @@ -850,15 +849,8 @@ static void updateBasicBlockArgTypes(SILBasicBlock *BB, // Try to apply substitutions to it and if it produces a different type, // use this type as new type of the BB argument. auto OldArgType = Arg->getType(); - auto NewArgType = OldArgType.subst(BB->getModule(), - [&](SubstitutableType *type) -> Type { - if (type == OldOpenedArchetype) - return NewOpenedArchetype; - return type; - }, - MakeAbstractConformanceForGenericType(), - CanGenericSignature(), - SubstFlags::SubstituteLocalArchetypes); + + auto NewArgType = Cloner.getOpType(OldArgType); if (NewArgType == Arg->getType()) continue; // Replace the type of this BB argument. The type of a BBArg @@ -910,13 +902,14 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst, usersToHandle.pushIfNotVisited(User); } + auto *OldEnv = OldOpenedArchetype->getGenericEnvironment(); + auto *NewEnv = NewOpenedArchetype->getGenericEnvironment(); + // Now process candidates. // Use a cloner. It makes copying the instruction and remapping of // opened archetypes trivial. InstructionCloner Cloner(Inst->getFunction()); - Cloner.registerLocalArchetypeRemapping( - OldOpenedArchetype->getGenericEnvironment(), - NewOpenedArchetype->getGenericEnvironment()); + Cloner.registerLocalArchetypeRemapping(OldEnv, NewEnv); auto &Builder = Cloner.getBuilder(); // Now clone each candidate and replace the opened archetype @@ -931,8 +924,7 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst, if (Successor->args_empty()) continue; // If a BB has any arguments, update their types if necessary. - updateBasicBlockArgTypes(Successor, OldOpenedArchetype, - NewOpenedArchetype, usersToHandle); + updateBasicBlockArgTypes(Successor, Cloner, usersToHandle); } } @@ -948,10 +940,7 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst, // Check if the result type depends on this specific opened existential. auto ResultDependsOnOldOpenedArchetype = - result->getType().getASTType().findIf( - [&OldOpenedArchetype](Type t) -> bool { - return (CanType(t) == OldOpenedArchetype); - }); + result->getType().getASTType()->hasLocalArchetypeFromEnvironment(OldEnv); // If it does, the candidate depends on the opened existential. if (ResultDependsOnOldOpenedArchetype) { diff --git a/lib/Sema/AssociatedTypeInference.cpp b/lib/Sema/AssociatedTypeInference.cpp index 724e53bf61893..3fa6ea780f17a 100644 --- a/lib/Sema/AssociatedTypeInference.cpp +++ b/lib/Sema/AssociatedTypeInference.cpp @@ -3458,8 +3458,7 @@ static Comparison compareDeclsForInference(DeclContext *DC, ValueDecl *decl1, if (!sig1 || !sig2) return TypeChecker::compareDeclarations(DC, decl1, decl2); - auto selfParam = GenericTypeParamType::getType(/*depth*/ 0, /*index*/ 0, - decl1->getASTContext()); + auto selfParam = DC->getASTContext().TheSelfType; // Collect the protocols required by extension 1. Type class1; diff --git a/lib/Sema/CodeSynthesisDistributedActor.cpp b/lib/Sema/CodeSynthesisDistributedActor.cpp index 591e26b5c1867..f98f5ec32bfe1 100644 --- a/lib/Sema/CodeSynthesisDistributedActor.cpp +++ b/lib/Sema/CodeSynthesisDistributedActor.cpp @@ -1077,11 +1077,8 @@ GetDistributedActorAsActorConformanceRequest::evaluate( if (!ext) return nullptr; - auto genericParam = GenericTypeParamType::getType(/*depth=*/0, /*index=*/0, - ctx); - auto distributedActorAsActorConformance = ctx.getNormalConformance( - Type(genericParam), actorProto, SourceLoc(), ext, + Type(ctx.TheSelfType), actorProto, SourceLoc(), ext, ProtocolConformanceState::Incomplete, ProtocolConformanceOptions()); // NOTE: Normally we "register" a conformance, but here we don't // because we cannot (currently) register them in a protocol, diff --git a/unittests/AST/ASTDumperTests.cpp b/unittests/AST/ASTDumperTests.cpp index 042ff30fd2539..9cb9f6fa83381 100644 --- a/unittests/AST/ASTDumperTests.cpp +++ b/unittests/AST/ASTDumperTests.cpp @@ -26,15 +26,14 @@ TEST(ASTDumper, ArchetypeType) { TestContext C; auto &ctx = C.Ctx; - auto *genericParamTy = GenericTypeParamType::getType(0, 0, ctx); - auto sig = buildGenericSignature(ctx, nullptr, {genericParamTy}, {}, + auto sig = buildGenericSignature(ctx, nullptr, {ctx.TheSelfType}, {}, /*allowInverses=*/true); TypeBase *archetype = nullptr; { llvm::SmallVector protocols; archetype = PrimaryArchetypeType::getNew(ctx, sig.getGenericEnvironment(), - genericParamTy, protocols, Type(), + ctx.TheSelfType, protocols, Type(), nullptr); }