Skip to content

Commit 747d9df

Browse files
committed
swift-api-digester: add a field to indicate whether a decl or a conformance is ABI placeholder.
ABI placeholders are decls with attribute '@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)'. The diagnostics phase could be forgiving for ABI breakages on these decls since they are added recently. This patch adds a new flag to the json file indicating whether a declaration or a conformance is an ABI placeholder. The checking of placeholder is transitive, meaning a decl is an ABI placeholder if its decl context is one. rdar://49502365
1 parent f7406e6 commit 747d9df

File tree

6 files changed

+232
-4
lines changed

6 files changed

+232
-4
lines changed

include/swift/IDE/DigesterEnums.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ KEY_BOOL(HasStorage, hasStorage)
134134
KEY_BOOL(HasDidset, hasDidset)
135135
KEY_BOOL(HasWillset, hasWillset)
136136
KEY_BOOL(ReqNewWitnessTableEntry, reqNewWitnessTableEntry)
137+
KEY_BOOL(IsABIPlaceholder, isABIPlaceholder)
137138

138139
KEY(kind)
139140

test/api-digester/Inputs/cake.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,20 @@ class UsableFromInlineClass {
100100
class InternalType {}
101101

102102
extension InternalType {}
103+
104+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
105+
public extension PSuper {
106+
func futureFoo() {}
107+
}
108+
109+
public class FutureContainer {
110+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
111+
public func futureFoo() {}
112+
@available(macOS 9999, *)
113+
public func NotfutureFoo() {}
114+
}
115+
116+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
117+
extension FutureContainer: P1 {}
118+
119+
extension FutureContainer: P2 {}

test/api-digester/Outputs/cake-abi.json

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,24 @@
10111011
"protocolReq": true,
10121012
"reqNewWitnessTableEntry": true,
10131013
"funcSelfKind": "NonMutating"
1014+
},
1015+
{
1016+
"kind": "Function",
1017+
"name": "futureFoo",
1018+
"printedName": "futureFoo()",
1019+
"children": [
1020+
{
1021+
"kind": "TypeNominal",
1022+
"name": "Void",
1023+
"printedName": "()"
1024+
}
1025+
],
1026+
"declKind": "Func",
1027+
"usr": "s:4cake6PSuperPAAE9futureFooyyF",
1028+
"moduleName": "cake",
1029+
"genericSig": "<τ_0_0 where τ_0_0 : PSuper>",
1030+
"isABIPlaceholder": true,
1031+
"funcSelfKind": "NonMutating"
10141032
}
10151033
],
10161034
"declKind": "Protocol",
@@ -1157,6 +1175,71 @@
11571175
"UsableFromInline"
11581176
]
11591177
},
1178+
{
1179+
"kind": "TypeDecl",
1180+
"name": "FutureContainer",
1181+
"printedName": "FutureContainer",
1182+
"children": [
1183+
{
1184+
"kind": "Function",
1185+
"name": "futureFoo",
1186+
"printedName": "futureFoo()",
1187+
"children": [
1188+
{
1189+
"kind": "TypeNominal",
1190+
"name": "Void",
1191+
"printedName": "()"
1192+
}
1193+
],
1194+
"declKind": "Func",
1195+
"usr": "s:4cake15FutureContainerC9futureFooyyF",
1196+
"moduleName": "cake",
1197+
"isABIPlaceholder": true,
1198+
"declAttributes": [
1199+
"Available",
1200+
"Available",
1201+
"Available",
1202+
"Available"
1203+
],
1204+
"funcSelfKind": "NonMutating"
1205+
},
1206+
{
1207+
"kind": "Function",
1208+
"name": "NotfutureFoo",
1209+
"printedName": "NotfutureFoo()",
1210+
"children": [
1211+
{
1212+
"kind": "TypeNominal",
1213+
"name": "Void",
1214+
"printedName": "()"
1215+
}
1216+
],
1217+
"declKind": "Func",
1218+
"usr": "s:4cake15FutureContainerC12NotfutureFooyyF",
1219+
"moduleName": "cake",
1220+
"declAttributes": [
1221+
"Available"
1222+
],
1223+
"funcSelfKind": "NonMutating"
1224+
}
1225+
],
1226+
"declKind": "Class",
1227+
"usr": "s:4cake15FutureContainerC",
1228+
"moduleName": "cake",
1229+
"conformances": [
1230+
{
1231+
"kind": "Conformance",
1232+
"name": "P1",
1233+
"printedName": "P1",
1234+
"isABIPlaceholder": true
1235+
},
1236+
{
1237+
"kind": "Conformance",
1238+
"name": "P2",
1239+
"printedName": "P2"
1240+
}
1241+
]
1242+
},
11601243
{
11611244
"kind": "TypeDecl",
11621245
"name": "Int",

test/api-digester/Outputs/cake.json

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,24 @@
958958
"protocolReq": true,
959959
"reqNewWitnessTableEntry": true,
960960
"funcSelfKind": "NonMutating"
961+
},
962+
{
963+
"kind": "Function",
964+
"name": "futureFoo",
965+
"printedName": "futureFoo()",
966+
"children": [
967+
{
968+
"kind": "TypeNominal",
969+
"name": "Void",
970+
"printedName": "()"
971+
}
972+
],
973+
"declKind": "Func",
974+
"usr": "s:4cake6PSuperPAAE9futureFooyyF",
975+
"moduleName": "cake",
976+
"genericSig": "<Self where Self : PSuper>",
977+
"isABIPlaceholder": true,
978+
"funcSelfKind": "NonMutating"
961979
}
962980
],
963981
"declKind": "Protocol",
@@ -1046,6 +1064,71 @@
10461064
"Infix"
10471065
]
10481066
},
1067+
{
1068+
"kind": "TypeDecl",
1069+
"name": "FutureContainer",
1070+
"printedName": "FutureContainer",
1071+
"children": [
1072+
{
1073+
"kind": "Function",
1074+
"name": "futureFoo",
1075+
"printedName": "futureFoo()",
1076+
"children": [
1077+
{
1078+
"kind": "TypeNominal",
1079+
"name": "Void",
1080+
"printedName": "()"
1081+
}
1082+
],
1083+
"declKind": "Func",
1084+
"usr": "s:4cake15FutureContainerC9futureFooyyF",
1085+
"moduleName": "cake",
1086+
"isABIPlaceholder": true,
1087+
"declAttributes": [
1088+
"Available",
1089+
"Available",
1090+
"Available",
1091+
"Available"
1092+
],
1093+
"funcSelfKind": "NonMutating"
1094+
},
1095+
{
1096+
"kind": "Function",
1097+
"name": "NotfutureFoo",
1098+
"printedName": "NotfutureFoo()",
1099+
"children": [
1100+
{
1101+
"kind": "TypeNominal",
1102+
"name": "Void",
1103+
"printedName": "()"
1104+
}
1105+
],
1106+
"declKind": "Func",
1107+
"usr": "s:4cake15FutureContainerC12NotfutureFooyyF",
1108+
"moduleName": "cake",
1109+
"declAttributes": [
1110+
"Available"
1111+
],
1112+
"funcSelfKind": "NonMutating"
1113+
}
1114+
],
1115+
"declKind": "Class",
1116+
"usr": "s:4cake15FutureContainerC",
1117+
"moduleName": "cake",
1118+
"conformances": [
1119+
{
1120+
"kind": "Conformance",
1121+
"name": "P1",
1122+
"printedName": "P1",
1123+
"isABIPlaceholder": true
1124+
},
1125+
{
1126+
"kind": "Conformance",
1127+
"name": "P2",
1128+
"printedName": "P2"
1129+
}
1130+
]
1131+
},
10491132
{
10501133
"kind": "TypeDecl",
10511134
"name": "Int",

tools/swift-api-digester/ModuleAnalyzerNodes.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ SDKNodeDecl::SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind)
8787
IsProtocolReq(Info.IsProtocolReq),
8888
IsOverriding(Info.IsOverriding),
8989
IsOpen(Info.IsOpen),
90-
IsInternal(Info.IsInternal),
90+
IsInternal(Info.IsInternal), IsABIPlaceholder(Info.IsABIPlaceholder),
9191
ReferenceOwnership(uint8_t(Info.ReferenceOwnership)),
9292
GenericSig(Info.GenericSig), FixedBinaryOrder(Info.FixedBinaryOrder) {}
9393

