Skip to content

Commit 7648833

Browse files
authored
Merge pull request #85094 from slavapestov/fix-rdar160804717
Fix spurious "infinite conformance substitution error" with parameter packs
2 parents 9102c65 + 41ff738 commit 7648833

File tree

10 files changed

+75
-45
lines changed

10 files changed

+75
-45
lines changed

lib/AST/SubstitutionMap.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,18 @@ bool SubstitutionMap::isIdentity() const {
620620

621621
SubstitutionMap swift::substOpaqueTypesWithUnderlyingTypes(
622622
SubstitutionMap subs, TypeExpansionContext context) {
623+
if (!context.shouldLookThroughOpaqueTypeArchetypes())
624+
return subs;
625+
626+
if (!subs.getRecursiveProperties().hasOpaqueArchetype() &&
627+
!llvm::any_of(subs.getConformances(),
628+
[&](ProtocolConformanceRef ref) {
629+
return (!ref.isInvalid() &&
630+
ref.getType()->hasOpaqueArchetype());
631+
})) {
632+
return subs;
633+
}
634+
623635
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
624636
context.getContext(), context.getResilienceExpansion(),
625637
context.isWholeModuleContext());

lib/AST/TypeSubstitution.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1089,11 +1089,19 @@ swift::substOpaqueTypesWithUnderlyingTypes(CanType ty,
10891089

10901090
ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes(
10911091
ProtocolConformanceRef ref, TypeExpansionContext context) {
1092+
if (ref.isInvalid())
1093+
return ref;
1094+
1095+
if (!context.shouldLookThroughOpaqueTypeArchetypes() ||
1096+
!ref.getType()->hasOpaqueArchetype())
1097+
return ref;
1098+
10921099
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
10931100
context.getContext(), context.getResilienceExpansion(),
10941101
context.isWholeModuleContext());
10951102
InFlightSubstitution IFS(replacer, replacer,
1096-
SubstFlags::SubstituteOpaqueArchetypes);
1103+
SubstFlags::SubstituteOpaqueArchetypes |
1104+
SubstFlags::PreservePackExpansionLevel);
10971105

10981106
auto substRef = ref.subst(IFS);
10991107

lib/IRGen/GenProto.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3761,8 +3761,8 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
37613761

37623762
// Look through any opaque types we're allowed to.
37633763
if (srcType->hasOpaqueArchetype()) {
3764-
std::tie(srcType, conformance) =
3765-
IGF.IGM.substOpaqueTypesWithUnderlyingTypes(srcType, conformance);
3764+
srcType = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(srcType);
3765+
conformance = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(conformance);
37663766
}
37673767

37683768
// If we don't have concrete conformance information, the type must be

lib/IRGen/GenReflection.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,7 @@ std::pair<llvm::Constant *, unsigned>
583583
IRGenModule::getLoweredTypeRef(SILType loweredType,
584584
CanGenericSignature genericSig,
585585
MangledTypeRefRole role) {
586-
auto substTy =
587-
substOpaqueTypesWithUnderlyingTypes(loweredType, genericSig);
586+
auto substTy = substOpaqueTypesWithUnderlyingTypes(loweredType);
588587
auto type = substTy.getASTType();
589588
return getTypeRefImpl(*this, type, genericSig, role);
590589
}
@@ -600,8 +599,8 @@ IRGenModule::emitWitnessTableRefString(CanType type,
600599
ProtocolConformanceRef conformance,
601600
GenericSignature origGenericSig,
602601
bool shouldSetLowBit) {
603-
std::tie(type, conformance)
604-
= substOpaqueTypesWithUnderlyingTypes(type, conformance);
602+
type = substOpaqueTypesWithUnderlyingTypes(type);
603+
conformance = substOpaqueTypesWithUnderlyingTypes(conformance);
605604

606605
auto origType = type;
607606
auto genericSig = origGenericSig.getCanonicalSignature();

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,10 +1162,9 @@ class IRGenModule {
11621162
CanType getRuntimeReifiedType(CanType type);
11631163
Type substOpaqueTypesWithUnderlyingTypes(Type type);
11641164
CanType substOpaqueTypesWithUnderlyingTypes(CanType type);
1165-
SILType substOpaqueTypesWithUnderlyingTypes(SILType type, CanGenericSignature genericSig);
1166-
std::pair<CanType, ProtocolConformanceRef>
1167-
substOpaqueTypesWithUnderlyingTypes(CanType type,
1168-
ProtocolConformanceRef conformance);
1165+
SILType substOpaqueTypesWithUnderlyingTypes(SILType type);
1166+
ProtocolConformanceRef
1167+
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef conformance);
11691168

11701169
bool isResilient(NominalTypeDecl *decl, ResilienceExpansion expansion,
11711170
ClassDecl *asViewedFromRootClass = nullptr);

lib/IRGen/MetadataRequest.cpp

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -494,46 +494,29 @@ CanType IRGenModule::getRuntimeReifiedType(CanType type) {
494494
Type IRGenModule::substOpaqueTypesWithUnderlyingTypes(Type type) {
495495
// Substitute away opaque types whose underlying types we're allowed to
496496
// assume are constant.
497-
if (type->hasOpaqueArchetype()) {
498-
auto context = getMaximalTypeExpansionContext();
499-
return swift::substOpaqueTypesWithUnderlyingTypes(type, context);
500-
}
501-
502-
return type;
497+
auto context = getMaximalTypeExpansionContext();
498+
return swift::substOpaqueTypesWithUnderlyingTypes(type, context);
503499
}
504500

505501
CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) {
506502
return substOpaqueTypesWithUnderlyingTypes(static_cast<Type>(type))
507503
->getCanonicalType();
508504
}
509505

510-
SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(
511-
SILType type, CanGenericSignature genericSig) {
506+
SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(SILType type) {
512507
// Substitute away opaque types whose underlying types we're allowed to
513508
// assume are constant.
514-
if (type.getASTType()->hasOpaqueArchetype()) {
515-
auto context = getMaximalTypeExpansionContext();
516-
return SILType::getPrimitiveType(
517-
swift::substOpaqueTypesWithUnderlyingTypes(type.getASTType(), context),
518-
type.getCategory());
519-
}
520-
521-
return type;
509+
auto context = getMaximalTypeExpansionContext();
510+
return SILType::getPrimitiveType(
511+
swift::substOpaqueTypesWithUnderlyingTypes(type.getASTType(), context),
512+
type.getCategory());
522513
}
523514

524-
std::pair<CanType, ProtocolConformanceRef>
525-
IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type,
526-
ProtocolConformanceRef conformance) {
527-
// Substitute away opaque types whose underlying types we're allowed to
528-
// assume are constant.
529-
if (type->hasOpaqueArchetype()) {
530-
auto context = getMaximalTypeExpansionContext();
531-
return std::make_pair(
532-
swift::substOpaqueTypesWithUnderlyingTypes(type, context),
533-
swift::substOpaqueTypesWithUnderlyingTypes(conformance, context));
534-
}
535-
536-
return std::make_pair(type, conformance);
515+
ProtocolConformanceRef
516+
IRGenModule::substOpaqueTypesWithUnderlyingTypes(
517+
ProtocolConformanceRef conformance) {
518+
auto context = getMaximalTypeExpansionContext();
519+
return swift::substOpaqueTypesWithUnderlyingTypes(conformance, context);
537520
}
538521

539522

lib/IRGen/Outlining.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void OutliningMetadataCollector::collectTypeMetadata(SILType ty) {
6868
}
6969

7070
// Substitute opaque types if allowed.
71-
ty = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(ty, CanGenericSignature());
71+
ty = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(ty);
7272

7373
collectTypeMetadataForLayout(ty);
7474
collectTypeMetadataForDeinit(ty);

lib/SIL/IR/SILTypeSubstitution.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,10 @@ class SILTypeSubstituter :
273273
// Substitute the underlying conformance of opaque type archetypes if we
274274
// should look through opaque archetypes.
275275
if (typeExpansionContext.shouldLookThroughOpaqueTypeArchetypes()) {
276-
auto substType = IFS.withNewOptions(std::nullopt, [&] {
277-
return selfType.subst(IFS)->getCanonicalType();
278-
});
276+
auto substType = IFS.withNewOptions(
277+
SubstFlags::PreservePackExpansionLevel, [&] {
278+
return selfType.subst(IFS)->getCanonicalType();
279+
});
279280
if (substType->hasOpaqueArchetype()) {
280281
substConformance = substOpaqueTypesWithUnderlyingTypes(
281282
substConformance, typeExpansionContext);

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,8 @@ findMissingGenericRequirementForSolutionFix(
10471047

10481048
return env->mapTypeIntoContext(gp);
10491049
},
1050-
LookUpConformanceInModule());
1050+
LookUpConformanceInModule(),
1051+
SubstFlags::PreservePackExpansionLevel);
10511052
};
10521053

10531054
type = getTypeInConformanceContext(type);

test/Generics/rdar160804717.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -target %target-swift-5.9-abi-triple
2+
// REQUIRES: objc_interop
3+
4+
// This used to trigger an infinite loop in conformance substitution
5+
// when emitting the opaque type descriptor in IRGen.
6+
7+
// rdar://160804717
8+
9+
import SwiftUI
10+
11+
public struct CategorySplitView<each Destination: View>: View {
12+
let titleKey: LocalizedStringKey
13+
let groups: (repeat each Destination)
14+
15+
public var body: some View {
16+
TupleView((repeat CategoryGroupSidebar(group: each groups))).navigationTitle(titleKey)
17+
}
18+
}
19+
20+
public struct CategoryGroupSidebar<Destination>: View {
21+
let group: Destination
22+
23+
public var body: some View {
24+
Text("Hi")
25+
}
26+
}
27+

0 commit comments

Comments
 (0)