Skip to content

Commit 06d27f0

Browse files
committed
Define @_implicitly_synthesizes_nested_requirement
State the previously unstated nested type requirement that CodingKeys adds to the witness requirements of a given type. The goal is to make this member cheap to synthesize, and independent of the expensive protocol conformance checks required to append it to the member list. Further, this makes a clean conceptual separation between what I'm calling "nested type requirements" and actual type and value requirements. With luck, we'll never have to use this attribute anywhere else.
1 parent 3ed0e19 commit 06d27f0

File tree

11 files changed

+91
-2
lines changed

11 files changed

+91
-2
lines changed

include/swift/AST/Attr.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,12 @@ DECL_ATTR(derivative, Derivative,
534534
ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove,
535535
97)
536536

537+
DECL_ATTR(_implicitly_synthesizes_nested_requirement, ImplicitlySynthesizesNestedRequirement,
538+
OnProtocol |
539+
UserInaccessible |
540+
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
541+
98)
542+
537543
#undef TYPE_ATTR
538544
#undef DECL_ATTR_ALIAS
539545
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/Attr.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,23 @@ class SwiftNativeObjCRuntimeBaseAttr : public DeclAttribute {
687687
}
688688
};
689689

690+
/// Defines the @_implicitly_synthesizes_nested_requirement attribute.
691+
class ImplicitlySynthesizesNestedRequirementAttr : public DeclAttribute {
692+
public:
693+
ImplicitlySynthesizesNestedRequirementAttr(StringRef Value, SourceLoc AtLoc,
694+
SourceRange Range)
695+
: DeclAttribute(DAK_ImplicitlySynthesizesNestedRequirement,
696+
AtLoc, Range, /*Implicit*/false),
697+
Value(Value) {}
698+
699+
/// The name of the phantom requirement.
700+
const StringRef Value;
701+
702+
static bool classof(const DeclAttribute *DA) {
703+
return DA->getKind() == DAK_ImplicitlySynthesizesNestedRequirement;
704+
}
705+
};
706+
690707
/// Determine the result of comparing an availability attribute to a specific
691708
/// platform or language version.
692709
enum class AvailableVersionComparison {

include/swift/AST/PrintOptions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ struct PrintOptions {
296296
/// List of attribute kinds that should not be printed.
297297
std::vector<AnyAttrKind> ExcludeAttrList = {DAK_Transparent, DAK_Effects,
298298
DAK_FixedLayout,
299-
DAK_ShowInInterface};
299+
DAK_ShowInInterface,
300+
DAK_ImplicitlySynthesizesNestedRequirement};
300301

301302
/// List of attribute kinds that should be printed exclusively.
302303
/// Empty means allow all.

lib/AST/Attr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,11 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
897897
break;
898898
}
899899

900+
case DAK_ImplicitlySynthesizesNestedRequirement:
901+
Printer.printAttrName("@_implicitly_synthesizes_nested_requirement");
902+
Printer << "(\"" << cast<ImplicitlySynthesizesNestedRequirementAttr>(this)->Value << "\")";
903+
break;
904+
900905
case DAK_Count:
901906
llvm_unreachable("exceed declaration attribute kinds");
902907

