Skip to content

Commit a5f6760

Browse files
committed
Eliminate remaining dependencies on a single underlying opaque type
The first generic parameter of an `OpaqueTypeDecl` was still being used as the "underlying" interface type of the opaque type, which is incorrect for both structural and named opaque result types. Eliminate this notion, because the (declared) interface type already has the correct structure. Only ABI checking depended on the old "underlying" type, so rework it to instead substitute into properly for structural opaque result types as well. Deserialization required a small adjustment to eliminate a cycle because the interface type of an `OpaqueTypeDecl` involves opaque archetype types, which reference the declaration itself... so deserialize the interface type later, now that it's correct.
1 parent a960f9c commit a5f6760

File tree

11 files changed

+40
-59
lines changed

11 files changed

+40
-59
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2719,9 +2719,6 @@ class OpaqueTypeDecl final :
27192719
/// abstracted underlying types.
27202720
GenericSignature OpaqueInterfaceGenericSignature;
27212721

2722-
/// The underlying type, which will involve the opaque generic parameters.
2723-
Type UnderlyingInterfaceType;
2724-
27252722
/// If known, the underlying type and conformances of the opaque type,
27262723
/// expressed as a SubstitutionMap for the opaque interface generic signature.
27272724
/// This maps types in the interface generic signature to the outer generic
@@ -2733,8 +2730,7 @@ class OpaqueTypeDecl final :
27332730
OpaqueTypeDecl(ValueDecl *NamingDecl, GenericParamList *GenericParams,
27342731
DeclContext *DC,
27352732
GenericSignature OpaqueInterfaceGenericSignature,
2736-
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
2737-
Type UnderlyingInterfaceType);
2733+
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs);
27382734

27392735
unsigned getNumOpaqueReturnTypeReprs() const {
27402736
return NamingDeclAndHasOpaqueReturnTypeRepr.getInt()
@@ -2751,8 +2747,7 @@ class OpaqueTypeDecl final :
27512747
ValueDecl *NamingDecl, GenericParamList *GenericParams,
27522748
DeclContext *DC,
27532749
GenericSignature OpaqueInterfaceGenericSignature,
2754-
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
2755-
Type UnderlyingInterfaceType);
2750+
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs);
27562751

27572752
ValueDecl *getNamingDecl() const {
27582753
return NamingDeclAndHasOpaqueReturnTypeRepr.getPointer();
@@ -2793,11 +2788,8 @@ class OpaqueTypeDecl final :
27932788
};
27942789
}
27952790

