@@ -2640,34 +2640,176 @@ CanSILFunctionType swift::getNativeSILFunctionType(
2640
2640
substConstant, reqtSubs, witnessMethodConformance);
2641
2641
}
2642
2642
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
+
2643
2785
// / Build a generic signature and environment for a re-abstraction thunk.
2644
2786
// /
2645
2787
// / Most thunks share the generic environment with their original function.
2646
2788
// / The one exception is if the thunk type involves an open existential,
2647
2789
// / in which case we "promote" the opened existential to a new generic parameter.
2648
2790
// /
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
2652
2793
// / \param inheritGenericSig - whether to inherit the generic signature from the
2653
2794
// / parent function.
2654
2795
// / \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
2656
2798
// / \param interfaceSubs - map interface types to old archetypes
2657
2799
static CanGenericSignature
2658
2800
buildThunkSignature (SILFunction *fn,
2659
2801
bool inheritGenericSig,
2660
- OpenedArchetypeType *openedExistential ,
2802
+ ArrayRef<CanLocalArchetypeType> localArchetypes ,
2661
2803
GenericEnvironment *&genericEnv,
2662
2804
SubstitutionMap &contextSubs,
2663
2805
SubstitutionMap &interfaceSubs,
2664
- ArchetypeType *&newArchetype ) {
2806
+ llvm::DenseMap< ArchetypeType*, Type> &contextLocalArchetypes ) {
2665
2807
auto *mod = fn->getModule ().getSwiftModule ();
2666
2808
auto &ctx = mod->getASTContext ();
2667
2809
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 () ) {
2671
2813
auto genericSig =
2672
2814
fn->getLoweredFunctionType ()->getInvocationGenericSignature ();
2673
2815
genericEnv = fn->getGenericEnvironment ();
@@ -2677,7 +2819,7 @@ buildThunkSignature(SILFunction *fn,
2677
2819
}
2678
2820
2679
2821
// Add the existing generic signature.
2680
- int depth = 0 ;
2822
+ unsigned depth = 0 ;
2681
2823
GenericSignature baseGenericSig;
2682
2824
if (inheritGenericSig) {
2683
2825
if (auto genericSig =
@@ -2687,25 +2829,26 @@ buildThunkSignature(SILFunction *fn,
2687
2829
}
2688
2830
}
2689
2831
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);
2698
2834
2699
- Requirement newRequirement (RequirementKind::Conformance, newGenericParam,
2700
- constraint);
2835
+ for (auto archetype : localArchetypes) {
2836
+ collector.collect (archetype);
2837
+ }
2701
2838
2702
2839
auto genericSig = buildGenericSignature (ctx, baseGenericSig,
2703
- { newGenericParam } ,
2704
- { newRequirement } );
2840
+ collector. Params ,
2841
+ collector. Requirements );
2705
2842
genericEnv = genericSig.getGenericEnvironment ();
2706
2843
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
+ }
2709
2852
2710
2853
// Calculate substitutions to map the caller's archetypes to the thunk's
2711
2854
// archetypes.
@@ -2723,8 +2866,11 @@ buildThunkSignature(SILFunction *fn,
2723
2866
interfaceSubs = SubstitutionMap::get (
2724
2867
genericSig,
2725
2868
[&](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
+ }
2728
2874
return fn->mapTypeIntoContext (type);
2729
2875
},
2730
2876
MakeAbstractConformanceForGenericType ());
@@ -2768,18 +2914,16 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
2768
2914
if (withoutActuallyEscaping)
2769
2915
extInfoBuilder = extInfoBuilder.withNoEscape (false );
2770
2916
2771
- // Does the thunk type involve archetypes other than opened existentials ?
2917
+ // Does the thunk type involve archetypes other than local archetypes ?
2772
2918
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 ;
2775
2921
auto archetypeVisitor = [&](CanType t) {
2776
2922
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);
2783
2927
} else {
2784
2928
hasArchetypes = true ;
2785
2929
}
@@ -2790,32 +2934,38 @@ CanSILFunctionType swift::buildSILFunctionThunkType(
2790
2934
// generic parameters.
2791
2935
CanGenericSignature genericSig;
2792
2936
SubstitutionMap contextSubs;
2793
- ArchetypeType *newArchetype = nullptr ;
2937
+ llvm::DenseMap< ArchetypeType*, Type> contextLocalArchetypes ;
2794
2938
2795
2939
if (expectedType->hasArchetype () || sourceType->hasArchetype ()) {
2796
2940
expectedType.visit (archetypeVisitor);
2797
2941
sourceType.visit (archetypeVisitor);
2798
2942
2799
2943
genericSig = buildThunkSignature (fn,
2800
2944
hasArchetypes,
2801
- openedExistential ,
2945
+ localArchetypes ,
2802
2946
genericEnv,
2803
2947
contextSubs,
2804
2948
interfaceSubs,
2805
- newArchetype );
2949
+ contextLocalArchetypes );
2806
2950
}
2807
2951
2808
2952
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.
2812
2960
if (!archetype->isRoot ())
2813
2961
return Type ();
2814
- }
2815
2962
2816
- if (CanType (type) == openedExistential)
2817
- return newArchetype;
2963
+ auto it = contextLocalArchetypes.find (archetype);
2964
+ assert (it != contextLocalArchetypes.end ());
2965
+ return it->second ;
2966
+ }
2818
2967
2968
+ // Otherwise, use the context substitutions.
2819
2969
return Type (type).subst (contextSubs);
2820
2970
};
2821
2971
auto substConformanceHelper =
0 commit comments