@@ -958,6 +963,8 @@ StringRef DeclAttribute::getAttrName() const {
958963
return "_swift_native_objc_runtime_base";
959964
case DAK_Semantics:
960965
return "_semantics";
966+
case DAK_ImplicitlySynthesizesNestedRequirement:
967+
return "_implicitly_synthesizes_nested_requirement";
961968
case DAK_Available:
962969
return "availability";
963970
case DAK_ObjC:

lib/Parse/ParseDecl.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,6 +1736,43 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
17361736
}
17371737
break;
17381738
}
1739+
1740+
case DAK_ImplicitlySynthesizesNestedRequirement: {
1741+
if (!consumeIf(tok::l_paren)) {
1742+
diagnose(Loc, diag::attr_expected_lparen, AttrName,
1743+
DeclAttribute::isDeclModifier(DK));
1744+
return false;
1745+
}
1746+
1747+
if (Tok.isNot(tok::string_literal)) {
1748+
diagnose(Loc, diag::attr_expected_string_literal, AttrName);
1749+
return false;
1750+
}
1751+
1752+
auto Value = getStringLiteralIfNotInterpolated(
1753+
Loc, ("'" + AttrName + "'").str());
1754+
1755+
consumeToken(tok::string_literal);
1756+
1757+
if (Value.hasValue())
1758+
AttrRange = SourceRange(Loc, Tok.getRange().getStart());
1759+
else
1760+
DiscardAttribute = true;
1761+
1762+
if (!consumeIf(tok::r_paren)) {
1763+
diagnose(Loc, diag::attr_expected_rparen, AttrName,
1764+
DeclAttribute::isDeclModifier(DK));
1765+
return false;
1766+
}
1767+
1768+
if (!DiscardAttribute) {
1769+
Attributes.add(new (Context)
1770+
ImplicitlySynthesizesNestedRequirementAttr(Value.getValue(), AtLoc,
1771+
AttrRange));
1772+
}
1773+
break;
1774+
}
1775+
17391776
case DAK_Available: {
17401777
if (!consumeIf(tok::l_paren)) {
17411778
diagnose(Loc, diag::attr_expected_lparen, AttrName,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
9696
IGNORED_ATTR(HasMissingDesignatedInitializers)
9797
IGNORED_ATTR(InheritsConvenienceInitializers)
9898
IGNORED_ATTR(Inline)
99+
IGNORED_ATTR(ImplicitlySynthesizesNestedRequirement)
99100
IGNORED_ATTR(ObjCBridged)
100101
IGNORED_ATTR(ObjCNonLazyRealization)
101102
IGNORED_ATTR(ObjCRuntimeName)

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,7 @@ namespace {
12981298
UNINTERESTING_ATTR(IBInspectable)
12991299
UNINTERESTING_ATTR(IBOutlet)
13001300
UNINTERESTING_ATTR(IBSegueAction)
1301+
UNINTERESTING_ATTR(ImplicitlySynthesizesNestedRequirement)
13011302
UNINTERESTING_ATTR(Indirect)
13021303
UNINTERESTING_ATTR(InheritsConvenienceInitializers)
13031304
UNINTERESTING_ATTR(Inline)

lib/Serialization/Deserialization.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4165,6 +4165,13 @@ llvm::Error DeclDeserializer::deserializeDeclAttributes() {
41654165
break;
41664166
}
41674167

4168+
case decls_block::ImplicitlySynthesizesNestedRequirement_DECL_ATTR: {
4169+
serialization::decls_block::ImplicitlySynthesizesNestedRequirementDeclAttrLayout
4170+
::readRecord(scratch);
4171+
Attr = new (ctx) ImplicitlySynthesizesNestedRequirementAttr(blobData, {}, {});
4172+
break;
4173+
}
4174+
41684175
#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
41694176
case decls_block::CLASS##_DECL_ATTR: { \
41704177
bool isImplicit; \

lib/Serialization/ModuleFormat.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t SWIFTMODULE_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 SWIFTMODULE_VERSION_MINOR = 529; // SILFunctionType substitutions
58+
const uint16_t SWIFTMODULE_VERSION_MINOR = 530; // @_implicitly_synthesizes_nested_requirement
5959

6060
/// A standard hash seed used for all string hashes in a serialized module.
6161
///
@@ -1811,6 +1811,10 @@ namespace decls_block {
18111811
TypeIDField // type referenced by this custom attribute
18121812
>;
18131813

1814+
using ImplicitlySynthesizesNestedRequirementDeclAttrLayout = BCRecordLayout<
1815+
ImplicitlySynthesizesNestedRequirement_DECL_ATTR,
1816+
BCBlob // member name
1817+
>;
18141818
}
18151819

18161820
/// Returns the encoding kind for the given decl.

lib/Serialization/Serialization.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,13 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
23642364
origDeclID, derivativeKind, indices);
23652365
return;
23662366
}
2367+
case DAK_ImplicitlySynthesizesNestedRequirement: {
2368+
auto *theAttr = cast<ImplicitlySynthesizesNestedRequirementAttr>(DA);
2369+
auto abbrCode = S.DeclTypeAbbrCodes[ImplicitlySynthesizesNestedRequirementDeclAttrLayout::Code];
2370+
ImplicitlySynthesizesNestedRequirementDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
2371+
theAttr->Value);
2372+
return;
2373+
}
23672374
}
23682375
}
23692376

0 commit comments

Comments
 (0)