Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,18 @@ bool SubstitutionMap::isIdentity() const {

SubstitutionMap swift::substOpaqueTypesWithUnderlyingTypes(
SubstitutionMap subs, TypeExpansionContext context) {
if (!context.shouldLookThroughOpaqueTypeArchetypes())
return subs;

if (!subs.getRecursiveProperties().hasOpaqueArchetype() &&
!llvm::any_of(subs.getConformances(),
[&](ProtocolConformanceRef ref) {
return (!ref.isInvalid() &&
ref.getType()->hasOpaqueArchetype());
})) {
return subs;
}

ReplaceOpaqueTypesWithUnderlyingTypes replacer(
context.getContext(), context.getResilienceExpansion(),
context.isWholeModuleContext());
Expand Down
10 changes: 9 additions & 1 deletion lib/AST/TypeSubstitution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1089,11 +1089,19 @@ swift::substOpaqueTypesWithUnderlyingTypes(CanType ty,

ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes(
ProtocolConformanceRef ref, TypeExpansionContext context) {
if (ref.isInvalid())
return ref;

if (!context.shouldLookThroughOpaqueTypeArchetypes() ||
!ref.getType()->hasOpaqueArchetype())
return ref;

ReplaceOpaqueTypesWithUnderlyingTypes replacer(
context.getContext(), context.getResilienceExpansion(),
context.isWholeModuleContext());
InFlightSubstitution IFS(replacer, replacer,
SubstFlags::SubstituteOpaqueArchetypes);
SubstFlags::SubstituteOpaqueArchetypes |
SubstFlags::PreservePackExpansionLevel);

auto substRef = ref.subst(IFS);

Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/GenProto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3761,8 +3761,8 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,

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

// If we don't have concrete conformance information, the type must be
Expand Down
7 changes: 3 additions & 4 deletions lib/IRGen/GenReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,7 @@ std::pair<llvm::Constant *, unsigned>
IRGenModule::getLoweredTypeRef(SILType loweredType,
CanGenericSignature genericSig,
MangledTypeRefRole role) {
auto substTy =
substOpaqueTypesWithUnderlyingTypes(loweredType, genericSig);
auto substTy = substOpaqueTypesWithUnderlyingTypes(loweredType);
auto type = substTy.getASTType();
return getTypeRefImpl(*this, type, genericSig, role);
}
Expand All @@ -600,8 +599,8 @@ IRGenModule::emitWitnessTableRefString(CanType type,
ProtocolConformanceRef conformance,
GenericSignature origGenericSig,
bool shouldSetLowBit) {
std::tie(type, conformance)
= substOpaqueTypesWithUnderlyingTypes(type, conformance);
type = substOpaqueTypesWithUnderlyingTypes(type);
conformance = substOpaqueTypesWithUnderlyingTypes(conformance);

auto origType = type;
auto genericSig = origGenericSig.getCanonicalSignature();
Expand Down
7 changes: 3 additions & 4 deletions lib/IRGen/IRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1162,10 +1162,9 @@ class IRGenModule {
CanType getRuntimeReifiedType(CanType type);
Type substOpaqueTypesWithUnderlyingTypes(Type type);
CanType substOpaqueTypesWithUnderlyingTypes(CanType type);
SILType substOpaqueTypesWithUnderlyingTypes(SILType type, CanGenericSignature genericSig);
std::pair<CanType, ProtocolConformanceRef>
substOpaqueTypesWithUnderlyingTypes(CanType type,
ProtocolConformanceRef conformance);
SILType substOpaqueTypesWithUnderlyingTypes(SILType type);
ProtocolConformanceRef
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef conformance);

bool isResilient(NominalTypeDecl *decl, ResilienceExpansion expansion,
ClassDecl *asViewedFromRootClass = nullptr);
Expand Down
41 changes: 12 additions & 29 deletions lib/IRGen/MetadataRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,46 +494,29 @@ CanType IRGenModule::getRuntimeReifiedType(CanType type) {
Type IRGenModule::substOpaqueTypesWithUnderlyingTypes(Type type) {
// Substitute away opaque types whose underlying types we're allowed to
// assume are constant.
if (type->hasOpaqueArchetype()) {
auto context = getMaximalTypeExpansionContext();
return swift::substOpaqueTypesWithUnderlyingTypes(type, context);
}

return type;
auto context = getMaximalTypeExpansionContext();
return swift::substOpaqueTypesWithUnderlyingTypes(type, context);
}

CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) {
return substOpaqueTypesWithUnderlyingTypes(static_cast<Type>(type))
->getCanonicalType();
}

SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(
SILType type, CanGenericSignature genericSig) {
SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(SILType type) {
// Substitute away opaque types whose underlying types we're allowed to
// assume are constant.
if (type.getASTType()->hasOpaqueArchetype()) {
auto context = getMaximalTypeExpansionContext();
return SILType::getPrimitiveType(
swift::substOpaqueTypesWithUnderlyingTypes(type.getASTType(), context),
type.getCategory());
}

return type;
auto context = getMaximalTypeExpansionContext();
return SILType::getPrimitiveType(
swift::substOpaqueTypesWithUnderlyingTypes(type.getASTType(), context),
type.getCategory());
}

std::pair<CanType, ProtocolConformanceRef>
IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type,
ProtocolConformanceRef conformance) {
// Substitute away opaque types whose underlying types we're allowed to
// assume are constant.
if (type->hasOpaqueArchetype()) {
auto context = getMaximalTypeExpansionContext();
return std::make_pair(
swift::substOpaqueTypesWithUnderlyingTypes(type, context),
swift::substOpaqueTypesWithUnderlyingTypes(conformance, context));
}

return std::make_pair(type, conformance);
ProtocolConformanceRef
IRGenModule::substOpaqueTypesWithUnderlyingTypes(
ProtocolConformanceRef conformance) {
auto context = getMaximalTypeExpansionContext();
return swift::substOpaqueTypesWithUnderlyingTypes(conformance, context);
}


Expand Down
2 changes: 1 addition & 1 deletion lib/IRGen/Outlining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void OutliningMetadataCollector::collectTypeMetadata(SILType ty) {
}

// Substitute opaque types if allowed.
ty = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(ty, CanGenericSignature());
ty = IGF.IGM.substOpaqueTypesWithUnderlyingTypes(ty);

collectTypeMetadataForLayout(ty);
collectTypeMetadataForDeinit(ty);
Expand Down
7 changes: 4 additions & 3 deletions lib/SIL/IR/SILTypeSubstitution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,10 @@ class SILTypeSubstituter :
// Substitute the underlying conformance of opaque type archetypes if we
// should look through opaque archetypes.
if (typeExpansionContext.shouldLookThroughOpaqueTypeArchetypes()) {
auto substType = IFS.withNewOptions(std::nullopt, [&] {
return selfType.subst(IFS)->getCanonicalType();
});
auto substType = IFS.withNewOptions(
SubstFlags::PreservePackExpansionLevel, [&] {
return selfType.subst(IFS)->getCanonicalType();
});
if (substType->hasOpaqueArchetype()) {
substConformance = substOpaqueTypesWithUnderlyingTypes(
substConformance, typeExpansionContext);
Expand Down
3 changes: 2 additions & 1 deletion lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,8 @@ findMissingGenericRequirementForSolutionFix(

return env->mapTypeIntoContext(gp);
},
LookUpConformanceInModule());
LookUpConformanceInModule(),
SubstFlags::PreservePackExpansionLevel);
};

type = getTypeInConformanceContext(type);
Expand Down
27 changes: 27 additions & 0 deletions test/Generics/rdar160804717.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// RUN: %target-swift-frontend -emit-ir %s -target %target-swift-5.9-abi-triple
// REQUIRES: objc_interop

// This used to trigger an infinite loop in conformance substitution
// when emitting the opaque type descriptor in IRGen.

// rdar://160804717

import SwiftUI

public struct CategorySplitView<each Destination: View>: View {
let titleKey: LocalizedStringKey
let groups: (repeat each Destination)

public var body: some View {
TupleView((repeat CategoryGroupSidebar(group: each groups))).navigationTitle(titleKey)
}
}

public struct CategoryGroupSidebar<Destination>: View {
let group: Destination

public var body: some View {
Text("Hi")
}
}