@@ -148,6 +148,53 @@ UUID GenericEnvironment::getOpenedElementUUID() const {
148
148
return getTrailingObjects<OpenedElementEnvironmentData>()->uuid ;
149
149
}
150
150
151
+ namespace {
152
+
153
+ struct FindOpenedElementParam {
154
+ ArrayRef<Type> openedPacks;
155
+ TypeArrayView<GenericTypeParamType> packElementParams;
156
+
157
+ FindOpenedElementParam (const GenericEnvironment *env,
158
+ ArrayRef<Type> openedPacks)
159
+ : openedPacks(openedPacks),
160
+ packElementParams (
161
+ env->getGenericSignature ().getInnermostGenericParams()) {
162
+ assert (openedPacks.size () == packElementParams.size ());
163
+ }
164
+
165
+ GenericTypeParamType *operator ()(Type packParam) {
166
+ for (auto i : indices (openedPacks)) {
167
+ if (openedPacks[i]->isEqual (packParam))
168
+ return packElementParams[i];
169
+ }
170
+ llvm_unreachable (" parameter was not an opened pack parameter" );
171
+ }
172
+ };
173
+
174
+ struct FindElementArchetypeForOpenedPackParam {
175
+ FindOpenedElementParam findElementParam;
176
+ QueryInterfaceTypeSubstitutions getElementArchetype;
177
+
178
+ FindElementArchetypeForOpenedPackParam (const GenericEnvironment *env,
179
+ ArrayRef<Type> openedPacks)
180
+ : findElementParam(env, openedPacks), getElementArchetype(env) {}
181
+
182
+
183
+ ElementArchetypeType *operator ()(Type interfaceType) {
184
+ assert (interfaceType->isTypeParameter ());
185
+ if (auto member = interfaceType->getAs <DependentMemberType>()) {
186
+ auto baseArchetype = (*this )(member->getBase ());
187
+ return baseArchetype->getNestedType (member->getAssocType ())
188
+ ->castTo <ElementArchetypeType>();
189
+ }
190
+ assert (interfaceType->is <GenericTypeParamType>());
191
+ return getElementArchetype (findElementParam (interfaceType))
192
+ ->castTo <ElementArchetypeType>();
193
+ }
194
+ };
195
+
196
+ }
197
+
151
198
void GenericEnvironment::forEachPackElementArchetype (
152
199
llvm::function_ref<void (ElementArchetypeType *)> function) const {
153
200
auto packElements = getGenericSignature ().getInnermostGenericParams ();
@@ -613,25 +660,51 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
613
660
614
661
Type
615
662
GenericEnvironment::mapContextualPackTypeIntoElementContext (Type type) const {
663
+ assert (getKind () == Kind::OpenedElement);
664
+ assert (!type->hasTypeParameter () && " expected contextual type" );
665
+
616
666
if (!type->hasArchetype ()) return type;
617
667
618
- // FIXME: this is potentially wrong if there are multiple
619
- // openings in play at once, because we really shouldn't touch
620
- // other element archetypes.
621
- return mapPackTypeIntoElementContext (type->mapTypeOutOfContext ());
668
+ auto sig = getGenericSignature ();
669
+ auto shapeClass = getOpenedElementShapeClass ();
670
+
671
+ FindElementArchetypeForOpenedPackParam
672
+ findElementArchetype (this , getOpenedPackParams ());
673
+
674
+ return type.transformRec ([&](TypeBase *ty) -> Optional<Type> {
675
+ // We're only directly substituting pack archetypes.
676
+ auto archetype = ty->getAs <PackArchetypeType>();
677
+ if (!archetype) {
678
+ // Don't recurse into nested pack expansions.
679
+ if (ty->is <PackExpansionType>())
680
+ return Type (ty);
681
+
682
+ // Recurse into any other type.
683
+ return None;
684
+ }
685
+
686
+ auto rootArchetype = cast<PackArchetypeType>(archetype->getRoot ());
687
+
688
+ // TODO: assert that the generic environment of the pack archetype
689
+ // matches the signature that was originally opened to make this
690
+ // environment. Unfortunately, that isn't a trivial check because of
691
+ // the extra opened-element parameters.
692
+
693
+ // If the archetype isn't the shape that was opened by this
694
+ // environment, ignore it.
695
+ auto rootParam = cast<GenericTypeParamType>(
696
+ rootArchetype->getInterfaceType ().getPointer ());
697
+ assert (rootParam->isParameterPack ());
698
+ if (!sig->haveSameShape (rootParam, shapeClass))
699
+ return Type (ty);
700
+
701
+ return Type (findElementArchetype (archetype->getInterfaceType ()));
702
+ });
622
703
}
623
704
624
705
CanType
625
706
GenericEnvironment::mapContextualPackTypeIntoElementContext (CanType type) const {
626
- if (!type->hasArchetype ()) return type;
627
-
628
- // FIXME: this is potentially wrong if there are multiple
629
- // openings in play at once, because we really shouldn't touch
630
- // other element archetypes.
631
- // FIXME: if we do this properly, there's no way for this rewrite
632
- // to produce a non-canonical type.
633
- return mapPackTypeIntoElementContext (type->mapTypeOutOfContext ())
634
- ->getCanonicalType ();
707
+ return CanType (mapContextualPackTypeIntoElementContext (Type (type)));
635
708
}
636
709
637
710
Type
@@ -641,40 +714,34 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
641
714
642
715
auto sig = getGenericSignature ();
643
716
auto shapeClass = getOpenedElementShapeClass ();
644
- QueryInterfaceTypeSubstitutions substitutions (this );
645
717
646
- llvm::SmallDenseMap<GenericParamKey,
647
- GenericTypeParamType *> elementParamForPack;
648
- auto packElements = sig.getInnermostGenericParams ();
649
- auto elementDepth = packElements.front ()->getDepth ();
650
-
651
- for (auto *genericParam : sig.getGenericParams ()) {
652
- if (genericParam->getDepth () == elementDepth)
653
- break ;
654
-
655
- if (!genericParam->isParameterPack ())
656
- continue ;
657
-
658
- if (!sig->haveSameShape (genericParam, shapeClass))
659
- continue ;
660
-
661
- auto elementIndex = elementParamForPack.size ();
662
- elementParamForPack[{genericParam}] = packElements[elementIndex];
663
- }
718
+ FindElementArchetypeForOpenedPackParam
719
+ findElementArchetype (this , getOpenedPackParams ());
664
720
665
721
// Map the interface type to the element type by stripping
666
722
// away the isParameterPack bit before mapping type parameters
667
723
// to archetypes.
668
- return type.subst ([&](SubstitutableType *type) {
669
- auto *genericParam = type->getAs <GenericTypeParamType>();
670
- if (!genericParam)
671
- return Type ();
724
+ return type.transformRec ([&](TypeBase *ty) -> Optional<Type> {
725
+ // We're only directly substituting pack parameters.
726
+ if (!ty->isTypeParameter ()) {
727
+ // Don't recurse into nested pack expansions; just map it into
728
+ // context.
729
+ if (ty->is <PackExpansionType>())
730
+ return mapTypeIntoContext (ty);
731
+
732
+ // Recurse into any other type.
733
+ return None;
734
+ }
672
735
673
- if (auto *elementParam = elementParamForPack[{genericParam}])
674
- return substitutions (elementParam);
736
+ // Just do normal mapping for types that are not rooted in
737
+ // opened type parameters.
738
+ auto rootParam = ty->getRootGenericParam ();
739
+ if (!rootParam->isParameterPack () ||
740
+ !sig->haveSameShape (rootParam, shapeClass))
741
+ return mapTypeIntoContext (ty);
675
742
676
- return substitutions (genericParam );
677
- }, LookUpConformanceInSignature (sig. getPointer ()) );
743
+ return Type ( findElementArchetype (ty) );
744
+ });
678
745
}
679
746
680
747
Type
0 commit comments