Skip to content

Commit 6b89415

Browse files
authored
[Serialization] Track whether a cross-reference came from Clang (#17333)
Cross-references are identified by their containing module, with the assumption that two modules will never have the same name. However, an overlay has the same name as its underlying Clang module, which means that there can be two declarations with the same name, the same type, and the same module name. This is the underlying cause of the 'UIEdgeInsetsZero' problem, but it also affects the CloudKit overlay. By tracking a bit that just says "this came from Clang", we're able to resolve otherwise ambiguous cross-references. (Why didn't we do it this way all along? Because if a declaration moves from Clang to Swift or vice versa, that would break the cross-reference. But that's only interesting if the swiftmodule format is meant to be persistent across changing dependencies, and it looks like we're moving away from that anyway. It's also a little weird for SerializedModuleLoader to have special cases for Clang, but this isn't the first.) Note that I'm not reverting the UIEdgeInsetsZero workaround here; the end state will have that coming just from UIKit as originally described. rdar://problem/40839486
1 parent a7209f6 commit 6b89415

File tree

4 files changed

+53
-23
lines changed

4 files changed

+53
-23
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 420; // Last change: accessor refactor
58+
const uint16_t VERSION_MINOR = 421; // Last change: track whether xrefs come from Clang
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -1308,21 +1308,24 @@ namespace decls_block {
13081308
XREF_TYPE_PATH_PIECE,
13091309
IdentifierIDField, // name
13101310
IdentifierIDField, // private discriminator
1311-
BCFixed<1> // restrict to protocol extension
1311+
BCFixed<1>, // restrict to protocol extension
1312+
BCFixed<1> // imported from Clang?
13121313
>;
13131314

13141315
using XRefValuePathPieceLayout = BCRecordLayout<
13151316
XREF_VALUE_PATH_PIECE,
13161317
TypeIDField, // type
13171318
IdentifierIDField, // name
13181319
BCFixed<1>, // restrict to protocol extension
1320+
BCFixed<1>, // imported from Clang?
13191321
BCFixed<1> // static?
13201322
>;
13211323

13221324
using XRefInitializerPathPieceLayout = BCRecordLayout<
13231325
XREF_INITIALIZER_PATH_PIECE,
13241326
TypeIDField, // type
13251327
BCFixed<1>, // restrict to protocol extension
1328+
BCFixed<1>, // imported from Clang?
13261329
CtorInitializerKindField // initializer kind
13271330
>;
13281331

lib/Serialization/Deserialization.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,8 @@ static bool reExportedToSameModule(const ModuleDecl *fromModule,
12041204
/// from Clang can also appear in any module.
12051205
static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
12061206
CanGenericSignature expectedGenericSig, bool isType,
1207-
bool inProtocolExt, bool isStatic,
1207+
bool inProtocolExt, bool importedFromClang,
1208+
bool isStatic,
12081209
Optional<swift::CtorInitializerKind> ctorInit,
12091210
SmallVectorImpl<ValueDecl *> &values) {
12101211
CanType canTy;
@@ -1226,6 +1227,8 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
12261227
return true;
12271228
if (value->isStatic() != isStatic)
12281229
return true;
1230+
if (value->hasClangNode() != importedFromClang)
1231+
return true;
12291232

12301233
if (value->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>())
12311234
return true;
@@ -1303,13 +1306,14 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
13031306
TypeID TID = 0;
13041307
bool isType = (recordID == XREF_TYPE_PATH_PIECE);
13051308
bool inProtocolExt = false;
1309+
bool importedFromClang = false;
13061310
bool isStatic = false;
13071311
if (isType)
13081312
XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
1309-
inProtocolExt);
1313+
inProtocolExt, importedFromClang);
13101314
else
13111315
XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
1312-
isStatic);
1316+
importedFromClang, isStatic);
13131317

13141318
DeclBaseName name = getDeclBaseName(IID);
13151319
pathTrace.addValue(name);
@@ -1337,8 +1341,8 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
13371341
NL_QualifiedDefault | NL_KnownNoDependency,
13381342
/*typeResolver=*/nullptr, values);
13391343
}
1340-
filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, isStatic,
1341-
None, values);
1344+
filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt,
1345+
importedFromClang, isStatic, None, values);
13421346
break;
13431347
}
13441348

@@ -1392,13 +1396,14 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
13921396
switch (recordID) {
13931397
case XREF_TYPE_PATH_PIECE: {
13941398
IdentifierID IID;
1395-
XRefTypePathPieceLayout::readRecord(scratch, IID, None, None);
1399+
XRefTypePathPieceLayout::readRecord(scratch, IID, None, None, None);
13961400
result = getIdentifier(IID);
13971401
break;
13981402
}
13991403
case XREF_VALUE_PATH_PIECE: {
14001404
IdentifierID IID;
1401-
XRefValuePathPieceLayout::readRecord(scratch, None, IID, None, None);
1405+
XRefValuePathPieceLayout::readRecord(scratch, None, IID, None, None,
1406+
None);
14021407
result = getIdentifier(IID);
14031408
break;
14041409
}
@@ -1451,8 +1456,9 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
14511456
IdentifierID IID;
14521457
IdentifierID privateDiscriminator;
14531458
bool onlyInNominal = false;
1459+
bool importedFromClang = false;
14541460
XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
1455-
onlyInNominal);
1461+
onlyInNominal, importedFromClang);
14561462
if (privateDiscriminator)
14571463
goto giveUpFastPath;
14581464