2796-
/// The underlying interface type describing the whole opaque type.
2797-
Type getUnderlyingInterfaceType() const {
2798-
return UnderlyingInterfaceType;
2799-
}
2800-
2791+
/// The substitutions that map the generic parameters of the opaque type to
2792+
/// their underlying types, when that information is known.
28012793
Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const {
28022794
return UnderlyingTypeSubstitutions;
28032795
}

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,18 +1510,18 @@ SDKNode *swift::ide::api::
15101510
SwiftDeclCollector::constructTypeNode(Type T, TypeInitInfo Info) {
15111511
if (Ctx.checkingABI()) {
15121512
T = T->getCanonicalType();
1513-
// If the type is a opaque result type (some Type) and we're in the ABI mode,
1514-
// we should substitute the opaque result type to its underlying type.
1515-
// Notice this only works if the opaque result type is from an inlinable
1516-
// function where the function body is present in the swift module file, thus
1517-
// allowing us to know the concrete type.
1518-
if (auto OTA = T->getAs<OpaqueTypeArchetypeType>()) {
1519-
if (auto *D = OTA->getDecl()) {
1520-
if (auto SubMap = D->getUnderlyingTypeSubstitutions()) {
1521-
T = D->getUnderlyingInterfaceType().
1522-
subst(*SubMap)->getCanonicalType();
1523-
}
1524-
}
1513+
1514+
if (T->hasOpaqueArchetype()) {
1515+
// When the type contains an opaque result type and we're in the ABI mode,
1516+
// we should substitute the opaque result type to its underlying type.
1517+
// Notice this only works if the opaque result type is from an inlinable
1518+
// function where the function body is present in the swift module file,
1519+
// thus allowing us to know the concrete type.
1520+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
1521+
/*inContext=*/nullptr, ResilienceExpansion::Maximal,
1522+
/*isWholeModuleContext=*/false);
1523+
T = T.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes)
1524+
->getCanonicalType();
15251525
}
15261526
}
15271527

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ namespace {
567567
OS << " naming_decl=";
568568
printDeclName(OTD->getNamingDecl());
569569
PrintWithColorRAII(OS, TypeColor) << " opaque_interface="
570-
<< OTD->getUnderlyingInterfaceType().getString();
570+
<< OTD->getDeclaredInterfaceType().getString();
571571
OS << " in "
572572
<< OTD->getOpaqueInterfaceGenericSignature()->getAsString();
573573
if (auto underlyingSubs = OTD->getUnderlyingTypeSubstitutions()) {

lib/AST/Decl.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7781,14 +7781,12 @@ OpaqueTypeDecl::OpaqueTypeDecl(ValueDecl *NamingDecl,
77817781
GenericParamList *GenericParams, DeclContext *DC,
77827782
GenericSignature OpaqueInterfaceGenericSignature,
77837783
ArrayRef<OpaqueReturnTypeRepr *>
7784-
OpaqueReturnTypeReprs,
7785-
Type UnderlyingInterfaceType)
7784+
OpaqueReturnTypeReprs)
77867785
: GenericTypeDecl(DeclKind::OpaqueType, DC, Identifier(), SourceLoc(), {},
77877786
GenericParams),
77887787
NamingDeclAndHasOpaqueReturnTypeRepr(
77897788
NamingDecl, !OpaqueReturnTypeReprs.empty()),
7790-
OpaqueInterfaceGenericSignature(OpaqueInterfaceGenericSignature),
7791-
UnderlyingInterfaceType(UnderlyingInterfaceType) {
7789+
OpaqueInterfaceGenericSignature(OpaqueInterfaceGenericSignature) {
77927790
// Always implicit.
77937791
setImplicit();
77947792

@@ -7806,15 +7804,14 @@ OpaqueTypeDecl *OpaqueTypeDecl::get(
78067804
ValueDecl *NamingDecl, GenericParamList *GenericParams,
78077805
DeclContext *DC,
78087806
GenericSignature OpaqueInterfaceGenericSignature,
7809-
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
7810-
Type UnderlyingInterfaceType) {
7807+
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs) {
78117808
ASTContext &ctx = DC->getASTContext();
78127809
auto size = totalSizeToAlloc<OpaqueReturnTypeRepr *>(
78137810
OpaqueReturnTypeReprs.size());
78147811
auto mem = ctx.Allocate(size, alignof(OpaqueTypeDecl));
78157812
return new (mem) OpaqueTypeDecl(
78167813
NamingDecl, GenericParams, DC, OpaqueInterfaceGenericSignature,
7817-
OpaqueReturnTypeReprs, UnderlyingInterfaceType);
7814+
OpaqueReturnTypeReprs);
78187815
}
78197816

78207817
bool OpaqueTypeDecl::isOpaqueReturnTypeOfFunction(

lib/AST/Type.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3323,8 +3323,9 @@ getArchetypeAndRootOpaqueArchetype(Type maybeOpaqueType) {
33233323
OpaqueSubstitutionKind
33243324
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
33253325
OpaqueTypeDecl *opaque) const {
3326-
return shouldPerformSubstitution(opaque, inContext->getParentModule(),
3327-
contextExpansion);
3326+
auto inModule = inContext ? inContext->getParentModule()
3327+
: opaque->getParentModule();
3328+
return shouldPerformSubstitution(opaque, inModule, contextExpansion);
33283329
}
33293330
OpaqueSubstitutionKind
33303331
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
@@ -3459,7 +3460,8 @@ operator()(SubstitutableType *maybeOpaqueType) const {
34593460
// context.
34603461
auto inContext = this->inContext;
34613462
auto isContextWholeModule = this->isContextWholeModule;
3462-
if (partialSubstTy.findIf(
3463+
if (inContext &&
3464+
partialSubstTy.findIf(
34633465
[inContext, substitutionKind, isContextWholeModule](Type t) -> bool {
34643466
if (!canSubstituteTypeInto(t, inContext, substitutionKind,
34653467
isContextWholeModule))
@@ -3515,6 +3517,7 @@ operator()(CanType maybeOpaqueType, Type replacementType,
35153517
// SIL type lowering may have already substituted away the opaque type, in
35163518
// which case we'll end up "substituting" the same type.
35173519
if (maybeOpaqueType->isEqual(replacementType)) {
3520+
assert(inContext && "Need context for already-substituted opaque types");
35183521
return inContext->getParentModule()
35193522
->lookupConformance(replacementType, protocol);
35203523
}

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,6 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
183183
auto originatingGenericContext = originatingDecl->getAsGenericContext();
184184
GenericParamList *genericParams;
185185
GenericSignature interfaceSignature;
186-
187-
// FIXME: The generic parameter that serves as the underlying type of the
188-
// opaque result type. This should become unnecessary, once we have fully
189-
// implemented structural opaque result types.
190-
GenericTypeParamType *underlyingGenericParamType;
191-
192186
CollectedOpaqueReprs opaqueReprs;
193187
if (auto namedOpaque = dyn_cast<NamedOpaqueReturnTypeRepr>(repr)) {
194188
// Produce the generic signature for the opaque type.
@@ -211,8 +205,6 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
211205
// Already produced an error.
212206
return nullptr;
213207
}
214-
215-
underlyingGenericParamType = interfaceSignature.getGenericParams()[0];
216208
} else {
217209
opaqueReprs = collectOpaqueReturnTypeReprs(repr);
218210
SmallVector<GenericTypeParamType *, 2> genericParamTypes;
@@ -285,13 +277,12 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
285277
genericParams = originatingGenericContext
286278
? originatingGenericContext->getGenericParams()
287279
: nullptr;
288-
underlyingGenericParamType = genericParamTypes[0];
289280
}
290281

291282
// Create the OpaqueTypeDecl for the result type.
292283
auto opaqueDecl = OpaqueTypeDecl::get(
293-
originatingDecl, genericParams, parentDC, interfaceSignature, opaqueReprs,
294-
underlyingGenericParamType);
284+
originatingDecl, genericParams, parentDC, interfaceSignature,
285+
opaqueReprs);
295286
opaqueDecl->copyFormalAccessFrom(originatingDecl);
296287
if (auto originatingSig = originatingDC->getGenericSignatureOfContext()) {
297288
opaqueDecl->setGenericSignature(originatingSig);

lib/Serialization/Deserialization.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3457,7 +3457,6 @@ class DeclDeserializer {
34573457

34583458
auto declContext = MF.getDeclContext(contextID);
34593459
auto interfaceSig = MF.getGenericSignature(interfaceSigID);
3460-
auto interfaceType = MF.getType(interfaceTypeID);
34613460

34623461
// Check for reentrancy.
34633462
if (declOrOffset.isComplete())
@@ -3468,13 +3467,13 @@ class DeclDeserializer {
34683467
// Create the decl.
34693468
auto opaqueDecl = OpaqueTypeDecl::get(
34703469
/*NamingDecl=*/ nullptr, genericParams, declContext,
3471-
interfaceSig, /*OpaqueReturnTypeReprs*/ { },
3472-
interfaceType);
3470+
interfaceSig, /*OpaqueReturnTypeReprs*/ { });
34733471
declOrOffset = opaqueDecl;
34743472

34753473
auto namingDecl = cast<ValueDecl>(MF.getDecl(namingDeclID));
34763474
opaqueDecl->setNamingDecl(namingDecl);
34773475

3476+
auto interfaceType = MF.getType(interfaceTypeID);
34783477
opaqueDecl->setInterfaceType(MetatypeType::get(interfaceType));
34793478

34803479
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))

lib/Serialization/Serialization.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,21 +3820,20 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
38203820
auto contextID = S.addDeclContextRef(opaqueDecl->getDeclContext());
38213821
auto interfaceSigID = S.addGenericSignatureRef(
38223822
opaqueDecl->getOpaqueInterfaceGenericSignature());
3823-
auto interfaceTypeID =
3824-
S.addTypeRef(opaqueDecl->getUnderlyingInterfaceType());
3823+
auto interfaceTypeID = S.addTypeRef(opaqueDecl->getDeclaredInterfaceType());
38253824

38263825
auto genericSigID = S.addGenericSignatureRef(opaqueDecl->getGenericSignature());
38273826

3828-
SubstitutionMapID underlyingTypeID = 0;
3827+
SubstitutionMapID underlyingSubsID = 0;
38293828
if (auto underlying = opaqueDecl->getUnderlyingTypeSubstitutions())
3830-
underlyingTypeID = S.addSubstitutionMapRef(*underlying);
3829+
underlyingSubsID = S.addSubstitutionMapRef(*underlying);
38313830
uint8_t rawAccessLevel =
38323831
getRawStableAccessLevel(opaqueDecl->getFormalAccess());
38333832
unsigned abbrCode = S.DeclTypeAbbrCodes[OpaqueTypeLayout::Code];
38343833
OpaqueTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
38353834
contextID.getOpaqueValue(), namingDeclID,
38363835
interfaceSigID, interfaceTypeID, genericSigID,
3837-
underlyingTypeID, rawAccessLevel);
3836+
underlyingSubsID, rawAccessLevel);
38383837
writeGenericParams(opaqueDecl->getGenericParams());
38393838
}
38403839

test/api-digester/Inputs/cake_baseline/cake.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ public class Zoo {
211211
}
212212
@inlinable
213213
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
214-
public func getCurrentAnimalInlinable() -> some Animal {
215-
return Cat()
214+
public func getCurrentAnimalInlinable() -> [some Animal] {
215+
return [Cat()]
216216
}
217217
}
218218

test/api-digester/Inputs/cake_current/cake.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,8 @@ public class Zoo {
224224
}
225225
@inlinable
226226
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
227-
public func getCurrentAnimalInlinable() -> some Animal {
228-
return Dog()
227+
public func getCurrentAnimalInlinable() -> [some Animal] {
228+
return [Dog()]
229229
}
230230
}
231231

test/api-digester/Outputs/Cake-abi.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ cake: Func C7.foo(_:_:) has removed default argument from parameter 1
5050
cake: Func EscapingFunctionType.addedEscaping(_:) has added @escaping in parameter 0
5151
cake: Func EscapingFunctionType.removedEscaping(_:) has removed @escaping in parameter 0
5252
cake: Func Somestruct2.foo1(_:) has parameter 0 type change from cake.C3 to cake.C1
53-
cake: Func Zoo.getCurrentAnimalInlinable() has return type change from cake.Cat to cake.Dog
53+
cake: Func Zoo.getCurrentAnimalInlinable() has return type change from [cake.Cat] to [cake.Dog]
5454
cake: Func ownershipChange(_:_:) has parameter 0 changing from InOut to Default
5555
cake: Func ownershipChange(_:_:) has parameter 1 changing from Shared to Owned
5656
cake: Func returnFunctionTypeOwnershipChange() has return type change from (cake.C1) -> () to (__owned cake.C1) -> ()

0 commit comments

Comments
 (0)