Skip to content

Commit efb43e3

Browse files
committed
Serialization: Cross-reference opaque return types by mangled name. rdar://problem/50005972
1 parent 0dbaa43 commit efb43e3

File tree

12 files changed

+139
-14
lines changed

12 files changed

+139
-14
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,6 +2786,8 @@ class OpaqueTypeDecl : public GenericTypeDecl {
27862786
/// signature of the original declaration.
27872787
Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
27882788

2789+
mutable Identifier OpaqueReturnTypeIdentifier;
2790+
27892791
public:
27902792
OpaqueTypeDecl(ValueDecl *NamingDecl,
27912793
GenericParamList *GenericParams,
@@ -2815,6 +2817,10 @@ class OpaqueTypeDecl : public GenericTypeDecl {
28152817
// Opaque type decls are currently always implicit
28162818
SourceRange getSourceRange() const { return SourceRange(); }
28172819

2820+
// Get the identifier string that can be used to cross-reference unnamed
2821+
// opaque return types across files.
2822+
Identifier getOpaqueReturnTypeIdentifier() const;
2823+
28182824
static bool classof(const Decl *D) {
28192825
return D->getKind() == DeclKind::OpaqueType;
28202826
}

include/swift/AST/PrintOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ struct PrintOptions {
521521
result.PrintInSILBody = true;
522522
result.PreferTypeRepr = false;
523523
result.PrintIfConfig = false;
524+
result.PrintStableReferencesToOpaqueReturnTypes = true;
524525
return result;
525526
}
526527

include/swift/Serialization/DeclTypeRecordNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ OTHER(XREF, 249)
188188
OTHER(INLINABLE_BODY_TEXT, 250)
189189
OTHER(SELF_PROTOCOL_CONFORMANCE, 251)
190190

191+
OTHER(XREF_OPAQUE_RETURN_TYPE_PATH_PIECE, 252)
192+
191193
#undef RECORD
192194
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL
193195
#undef RECORD_VAL

include/swift/Serialization/ModuleFormat.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,11 @@ namespace decls_block {
14271427
BCFixed<1>, // restrict to protocol extension
14281428
BCFixed<1> // imported from Clang?
14291429
>;
1430+
1431+
using XRefOpaqueReturnTypePathPieceLayout = BCRecordLayout<
1432+
XREF_OPAQUE_RETURN_TYPE_PATH_PIECE,
1433+
IdentifierIDField // mangled name of defining decl
1434+
>;
14301435

14311436
using XRefValuePathPieceLayout = BCRecordLayout<
14321437
XREF_VALUE_PATH_PIECE,

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "swift/Basic/STLExtras.h"
3838
#include "swift/Basic/StringExtras.h"
3939
#include "swift/Config.h"
40-
#include "swift/Demangling/ManglingMacros.h"
4140
#include "swift/Parse/Lexer.h"
4241
#include "swift/Strings.h"
4342
#include "clang/AST/ASTContext.h"
@@ -4173,15 +4172,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41734172
// type.
41744173
Printer << "@_opaqueReturnTypeOf(";
41754174

4176-
SmallString<64> mangleBuf;
4177-
{
4178-
llvm::raw_svector_ostream os(mangleBuf);
4179-
Mangle::ASTMangler mangler;
4180-
os << mangler.mangleDeclAsUSR(decl->getNamingDecl(),
4181-
MANGLING_PREFIX_STR);
4182-
}
4183-
4184-
Printer.printEscapedStringLiteral(mangleBuf);
4175+
Printer.printEscapedStringLiteral(
4176+
decl->getOpaqueReturnTypeIdentifier().str());
41854177

41864178
Printer << ", " << T->getInterfaceType()
41874179
->castTo<GenericTypeParamType>()

lib/AST/Decl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "swift/Basic/Range.h"
5151
#include "swift/Basic/StringExtras.h"
5252
#include "swift/Basic/Statistic.h"
53+
#include "swift/Demangling/ManglingMacros.h"
5354

5455
#include "clang/Basic/CharInfo.h"
5556
#include "clang/AST/Attr.h"
@@ -5933,6 +5934,22 @@ OpaqueTypeDecl::OpaqueTypeDecl(ValueDecl *NamingDecl,
59335934
setImplicit();
59345935
}
59355936

5937+
Identifier OpaqueTypeDecl::getOpaqueReturnTypeIdentifier() const {
5938+
assert(getNamingDecl() && "not an opaque return type");
5939+
if (!OpaqueReturnTypeIdentifier.empty())
5940+
return OpaqueReturnTypeIdentifier;
5941+
5942+
SmallString<64> mangleBuf;
5943+
{
5944+
llvm::raw_svector_ostream os(mangleBuf);
5945+
Mangle::ASTMangler mangler;
5946+
os << mangler.mangleDeclAsUSR(getNamingDecl(), MANGLING_PREFIX_STR);
5947+
}
5948+
5949+
OpaqueReturnTypeIdentifier = getASTContext().getIdentifier(mangleBuf);
5950+
return OpaqueReturnTypeIdentifier;
5951+
}
5952+
59365953
void AbstractFunctionDecl::computeType(AnyFunctionType::ExtInfo info) {
59375954
auto &ctx = getASTContext();
59385955
auto *sig = getGenericSignature();

lib/AST/Module.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,9 +1792,8 @@ SourceFile::lookupOpaqueResultType(StringRef MangledName,
17921792
void SourceFile::markDeclWithOpaqueResultTypeAsValidated(ValueDecl *vd) {
17931793
UnvalidatedDeclsWithOpaqueReturnTypes.erase(vd);
17941794
if (auto opaqueDecl = vd->getOpaqueResultTypeDecl()) {
1795-
Mangle::ASTMangler mangler;
1796-
auto name = mangler.mangleDeclAsUSR(vd, MANGLING_PREFIX_STR);
1797-
ValidatedOpaqueReturnTypes.insert({name, opaqueDecl});
1795+
ValidatedOpaqueReturnTypes.insert(
1796+
{opaqueDecl->getOpaqueReturnTypeIdentifier().str(), opaqueDecl});
17981797
}
17991798
}
18001799

lib/Serialization/Deserialization.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,20 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
13141314
importedFromClang, isStatic, None, values);
13151315
break;
13161316
}
1317+
1318+
case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
1319+
IdentifierID DefiningDeclNameID;
1320+
1321+
XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, DefiningDeclNameID);
1322+
1323+
auto name = getIdentifier(DefiningDeclNameID);
1324+
pathTrace.addOpaqueReturnType(name);
1325+
1326+
if (auto opaque = baseModule->lookupOpaqueResultType(name.str(), nullptr)) {
1327+
values.push_back(opaque);
1328+
}
1329+
break;
1330+
}
13171331

13181332
case XREF_EXTENSION_PATH_PIECE:
13191333
llvm_unreachable("can only extend a nominal");
@@ -1377,6 +1391,22 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
13771391
result = getIdentifier(IID);
13781392
break;
13791393
}
1394+
case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
1395+
IdentifierID IID;
1396+
XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, IID);
1397+
auto mangledName = getIdentifier(IID);
1398+
1399+
SmallString<64> buf;
1400+
{
1401+
llvm::raw_svector_ostream os(buf);
1402+
os << "<<opaque return type of ";
1403+
os << mangledName.str();
1404+
os << ">>";
1405+
}
1406+
1407+
result = getContext().getIdentifier(buf);
1408+
break;
1409+
}
13801410
case XREF_INITIALIZER_PATH_PIECE:
13811411
result = DeclBaseName::createConstructor();
13821412
break;
@@ -1683,6 +1713,22 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
16831713

