Skip to content

Commit fd97dac

Browse files
committed
[GenericEnvironment] Handle parameter packs in opened element signatures in
getOrCreateArchetypeFromInterfaceType. Instead of special casing parameter packs for primary generic environments, handle parameter packs in each kind of environment. For opened element environments, a pack archetype can be produced from the outer substitutions.
1 parent 8db8b7c commit fd97dac

File tree

2 files changed

+75
-55
lines changed

2 files changed

+75
-55
lines changed

lib/AST/GenericEnvironment.cpp

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -404,78 +404,82 @@ GenericEnvironment::getOrCreateArchetypeFromInterfaceType(Type depType) {
404404
Type result;
405405

406406
auto rootGP = requirements.anchor->getRootGenericParam();
407-
if (rootGP->isParameterPack()) {
408-
assert(getKind() == Kind::Primary);
409-
result = PackArchetypeType::get(ctx, this, requirements.anchor,
410-
requirements.packShape,
411-
requirements.protos, superclass,
412-
requirements.layout);
413-
} else {
414-
switch (getKind()) {
415-
case Kind::Primary:
407+
switch (getKind()) {
408+
case Kind::Primary:
409+
if (rootGP->isParameterPack()) {
410+
result = PackArchetypeType::get(ctx, this, requirements.anchor,
411+
requirements.packShape,
412+
requirements.protos, superclass,
413+
requirements.layout);
414+
} else {
416415
result = PrimaryArchetypeType::getNew(ctx, this, requirements.anchor,
417416
requirements.protos, superclass,
418417
requirements.layout);
419-
break;
418+
}
420419

421-
case Kind::Opaque: {
422-
// If the anchor type isn't rooted in a generic parameter that
423-
// represents an opaque declaration, then apply the outer substitutions.
424-
// It would be incorrect to build an opaque type archetype here.
425-
unsigned opaqueDepth =
426-
getOpaqueTypeDecl()->getOpaqueGenericParams().front()->getDepth();
427-
if (rootGP->getDepth() < opaqueDepth) {
428-
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
429-
break;
430-
}
420+
break;
421+
422+
case Kind::Opaque: {
423+
assert(!rootGP->isParameterPack());
431424

432-
result = OpaqueTypeArchetypeType::getNew(this, requirements.anchor,
433-
requirements.protos, superclass,
434-
requirements.layout);
425+
// If the anchor type isn't rooted in a generic parameter that
426+
// represents an opaque declaration, then apply the outer substitutions.
427+
// It would be incorrect to build an opaque type archetype here.
428+
unsigned opaqueDepth =
429+
getOpaqueTypeDecl()->getOpaqueGenericParams().front()->getDepth();
430+
if (rootGP->getDepth() < opaqueDepth) {
431+
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
435432
break;
436433
}
437434

438-
case Kind::OpenedExistential: {
439-
// FIXME: The existential layout's protocols might differ from the
440-
// canonicalized set of protocols determined by the generic signature.
441-
// Before NestedArchetypeType was removed, we used the former when
442-
// building a root OpenedArchetypeType, and the latter when building
443-
// nested archetypes.
444-
// For compatibility, continue using the existential layout's version when
445-
// the interface type is a generic parameter. We should align these at
446-
// some point.
447-
if (depType->is<GenericTypeParamType>()) {
448-
auto layout = getOpenedExistentialType()->getExistentialLayout();
449-
SmallVector<ProtocolDecl *, 2> protos;
450-
for (auto proto : layout.getProtocols())
451-
protos.push_back(proto);
452-
453-
result = OpenedArchetypeType::getNew(this, requirements.anchor, protos,
454-
superclass, requirements.layout);
455-
} else {
456-
result = OpenedArchetypeType::getNew(this, requirements.anchor,
435+
result = OpaqueTypeArchetypeType::getNew(this, requirements.anchor,
457436
requirements.protos, superclass,
458437
requirements.layout);
459-
}
438+
break;
439+
}
460440

461-
break;
441+
case Kind::OpenedExistential: {
442+
assert(!rootGP->isParameterPack());
443+
444+
// FIXME: The existential layout's protocols might differ from the
445+
// canonicalized set of protocols determined by the generic signature.
446+
// Before NestedArchetypeType was removed, we used the former when
447+
// building a root OpenedArchetypeType, and the latter when building
448+
// nested archetypes.
449+
// For compatibility, continue using the existential layout's version when
450+
// the interface type is a generic parameter. We should align these at
451+
// some point.
452+
if (depType->is<GenericTypeParamType>()) {
453+
auto layout = getOpenedExistentialType()->getExistentialLayout();
454+
SmallVector<ProtocolDecl *, 2> protos;
455+
for (auto proto : layout.getProtocols())
456+
protos.push_back(proto);
457+
458+
result = OpenedArchetypeType::getNew(this, requirements.anchor, protos,
459+
superclass, requirements.layout);
460+
} else {
461+
result = OpenedArchetypeType::getNew(this, requirements.anchor,
462+
requirements.protos, superclass,
463+
requirements.layout);
462464
}
463465

464-
case Kind::OpenedElement: {
465-
auto packElements = getGenericSignature().getInnermostGenericParams();
466-
auto elementDepth = packElements.front()->getDepth();
466+
break;
467+
}
467468

468-
if (rootGP->getDepth() < elementDepth) {
469-
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
470-
break;
471-
}
469+
case Kind::OpenedElement: {
470+
auto packElements = getGenericSignature().getInnermostGenericParams();
471+
auto elementDepth = packElements.front()->getDepth();
472472

473-
result = ElementArchetypeType::getNew(this, requirements.anchor,
474-
requirements.protos, superclass,
475-
requirements.layout);
473+
if (rootGP->getDepth() < elementDepth) {
474+
result = maybeApplyOuterContextSubstitutions(requirements.anchor);
476475
break;
477476
}
478-
}
477+
478+
result = ElementArchetypeType::getNew(this, requirements.anchor,
479+
requirements.protos, superclass,
480+
requirements.layout);
481+
break;
482+
}
479483
}
480484

481485
if (genericParam)

test/Constraints/pack-expansion-expressions.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,19 @@ func localValuePack<T...>(_ t: T...) -> (T..., T...) {
4242

4343
return (local..., localAnnotated...)
4444
}
45+
46+
protocol P {
47+
associatedtype A
48+
49+
var value: A { get }
50+
51+
func f(_ self: Self) -> Self
52+
}
53+
54+
func outerArchetype<T..., U>(t: T..., u: U) where T: P {
55+
let _: ((T.A, U)...) = ((t.value, u)...)
56+
}
57+
58+
func sameElement<T..., U>(t: T..., u: U) where T: P, T == U {
59+
let _: (T...) = (t.f(u)...)
60+
}

0 commit comments

Comments
 (0)