@@ -1509,12 +1515,13 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
15091515
Optional<swift::CtorInitializerKind> ctorInit;
15101516
bool isType = false;
15111517
bool inProtocolExt = false;
1518+
bool importedFromClang = false;
15121519
bool isStatic = false;
15131520
switch (recordID) {
15141521
case XREF_TYPE_PATH_PIECE: {
15151522
IdentifierID IID, discriminatorID;
15161523
XRefTypePathPieceLayout::readRecord(scratch, IID, discriminatorID,
1517-
inProtocolExt);
1524+
inProtocolExt, importedFromClang);
15181525
memberName = getDeclBaseName(IID);
15191526
privateDiscriminator = getIdentifier(discriminatorID);
15201527
isType = true;
@@ -1524,15 +1531,15 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
15241531
case XREF_VALUE_PATH_PIECE: {
15251532
IdentifierID IID;
15261533
XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
1527-
isStatic);
1534+
importedFromClang, isStatic);
15281535
memberName = getDeclBaseName(IID);
15291536
break;
15301537
}
15311538

15321539
case XREF_INITIALIZER_PATH_PIECE: {
15331540
uint8_t kind;
15341541
XRefInitializerPathPieceLayout::readRecord(scratch, TID, inProtocolExt,
1535-
kind);
1542+
importedFromClang, kind);
15361543
memberName = DeclBaseName::createConstructor();
15371544
ctorInit = getActualCtorInitializerKind(kind);
15381545
break;
@@ -1585,8 +1592,8 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
15851592
auto members = nominal->lookupDirect(memberName);
15861593
values.append(members.begin(), members.end());
15871594
}
1588-
filterValues(filterTy, M, genericSig, isType, inProtocolExt, isStatic,
1589-
ctorInit, values);
1595+
filterValues(filterTy, M, genericSig, isType, inProtocolExt,
1596+
importedFromClang, isStatic, ctorInit, values);
15901597
break;
15911598
}
15921599

lib/Serialization/Serialization.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,7 +1875,8 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
18751875
XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
18761876
addDeclBaseNameRef(generic->getName()),
18771877
addDeclBaseNameRef(discriminator),
1878-
false);
1878+
/*inProtocolExtension*/false,
1879+
generic->hasClangNode());
18791880
break;
18801881
}
18811882

@@ -1906,7 +1907,8 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19061907
bool isProtocolExt = SD->getDeclContext()->getAsProtocolExtensionContext();
19071908
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19081909
addTypeRef(ty), SUBSCRIPT_ID,
1909-
isProtocolExt, SD->isStatic());
1910+
isProtocolExt, SD->hasClangNode(),
1911+
SD->isStatic());
19101912
break;
19111913
}
19121914

@@ -1922,6 +1924,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19221924
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19231925
addTypeRef(ty), nameID,
19241926
isProtocolExt,
1927+
storage->hasClangNode(),
19251928
storage->isStatic());
19261929

19271930
abbrCode =
@@ -1946,6 +1949,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19461949
XRefInitializerPathPieceLayout::emitRecord(
19471950
Out, ScratchRecord, abbrCode, addTypeRef(ty),
19481951
(bool)ctor->getDeclContext()->getAsProtocolExtensionContext(),
1952+
ctor->hasClangNode(),
19491953
getStableCtorInitializerKind(ctor->getInitKind()));
19501954
break;
19511955
}
@@ -1955,7 +1959,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19551959
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19561960
addTypeRef(ty),
19571961
addDeclBaseNameRef(fn->getBaseName()),
1958-
isProtocolExt,
1962+
isProtocolExt, fn->hasClangNode(),
19591963
fn->isStatic());
19601964

19611965
if (fn->isOperator()) {
@@ -2035,7 +2039,7 @@ void Serializer::writeCrossReference(const Decl *D) {
20352039
XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
20362040
addDeclBaseNameRef(type->getName()),
20372041
addDeclBaseNameRef(discriminator),
2038-
isProtocolExt);
2042+
isProtocolExt, D->hasClangNode());
20392043
return;
20402044
}
20412045

@@ -2044,10 +2048,8 @@ void Serializer::writeCrossReference(const Decl *D) {
20442048
abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
20452049
IdentifierID iid = addDeclBaseNameRef(val->getBaseName());
20462050
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
2047-
addTypeRef(ty),
2048-
iid,
2049-
isProtocolExt,
2050-
val->isStatic());
2051+
addTypeRef(ty), iid, isProtocolExt,
2052+
D->hasClangNode(), val->isStatic());
20512053
}
20522054

20532055
/// Translate from the AST associativity enum to the Serialization enum
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -emit-module-path %t/main4.swiftmodule -swift-version 4 %s
3+
// RUN: %target-build-swift -emit-module-path %t/main4_2.swiftmodule -swift-version 4.2 %s
4+
5+
// REQUIRES: OS=macosx || OS=ios
6+
7+
import CloudKit
8+
9+
@available(macOS 10.10, iOS 8, *)
10+
extension CKRecord {
11+
@inlinable public func testMethod() -> Any? {
12+
return self.object(forKey: "abc" as CKRecord.FieldKey)
13+
}
14+
15+
@inlinable public func testSubscript() -> Any? {
16+
return self["abc" as CKRecord.FieldKey]
17+
}
18+
}

0 commit comments

Comments
 (0)