@@ -148,6 +148,53 @@ UUID GenericEnvironment::getOpenedElementUUID() const {
148148 return getTrailingObjects<OpenedElementEnvironmentData>()->uuid ;
149149}
150150
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+
151198void GenericEnvironment::forEachPackElementArchetype (
152199 llvm::function_ref<void (ElementArchetypeType *)> function) const {
153200 auto packElements = getGenericSignature ().getInnermostGenericParams ();
@@ -613,25 +660,51 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
613660
614661Type
615662GenericEnvironment::mapContextualPackTypeIntoElementContext (Type type) const {
663+ assert (getKind () == Kind::OpenedElement);
664+ assert (!type->hasTypeParameter () && " expected contextual type" );
665+
616666 if (!type->hasArchetype ()) return type;
617667
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+ });
622703}
623704
624705CanType
625706GenericEnvironment::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)));
635708}
636709
637710Type
@@ -641,40 +714,34 @@ GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
641714
642715 auto sig = getGenericSignature ();
643716 auto shapeClass = getOpenedElementShapeClass ();
644- QueryInterfaceTypeSubstitutions substitutions (this );
645717
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 ());
664720
665721 // Map the interface type to the element type by stripping
666722 // away the isParameterPack bit before mapping type parameters
667723 // 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+ }
672735
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);
675742
676- return substitutions (genericParam );
677- }, LookUpConformanceInSignature (sig. getPointer ()) );
743+ return Type ( findElementArchetype (ty) );
744+ });
678745}
679746
680747Type
0 commit comments