@@ -111,7 +111,8 @@ SDKNodeDeclType::SDKNodeDeclType(SDKNodeInitInfo Info):
111111
EnumRawTypeName(Info.EnumRawTypeName) {}
112112

113113
SDKNodeConformance::SDKNodeConformance(SDKNodeInitInfo Info):
114-
SDKNode(Info, SDKNodeKind::Conformance) {}
114+
SDKNode(Info, SDKNodeKind::Conformance),
115+
IsABIPlaceholder(Info.IsABIPlaceholder) {}
115116

116117
SDKNodeTypeWitness::SDKNodeTypeWitness(SDKNodeInitInfo Info):
117118
SDKNode(Info, SDKNodeKind::TypeWitness) {}
@@ -1102,6 +1103,28 @@ Optional<uint8_t> SDKContext::getFixedBinaryOrder(ValueDecl *VD) const {
11021103
}
11031104
}
11041105

1106+
// check for if it has @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
1107+
static bool isABIPlaceHolder(Decl *D) {
1108+
llvm::SmallSet<PlatformKind, 4> Platforms;
1109+
for (auto *ATT: D->getAttrs()) {
1110+
if (auto *AVA = dyn_cast<AvailableAttr>(ATT)) {
1111+
if (AVA->Platform != PlatformKind::none && AVA->Introduced &&
1112+
AVA->Introduced->getMajor() == 9999) {
1113+
Platforms.insert(AVA->Platform);
1114+
}
1115+
}
1116+
}
1117+
return Platforms.size() == 4;
1118+
}
1119+
1120+
static bool isABIPlaceholderRecursive(Decl *D) {
1121+
for (auto *CD = D; CD; CD = CD->getDeclContext()->getAsDecl()) {
1122+
if (isABIPlaceHolder(CD))
1123+
return true;
1124+
}
1125+
return false;
1126+
}
1127+
11051128
SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Type Ty, TypeInitInfo Info) :
11061129
Ctx(Ctx), Name(getTypeName(Ctx, Ty, Info.IsImplicitlyUnwrappedOptional)),
11071130
PrintedName(getPrintedName(Ctx, Ty, Info.IsImplicitlyUnwrappedOptional)),
@@ -1121,7 +1144,8 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Decl *D):
11211144
ModuleName(D->getModuleContext()->getName().str()),
11221145
GenericSig(printGenericSignature(Ctx, D)),
11231146
IsImplicit(D->isImplicit()),
1124-
IsDeprecated(D->getAttrs().getDeprecated(D->getASTContext())) {
1147+
IsDeprecated(D->getAttrs().getDeprecated(D->getASTContext())),
1148+
IsABIPlaceholder(isABIPlaceholderRecursive(D)) {
11251149
// Capture all attributes.
11261150
auto AllAttrs = D->getAttrs();
11271151
std::transform(AllAttrs.begin(), AllAttrs.end(), std::back_inserter(DeclAttrs),
@@ -1134,6 +1158,15 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, OperatorDecl *OD):
11341158
PrintedName = OD->getName().str();
11351159
}
11361160

1161+
1162+
SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ProtocolConformance *Conform):
1163+
SDKNodeInitInfo(Ctx, Conform->getProtocol()) {
1164+
// Whether this conformance is ABI placeholder depends on the decl context
1165+
// of this conformance.
1166+
IsABIPlaceholder = isABIPlaceholderRecursive(Conform->getDeclContext()->
1167+
getAsDecl());
1168+
}
1169+
11371170
static bool isProtocolRequirement(ValueDecl *VD) {
11381171
if (isa<ProtocolDecl>(VD->getDeclContext()) && VD->isProtocolRequirement())
11391172
return true;
@@ -1517,7 +1550,7 @@ SwiftDeclCollector::constructConformanceNode(ProtocolConformance *Conform) {
15171550
if (Ctx.checkingABI())
15181551
Conform = Conform->getCanonicalConformance();
15191552
auto ConfNode = cast<SDKNodeConformance>(SDKNodeInitInfo(Ctx,
1520-
Conform->getProtocol()).createSDKNode(SDKNodeKind::Conformance));
1553+
Conform).createSDKNode(SDKNodeKind::Conformance));
15211554
Conform->forEachTypeWitness(nullptr,
15221555
[&](AssociatedTypeDecl *assoc, Type ty, TypeDecl *typeDecl) -> bool {
15231556
ConfNode->addChild(constructTypeWitnessNode(assoc, ty));
@@ -1643,6 +1676,11 @@ void SDKNode::jsonize(json::Output &out) {
16431676
out.mapOptional(getKeyContent(Ctx, KeyKind::KK_children).data(), Children);
16441677
}
16451678

1679+
void SDKNodeConformance::jsonize(json::Output &out) {
1680+
SDKNode::jsonize(out);
1681+
output(out, KeyKind::KK_isABIPlaceholder, IsABIPlaceholder);
1682+
}
1683+
16461684
void SDKNodeDecl::jsonize(json::Output &out) {
16471685
SDKNode::jsonize(out);
16481686
out.mapRequired(getKeyContent(Ctx, KeyKind::KK_declKind).data(), DKind);
@@ -1657,6 +1695,7 @@ void SDKNodeDecl::jsonize(json::Output &out) {
16571695
output(out, KeyKind::KK_implicit, IsImplicit);
16581696
output(out, KeyKind::KK_isOpen, IsOpen);
16591697
output(out, KeyKind::KK_isInternal, IsInternal);
1698+
output(out, KeyKind::KK_isABIPlaceholder, IsABIPlaceholder);
16601699
out.mapOptional(getKeyContent(Ctx, KeyKind::KK_declAttributes).data(), DeclAttributes);
16611700
out.mapOptional(getKeyContent(Ctx, KeyKind::KK_fixedbinaryorder).data(), FixedBinaryOrder);
16621701
// Strong reference is implied, no need for serialization.

tools/swift-api-digester/ModuleAnalyzerNodes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ class SDKNodeDecl: public SDKNode {
300300
bool IsOverriding;
301301
bool IsOpen;
302302
bool IsInternal;
303+
bool IsABIPlaceholder;
303304
uint8_t ReferenceOwnership;
304305
StringRef GenericSig;
305306
Optional<uint8_t> FixedBinaryOrder;
@@ -332,6 +333,7 @@ class SDKNodeDecl: public SDKNode {
332333
bool isOptional() const { return hasDeclAttribute(DeclAttrKind::DAK_Optional); }
333334
bool isOpen() const { return IsOpen; }
334335
bool isInternal() const { return IsInternal; }
336+
bool isABIPlaceholder() const { return IsABIPlaceholder; }
335337
StringRef getGenericSignature() const { return GenericSig; }
336338
StringRef getScreenInfo() const;
337339
bool hasFixedBinaryOrder() const { return FixedBinaryOrder.hasValue(); }
@@ -499,10 +501,13 @@ class SDKNodeDeclType: public SDKNodeDecl {
499501
class SDKNodeConformance: public SDKNode {
500502
SDKNodeDeclType *TypeDecl;
501503
friend class SDKNodeDeclType;
504+
bool IsABIPlaceholder;
502505
public:
503506
SDKNodeConformance(SDKNodeInitInfo Info);
504507
ArrayRef<SDKNode*> getTypeWitnesses() const { return Children; }
505508
SDKNodeDeclType *getNominalTypeDecl() const { return TypeDecl; }
509+
bool isABIPlaceholder() const { return IsABIPlaceholder; }
510+
void jsonize(json::Output &out) override;
506511
static bool classof(const SDKNode *N);
507512
};
508513

0 commit comments

Comments
 (0)