Skip to content

Commit 5163888

Browse files
authored
[Serialization] Track whether a cross-reference came from Clang (#17377)
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 (cherry picked from commit 6b89415)
1 parent 0ca361f commit 5163888

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 = 413; // Last change: Remove discriminator from LocalDeclTableInfo.
58+
const uint16_t VERSION_MINOR = 414; // Last change: track whether xrefs come from Clang
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -1316,21 +1316,24 @@ namespace decls_block {
13161316
XREF_TYPE_PATH_PIECE,
13171317
IdentifierIDField, // name
13181318
IdentifierIDField, // private discriminator
1319-
BCFixed<1> // restrict to protocol extension
1319+
BCFixed<1>, // restrict to protocol extension
1320+
BCFixed<1> // imported from Clang?
13201321
>;
13211322

13221323
using XRefValuePathPieceLayout = BCRecordLayout<
13231324
XREF_VALUE_PATH_PIECE,
13241325
TypeIDField, // type
13251326
IdentifierIDField, // name
13261327
BCFixed<1>, // restrict to protocol extension
1328+
BCFixed<1>, // imported from Clang?
13271329
BCFixed<1> // static?
13281330
>;
13291331

13301332
using XRefInitializerPathPieceLayout = BCRecordLayout<
13311333
XREF_INITIALIZER_PATH_PIECE,
13321334
TypeIDField, // type
13331335
BCFixed<1>, // restrict to protocol extension
1336+
BCFixed<1>, // imported from Clang?
13341337
CtorInitializerKindField // initializer kind
13351338
>;
13361339

lib/Serialization/Deserialization.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,8 @@ static bool reExportedToSameModule(const ModuleDecl *fromModule,
11761176
/// from Clang can also appear in any module.
11771177
static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
11781178
CanGenericSignature expectedGenericSig, bool isType,
1179-
bool inProtocolExt, bool isStatic,
1179+
bool inProtocolExt, bool importedFromClang,
1180+
bool isStatic,
11801181
Optional<swift::CtorInitializerKind> ctorInit,
11811182
SmallVectorImpl<ValueDecl *> &values) {
11821183
CanType canTy;
@@ -1198,6 +1199,8 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
11981199
return true;
11991200
if (value->isStatic() != isStatic)
12001201
return true;
1202+
if (value->hasClangNode() != importedFromClang)
1203+
return true;
12011204

12021205
if (value->getAttrs().hasAttribute<ForbidSerializingReferenceAttr>())
12031206
return true;
@@ -1275,13 +1278,14 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
12751278
TypeID TID = 0;
12761279
bool isType = (recordID == XREF_TYPE_PATH_PIECE);
12771280
bool inProtocolExt = false;
1281+
bool importedFromClang = false;
12781282
bool isStatic = false;
12791283
if (isType)
12801284
XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
1281-
inProtocolExt);
1285+
inProtocolExt, importedFromClang);
12821286
else
12831287
XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
1284-
isStatic);
1288+
importedFromClang, isStatic);
12851289

12861290
DeclBaseName name = getDeclBaseName(IID);
12871291
pathTrace.addValue(name);
@@ -1309,8 +1313,8 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
13091313
NL_QualifiedDefault | NL_KnownNoDependency,
13101314
/*typeResolver=*/nullptr, values);
13111315
}
1312-
filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt, isStatic,
1313-
None, values);
1316+
filterValues(filterTy, nullptr, nullptr, isType, inProtocolExt,
1317+
importedFromClang, isStatic, None, values);
13141318
break;
13151319
}
13161320

@@ -1364,13 +1368,14 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
13641368
switch (recordID) {
13651369
case XREF_TYPE_PATH_PIECE: {
13661370
IdentifierID IID;
1367-
XRefTypePathPieceLayout::readRecord(scratch, IID, None, None);
1371+
XRefTypePathPieceLayout::readRecord(scratch, IID, None, None, None);
13681372
result = getIdentifier(IID);
13691373
break;
13701374
}
13711375
case XREF_VALUE_PATH_PIECE: {
13721376
IdentifierID IID;
1373-
XRefValuePathPieceLayout::readRecord(scratch, None, IID, None, None);
1377+
XRefValuePathPieceLayout::readRecord(scratch, None, IID, None, None,
1378+
None);
13741379
result = getIdentifier(IID);
13751380
break;
13761381
}
@@ -1423,8 +1428,9 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
14231428
IdentifierID IID;
14241429
IdentifierID privateDiscriminator;
14251430
bool onlyInNominal = false;
1431+
bool importedFromClang = false;
14261432
XRefTypePathPieceLayout::readRecord(scratch, IID, privateDiscriminator,
1427-
onlyInNominal);
1433+
onlyInNominal, importedFromClang);
14281434
if (privateDiscriminator)
14291435
goto giveUpFastPath;
14301436