16841714
break;
16851715
}
1716+
1717+
case XREF_OPAQUE_RETURN_TYPE_PATH_PIECE: {
1718+
values.clear();
1719+
IdentifierID DefiningDeclNameID;
1720+
1721+
XRefOpaqueReturnTypePathPieceLayout::readRecord(scratch, DefiningDeclNameID);
1722+
1723+
auto name = getIdentifier(DefiningDeclNameID);
1724+
pathTrace.addOpaqueReturnType(name);
1725+
1726+
if (auto opaqueTy = baseModule->lookupOpaqueResultType(name.str(),
1727+
nullptr)) {
1728+
values.push_back(opaqueTy);
1729+
}
1730+
break;
1731+
}
16861732

16871733
default:
16881734
// Unknown xref path piece.

lib/Serialization/DeserializationErrors.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class XRefTracePath {
3838
Extension,
3939
GenericParam,
4040
PrivateDiscriminator,
41+
OpaqueReturnType,
4142
Unknown
4243
};
4344

@@ -61,6 +62,7 @@ class XRefTracePath {
6162
case Kind::Value:
6263
case Kind::Operator:
6364
case Kind::PrivateDiscriminator:
65+
case Kind::OpaqueReturnType:
6466
return getDataAs<DeclBaseName>();
6567
case Kind::Type:
6668
case Kind::OperatorFilter:
@@ -146,6 +148,9 @@ class XRefTracePath {
146148
case Kind::PrivateDiscriminator:
147149
os << "(in " << getDataAs<Identifier>() << ")";
148150
break;
151+
case Kind::OpaqueReturnType:
152+
os << "opaque return type of " << getDataAs<DeclBaseName>();
153+
break;
149154
case Kind::Unknown:
150155
os << "unknown xref kind " << getDataAs<uintptr_t>();
151156
break;
@@ -196,6 +201,10 @@ class XRefTracePath {
196201
void addUnknown(uintptr_t kind) {
197202
path.push_back({ PathPiece::Kind::Unknown, kind });
198203
}
204+
205+
void addOpaqueReturnType(Identifier name) {
206+
path.push_back({ PathPiece::Kind::OpaqueReturnType, name });
207+
}
199208

200209
DeclBaseName getLastName() const {
201210
for (auto &piece : reversed(path)) {

lib/Serialization/Serialization.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1931,9 +1931,24 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19311931
break;
19321932

19331933
case DeclContextKind::GenericTypeDecl: {
1934+
auto generic = cast<GenericTypeDecl>(DC);
1935+
1936+
// Opaque return types are unnamed and need a special xref.
1937+
if (auto opaque = dyn_cast<OpaqueTypeDecl>(generic)) {
1938+
if (!opaque->hasName()) {
1939+
abbrCode = DeclTypeAbbrCodes[XRefOpaqueReturnTypePathPieceLayout::Code];
1940+
1941+
XRefOpaqueReturnTypePathPieceLayout::emitRecord(Out, ScratchRecord,
1942+
abbrCode,
1943+
addDeclBaseNameRef(opaque->getOpaqueReturnTypeIdentifier()));
1944+
break;
1945+
}
1946+
}
1947+
1948+
assert(generic->hasName());
1949+
19341950
writeCrossReference(DC->getParent(), pathLen + 1);
19351951

1936-
auto generic = cast<GenericTypeDecl>(DC);
19371952
abbrCode = DeclTypeAbbrCodes[XRefTypePathPieceLayout::Code];
19381953

19391954
Identifier discriminator;
@@ -2088,6 +2103,14 @@ void Serializer::writeCrossReference(const Decl *D) {
20882103

20892104
writeCrossReference(D->getDeclContext());
20902105

2106+
if (auto opaque = dyn_cast<OpaqueTypeDecl>(D)) {
2107+
abbrCode = DeclTypeAbbrCodes[XRefOpaqueReturnTypePathPieceLayout::Code];
2108+
XRefOpaqueReturnTypePathPieceLayout::emitRecord(Out, ScratchRecord,
2109+
abbrCode,
2110+
addDeclBaseNameRef(opaque->getOpaqueReturnTypeIdentifier()));
2111+
return;
2112+
}
2113+
20912114
if (auto genericParam = dyn_cast<GenericTypeParamDecl>(D)) {
20922115
assert(!D->getDeclContext()->isModuleScopeContext() &&
20932116
"Cannot cross reference a generic type decl at module scope.");
@@ -4274,6 +4297,7 @@ void Serializer::writeAllDeclsAndTypes() {
42744297
registerDeclTypeAbbr<TopLevelCodeDeclContextLayout>();
42754298

42764299
registerDeclTypeAbbr<XRefTypePathPieceLayout>();
4300+
registerDeclTypeAbbr<XRefOpaqueReturnTypePathPieceLayout>();
42774301
registerDeclTypeAbbr<XRefValuePathPieceLayout>();
42784302
registerDeclTypeAbbr<XRefExtensionPathPieceLayout>();
42794303
registerDeclTypeAbbr<XRefOperatorOrAccessorPathPieceLayout>();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public protocol Butt {}
2+
extension Int: Butt {}
3+
4+
public func exportsOpaqueReturn() -> some Butt { return 0 }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/OpaqueReturnTypeExporter.swiftmodule -module-name OpaqueReturnTypeExporter %S/Inputs/OpaqueReturnTypeExporter.swift
3+
// RUN: %target-sil-opt -I %t %s -emit-sib -module-name test -o %t/test.sib
4+
// RUN: %target-swift-frontend -I %t -emit-ir %t/test.sib
5+
6+
import OpaqueReturnTypeExporter
7+
8+
typealias SomeButt = @_opaqueReturnTypeOf("$s24OpaqueReturnTypeExporter07exportsaB0QryF", 0) opaque
9+
10+
sil @$s24OpaqueReturnTypeExporter07exportsaB0QryF : $@convention(thin) () -> @out SomeButt
11+
12+
sil @use_opaque_type : $@convention(thin) () -> () {
13+
entry:
14+
%f = function_ref @$s24OpaqueReturnTypeExporter07exportsaB0QryF : $@convention(thin) () -> @out SomeButt
15+
%x = alloc_stack $SomeButt
16+
apply %f(%x) : $@convention(thin) () -> @out SomeButt
17+
destroy_addr %x : $*SomeButt
18+
dealloc_stack %x : $*SomeButt
19+
return undef : $()
20+
}

0 commit comments

Comments
 (0)