Skip to content

Commit e1f11e4

Browse files
committed
IRGen: We can't look through opaque archetypes if the underlying type contains a private type
Not without more context at least (where the substitution happens). The private type could be from a different TU. Yes, this can probably happen in earlier uses of opaque archetype substitution. For now, fix the known failure. rdar://56093964
1 parent 54ec600 commit e1f11e4

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

lib/IRGen/MetadataRequest.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,28 @@ CanType IRGenModule::getRuntimeReifiedType(CanType type) {
512512
}));
513513
}
514514

515+
static bool containsPrivateType(CanType ty) {
516+
return ty.findIf([](Type t) -> bool {
517+
if (auto *nominal = t->getAnyNominal()) {
518+
if (nominal->getEffectiveAccess() <= AccessLevel::FilePrivate)
519+
return true;
520+
}
521+
return false;
522+
});
523+
}
524+
515525
CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) {
516526
// Substitute away opaque types whose underlying types we're allowed to
517527
// assume are constant.
518528
if (type->hasOpaqueArchetype()) {
519529
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
520530
ResilienceExpansion::Maximal);
521-
type = type.subst(replacer, replacer,
522-
SubstFlags::SubstituteOpaqueArchetypes)
523-
->getCanonicalType();
531+
auto underlyingTy =
532+
type.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes)
533+
->getCanonicalType();
534+
// The underlying type could contain a private type from a different TU.
535+
if (!containsPrivateType(underlyingTy))
536+
return underlyingTy;
524537
}
525538

526539
return type;
@@ -533,8 +546,12 @@ SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes(
533546
if (type.getASTType()->hasOpaqueArchetype()) {
534547
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
535548
ResilienceExpansion::Maximal);
536-
type = type.subst(getSILModule(), replacer, replacer, genericSig,
537-
/*substitute opaque*/ true);
549+
auto underlyingTy =
550+
type.subst(getSILModule(), replacer, replacer, genericSig,
551+
/*substitute opaque*/ true);
552+
// The underlying type could contain a private type from a different TU.
553+
if (!containsPrivateType(underlyingTy.getASTType()))
554+
return underlyingTy;
538555
}
539556

540557
return type;
@@ -548,11 +565,14 @@ IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type,
548565
if (type->hasOpaqueArchetype()) {
549566
ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(),
550567
ResilienceExpansion::Maximal);
551-
conformance = conformance.subst(type, replacer, replacer,
552-
SubstFlags::SubstituteOpaqueArchetypes);
553-
type = type.subst(replacer, replacer,
554-
SubstFlags::SubstituteOpaqueArchetypes)
555-
->getCanonicalType();
568+
auto substConformance = conformance.subst(
569+
type, replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes);
570+
auto underlyingTy =
571+
type.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes)
572+
->getCanonicalType();
573+
// The underlying type could contain a private type from a different TU.
574+
if (!containsPrivateType(underlyingTy))
575+
return std::make_pair(underlyingTy, substConformance);
556576
}
557577

558578
return std::make_pair(type, conformance);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public protocol A {
2+
associatedtype Assoc
3+
func bindAssoc() -> Assoc
4+
}
5+
6+
public protocol Q {}
7+
8+
fileprivate struct PrivateS : Q {
9+
init() {}
10+
}
11+
12+
public struct G : A {
13+
public init() {}
14+
public func bindAssoc() -> some Q {
15+
return PrivateS()
16+
}
17+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -emit-ir -primary-file %s -primary-file %S/Inputs/opaque_result_type_private_underlying_2.swift
2+
3+
public struct G2 : A {
4+
public init() {}
5+
public func bindAssoc() -> some Q {
6+
return G().bindAssoc()
7+
}
8+
}

0 commit comments

Comments
 (0)