@@ -2640,34 +2640,176 @@ CanSILFunctionType swift::getNativeSILFunctionType(
26402640 substConstant, reqtSubs, witnessMethodConformance);
26412641}
26422642
2643+ namespace {
2644+ struct LocalArchetypeRequirementCollector {
2645+ const ASTContext &Context;
2646+ unsigned Depth;
2647+
2648+ // / The lists of new parameters and requirements to add to the signature.
2649+ SmallVector<GenericTypeParamType *, 2 > Params;
2650+ SmallVector<Requirement, 2 > Requirements;
2651+
2652+ // / The list of contextual types from the original function to use as
2653+ // / substitutions for the new parameters; parallel to Params.
2654+ SmallVector<Type, 4 > ParamSubs;
2655+
2656+ // / A mapping of local archetypes to the corresponding type parameters
2657+ // / created for them.
2658+ llvm::DenseMap<CanType, Type> ParamsForLocalArchetypes;
2659+
2660+ // / The set of element environments we've processed.
2661+ llvm::SmallPtrSet<GenericEnvironment*, 4 > ElementEnvs;
2662+
2663+ LocalArchetypeRequirementCollector (const ASTContext &ctx, unsigned depth)
2664+ : Context(ctx), Depth(depth) {}
2665+
2666+ void collect (CanLocalArchetypeType archetype) {
2667+ if (auto openedExistential = dyn_cast<OpenedArchetypeType>(archetype)) {
2668+ collect (openedExistential);
2669+ } else {
2670+ collect (cast<ElementArchetypeType>(archetype));
2671+ }
2672+ }
2673+
2674+ void collect (CanOpenedArchetypeType archetype) {
2675+ auto param = addParameter (archetype);
2676+
2677+ assert (archetype->isRoot ());
2678+ auto constraint = archetype->getExistentialType ();
2679+ if (auto existential = constraint->getAs <ExistentialType>())
2680+ constraint = existential->getConstraintType ();
2681+
2682+ addRequirement (RequirementKind::Conformance, param, constraint);
2683+ }
2684+
2685+ void collect (CanElementArchetypeType archetype) {
2686+ size_t startingIndex = Params.size ();
2687+
2688+ // Check whether we've already handled this environment.
2689+ // This can happen with opened-element environments because
2690+ // they can open multiple archetypes.
2691+ auto env = archetype->getGenericEnvironment ();
2692+ if (!ElementEnvs.insert (env).second ) return ;
2693+
2694+ // Add a parameter for each of the opened elements in this environment.
2695+ auto sig = env->getGenericSignature ();
2696+ auto elementParams = sig.getInnermostGenericParams ();
2697+ #ifndef NDEBUG
2698+ unsigned nextIndex = 0 ;
2699+ #endif
2700+ for (auto elementParam : elementParams) {
2701+ assert (elementParam->getIndex () == nextIndex++);
2702+ auto elementArchetype = env->mapTypeIntoContext (elementParam);
2703+ addParameter (cast<LocalArchetypeType>(CanType (elementArchetype)));
2704+ }
2705+
2706+ // Clone the element requirements.
2707+
2708+ // The element parameters should all have the same depth, and their
2709+ // index values are dense and in order from 0..<N in that depth.
2710+ // We asserted that above, and we'll use it below to map them to
2711+ // their new parameters in Params.
2712+ auto elementDepth = elementParams.front ()->getDepth ();
2713+
2714+ // Helper function: does the given type refer to an opened element
2715+ // parameter from the opened element generic signature?
2716+ auto refersToElementType = [=](Type type) {
2717+ return type.findIf ([&](Type t) {
2718+ if (auto *param = t->getAs <GenericTypeParamType>())
2719+ return (param->getDepth () == elementDepth);
2720+ return false ;
2721+ });
2722+ };
2723+ // Helper function: replace references to opened element parameters
2724+ // with one of the type parameters we just created for this
2725+ // environment.
2726+ auto rewriteElementType = [=](Type type) {
2727+ return type.transformRec ([&](Type t) -> Optional<Type> {
2728+ if (auto *param = t->getAs <GenericTypeParamType>()) {
2729+ if (param->getDepth () == elementDepth)
2730+ return Type (Params[startingIndex + param->getIndex ()]);
2731+ }
2732+ return None;
2733+ });
2734+ };
2735+
2736+ for (auto req : sig.getRequirements ()) {
2737+ switch (req.getKind ()) {
2738+ case RequirementKind::SameShape:
2739+ // These never involve element types.
2740+ break ;
2741+ case RequirementKind::Conformance:
2742+ if (refersToElementType (req.getFirstType ())) {
2743+ addRequirement (RequirementKind::Conformance,
2744+ rewriteElementType (req.getFirstType ()),
2745+ req.getSecondType ());
2746+ }
2747+ break ;
2748+ case RequirementKind::Superclass:
2749+ case RequirementKind::SameType:
2750+ if (refersToElementType (req.getFirstType ()) ||
2751+ refersToElementType (req.getSecondType ())) {
2752+ addRequirement (req.getKind (),
2753+ rewriteElementType (req.getFirstType ()),
2754+ rewriteElementType (req.getSecondType ()));
2755+ }
2756+ break ;
2757+ break ;
2758+ case RequirementKind::Layout:
2759+ if (refersToElementType (req.getFirstType ())) {
2760+ addRequirement (RequirementKind::Layout,
2761+ rewriteElementType (req.getFirstType ()),
2762+ req.getLayoutConstraint ());
2763+ }
2764+ break ;
2765+ }
2766+ }
2767+ }
2768+
2769+ GenericTypeParamType *addParameter (CanLocalArchetypeType localArchetype) {
2770+ auto *param = GenericTypeParamType::get (/* pack*/ false , Depth,
2771+ Params.size (), Context);
2772+ Params.push_back (param);
2773+ ParamSubs.push_back (localArchetype);
2774+ ParamsForLocalArchetypes.insert (std::make_pair (localArchetype, param));
2775+ return param;
2776+ }
2777+
2778+ template <class ... Args>
2779+ void addRequirement (Args &&... args) {
2780+ Requirements.emplace_back (std::forward<Args>(args)...);
2781+ }
2782+ };
2783+ } // end anonymous namespace
2784+
26432785// / Build a generic signature and environment for a re-abstraction thunk.
26442786// /
26452787// / Most thunks share the generic environment with their original function.
26462788// / The one exception is if the thunk type involves an open existential,
26472789// / in which case we "promote" the opened existential to a new generic parameter.
26482790// /
2649- // / \param SGF - the parent function
2650- // / \param openedExistential - the opened existential to promote to a generic
2651- // parameter, if any
2791+ // / \param localArchetypes - the list of local archetypes to promote
2792+ // / into the signature, if any
26522793// / \param inheritGenericSig - whether to inherit the generic signature from the
26532794// / parent function.
26542795// / \param genericEnv - the new generic environment
2655- // / \param contextSubs - map old archetypes to new archetypes
2796+ // / \param contextSubs - map non-local archetypes from the original function
2797+ // / to archetypes in the thunk
26562798// / \param interfaceSubs - map interface types to old archetypes
26572799static CanGenericSignature
26582800buildThunkSignature (SILFunction *fn,
26592801 bool inheritGenericSig,
2660- OpenedArchetypeType *openedExistential ,
2802+ ArrayRef<CanLocalArchetypeType> localArchetypes ,
26612803 GenericEnvironment *&genericEnv,
26622804 SubstitutionMap &contextSubs,
26632805 SubstitutionMap &interfaceSubs,
2664- ArchetypeType *&newArchetype ) {
2806+ llvm::DenseMap< ArchetypeType*, Type> &contextLocalArchetypes ) {
26652807 auto *mod = fn->getModule ().getSwiftModule ();
26662808 auto &ctx = mod->getASTContext ();
26672809
2668- // If there's no opened existential , we just inherit the generic environment
2669- // from the parent function.
2670- if (openedExistential == nullptr ) {
2810+ // If there are no local archetypes , we just inherit the generic
2811+ // environment from the parent function.
2812+ if (localArchetypes. empty () ) {
26712813 auto genericSig =
26722814 fn->getLoweredFunctionType ()->getInvocationGenericSignature ();
26732815 genericEnv = fn->getGenericEnvironment ();
@@ -2677,7 +2819,7 @@ buildThunkSignature(SILFunction *fn,
26772819 }
26782820
26792821 // Add the existing generic signature.
2680- int depth = 0 ;
2822+ unsigned depth = 0 ;
26812823 GenericSignature baseGenericSig;
26822824 if (inheritGenericSig) {
26832825 if (auto genericSig =
@@ -2687,25 +2829,26 @@ buildThunkSignature(SILFunction *fn,
26872829 }
26882830 }
26892831
2690- // Add a new generic parameter to replace the opened existential.
2691- auto *newGenericParam =
2692- GenericTypeParamType::get (/* isParameterPack*/ false , depth, 0 , ctx);
2693-
2694- assert (openedExistential->isRoot ());
2695- auto constraint = openedExistential->getExistentialType ();
2696- if (auto existential = constraint->getAs <ExistentialType>())
2697- constraint = existential->getConstraintType ();
2832+ // Add new generic parameters to replace the local archetypes.
2833+ LocalArchetypeRequirementCollector collector (ctx, depth);
26982834
2699- Requirement newRequirement (RequirementKind::Conformance, newGenericParam,
2700- constraint);
2835+ for (auto archetype : localArchetypes) {
2836+ collector.collect (archetype);
2837+ }
27012838
27022839 auto genericSig = buildGenericSignature (ctx, baseGenericSig,
2703- { newGenericParam } ,
2704- { newRequirement } );
2840+ collector. Params ,
2841+ collector. Requirements );
27052842 genericEnv = genericSig.getGenericEnvironment ();
27062843
2707- newArchetype = genericEnv->mapTypeIntoContext (newGenericParam)
2708- ->castTo <ArchetypeType>();
2844+ // Map the local archetypes to their new parameter types.
2845+ for (auto localArchetype : localArchetypes) {
2846+ auto param =
2847+ collector.ParamsForLocalArchetypes .find (localArchetype)->second ;
2848+ auto thunkArchetype = genericEnv->mapTypeIntoContext (param);
2849+ contextLocalArchetypes.insert (std::make_pair (localArchetype,
2850+ thunkArchetype));
2851+ }
27092852
27102853 // Calculate substitutions to map the caller's archetypes to the thunk's
27112854 // archetypes.
@@ -2723,8 +2866,11 @@ buildThunkSignature(SILFunction *fn,
27232866 interfaceSubs = SubstitutionMap::get (
27242867 genericSig,
27252868 [&](SubstitutableType *type) -> Type {
2726- if (type->isEqual (newGenericParam))
2727- return openedExistential;
2869+ if (auto param = dyn_cast<GenericTypeParamType>(type)) {
2870+ if (param->getDepth () == depth) {
2871+ return collector.ParamSubs [param->getIndex ()];
2872+ }
2873+ }
27282874 return fn->mapTypeIntoContext (type);
27292875 },
27302876 MakeAbstractConformanceForGenericType ());
@@ -2768,18 +2914,16 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
27682914 if (withoutActuallyEscaping)
27692915 extInfoBuilder = extInfoBuilder.withNoEscape (false );
27702916
2771- // Does the thunk type involve archetypes other than opened existentials ?
2917+ // Does the thunk type involve archetypes other than local archetypes ?
27722918 bool hasArchetypes = false ;
2773- // Does the thunk type involve an open existential type?
2774- CanOpenedArchetypeType openedExistential ;
2919+ // Does the thunk type involve a local archetype type?
2920+ SmallVector<CanLocalArchetypeType, 8 > localArchetypes ;
27752921 auto archetypeVisitor = [&](CanType t) {
27762922 if (auto archetypeTy = dyn_cast<ArchetypeType>(t)) {
2777- if (auto opened = dyn_cast<OpenedArchetypeType>(archetypeTy)) {
2778- const auto root = opened.getRoot ();
2779- assert ((openedExistential == CanArchetypeType () ||
2780- openedExistential == root) &&
2781- " one too many open existentials" );
2782- openedExistential = root;
2923+ if (auto opened = dyn_cast<LocalArchetypeType>(archetypeTy)) {
2924+ auto root = opened.getRoot ();
2925+ if (llvm::find (localArchetypes, root) == localArchetypes.end ())
2926+ localArchetypes.push_back (root);
27832927 } else {
27842928 hasArchetypes = true ;
27852929 }
@@ -2790,32 +2934,38 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
27902934 // generic parameters.
27912935 CanGenericSignature genericSig;
27922936 SubstitutionMap contextSubs;
2793- ArchetypeType *newArchetype = nullptr ;
2937+ llvm::DenseMap< ArchetypeType*, Type> contextLocalArchetypes ;
27942938
27952939 if (expectedType->hasArchetype () || sourceType->hasArchetype ()) {
27962940 expectedType.visit (archetypeVisitor);
27972941 sourceType.visit (archetypeVisitor);
27982942
27992943 genericSig = buildThunkSignature (fn,
28002944 hasArchetypes,
2801- openedExistential ,
2945+ localArchetypes ,
28022946 genericEnv,
28032947 contextSubs,
28042948 interfaceSubs,
2805- newArchetype );
2949+ contextLocalArchetypes );
28062950 }
28072951
28082952 auto substTypeHelper = [&](SubstitutableType *type) -> Type {
2809- // FIXME: Type::subst should not pass in non-root archetypes.
2810- // Consider only root archetypes.
2811- if (auto *archetype = dyn_cast<ArchetypeType>(type)) {
2953+ // If it's a local archetype, do an ad-hoc mapping through the
2954+ // map produced by buildThunkSignature.
2955+ if (auto *archetype = dyn_cast<LocalArchetypeType>(type)) {
2956+ assert (!contextLocalArchetypes.empty ());
2957+
2958+ // Decline to map non-root archetypes; subst() will come back
2959+ // to us later and ask about the root.
28122960 if (!archetype->isRoot ())
28132961 return Type ();
2814- }
28152962
2816- if (CanType (type) == openedExistential)
2817- return newArchetype;
2963+ auto it = contextLocalArchetypes.find (archetype);
2964+ assert (it != contextLocalArchetypes.end ());
2965+ return it->second ;
2966+ }
28182967
2968+ // Otherwise, use the context substitutions.
28192969 return Type (type).subst (contextSubs);
28202970 };
28212971 auto substConformanceHelper =
0 commit comments