@@ -1481,12 +1487,13 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
14811487
Optional<swift::CtorInitializerKind> ctorInit;
14821488
bool isType = false;
14831489
bool inProtocolExt = false;
1490+
bool importedFromClang = false;
14841491
bool isStatic = false;
14851492
switch (recordID) {
14861493
case XREF_TYPE_PATH_PIECE: {
14871494
IdentifierID IID, discriminatorID;
14881495
XRefTypePathPieceLayout::readRecord(scratch, IID, discriminatorID,
1489-
inProtocolExt);
1496+
inProtocolExt, importedFromClang);
14901497
memberName = getDeclBaseName(IID);
14911498
privateDiscriminator = getIdentifier(discriminatorID);
14921499
isType = true;
@@ -1496,15 +1503,15 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
14961503
case XREF_VALUE_PATH_PIECE: {
14971504
IdentifierID IID;
14981505
XRefValuePathPieceLayout::readRecord(scratch, TID, IID, inProtocolExt,
1499-
isStatic);
1506+
importedFromClang, isStatic);
15001507
memberName = getDeclBaseName(IID);
15011508
break;
15021509
}
15031510

15041511
case XREF_INITIALIZER_PATH_PIECE: {
15051512
uint8_t kind;
15061513
XRefInitializerPathPieceLayout::readRecord(scratch, TID, inProtocolExt,
1507-
kind);
1514+
importedFromClang, kind);
15081515
memberName = DeclBaseName::createConstructor();
15091516
ctorInit = getActualCtorInitializerKind(kind);
15101517
break;
@@ -1557,8 +1564,8 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
15571564
auto members = nominal->lookupDirect(memberName);
15581565
values.append(members.begin(), members.end());
15591566
}
1560-
filterValues(filterTy, M, genericSig, isType, inProtocolExt, isStatic,
1561-
ctorInit, values);
1567+
filterValues(filterTy, M, genericSig, isType, inProtocolExt,
1568+
importedFromClang, isStatic, ctorInit, values);
15621569
break;
15631570
}
15641571

lib/Serialization/Serialization.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,7 +1902,8 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19021902
XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19031903
addDeclBaseNameRef(generic->getName()),
19041904
addDeclBaseNameRef(discriminator),
1905-
false);
1905+
/*inProtocolExtension*/false,
1906+
generic->hasClangNode());
19061907
break;
19071908
}
19081909

@@ -1933,7 +1934,8 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19331934
bool isProtocolExt = SD->getDeclContext()->getAsProtocolExtensionContext();
19341935
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19351936
addTypeRef(ty), SUBSCRIPT_ID,
1936-
isProtocolExt, SD->isStatic());
1937+
isProtocolExt, SD->hasClangNode(),
1938+
SD->isStatic());
19371939
break;
19381940
}
19391941

@@ -1949,6 +1951,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19491951
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19501952
addTypeRef(ty), nameID,
19511953
isProtocolExt,
1954+
storage->hasClangNode(),
19521955
storage->isStatic());
19531956

19541957
abbrCode =
@@ -1973,6 +1976,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19731976
XRefInitializerPathPieceLayout::emitRecord(
19741977
Out, ScratchRecord, abbrCode, addTypeRef(ty),
19751978
(bool)ctor->getDeclContext()->getAsProtocolExtensionContext(),
1979+
ctor->hasClangNode(),
19761980
getStableCtorInitializerKind(ctor->getInitKind()));
19771981
break;
19781982
}
@@ -1982,7 +1986,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
19821986
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
19831987
addTypeRef(ty),
19841988
addDeclBaseNameRef(fn->getBaseName()),
1985-
isProtocolExt,
1989+
isProtocolExt, fn->hasClangNode(),
19861990
fn->isStatic());
19871991

19881992
if (fn->isOperator()) {
@@ -2062,7 +2066,7 @@ void Serializer::writeCrossReference(const Decl *D) {
20622066
XRefTypePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
20632067
addDeclBaseNameRef(type->getName()),
20642068
addDeclBaseNameRef(discriminator),
2065-
isProtocolExt);
2069+
isProtocolExt, D->hasClangNode());
20662070
return;
20672071
}
20682072

@@ -2071,10 +2075,8 @@ void Serializer::writeCrossReference(const Decl *D) {
20712075
abbrCode = DeclTypeAbbrCodes[XRefValuePathPieceLayout::Code];
20722076
IdentifierID iid = addDeclBaseNameRef(val->getBaseName());
20732077
XRefValuePathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
2074-
addTypeRef(ty),
2075-
iid,
2076-
isProtocolExt,
2077-
val->isStatic());
2078+
addTypeRef(ty), iid, isProtocolExt,
2079+
D->hasClangNode(), val->isStatic());
20782080
}
20792081

20802082
/// 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)