Skip to content

Commit 0dde044

Browse files
authored
Merge pull request swiftlang#76256 from meg-gupta/lifetimeattrsyntax
Introduce @Lifetime attribute to specify lifetime dependence on function declarations
2 parents 82e7bee + c5f2c5f commit 0dde044

23 files changed

+789
-288
lines changed

include/swift/AST/Attr.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/DeclNameLoc.h"
2525
#include "swift/AST/Identifier.h"
2626
#include "swift/AST/KnownProtocols.h"
27+
#include "swift/AST/LifetimeDependence.h"
2728
#include "swift/AST/MacroDeclaration.h"
2829
#include "swift/AST/Ownership.h"
2930
#include "swift/AST/PlatformKind.h"
@@ -2627,6 +2628,31 @@ class RawLayoutAttr final : public DeclAttribute {
26272628
}
26282629
};
26292630

2631+
class LifetimeAttr final
2632+
: public DeclAttribute,
2633+
private llvm::TrailingObjects<LifetimeAttr, LifetimeEntry> {
2634+
2635+
friend TrailingObjects;
2636+
2637+
unsigned NumEntries = 0;
2638+
2639+
explicit LifetimeAttr(SourceLoc atLoc, SourceRange baseRange, bool implicit,
2640+
ArrayRef<LifetimeEntry> entries);
2641+
2642+
public:
2643+
static LifetimeAttr *create(ASTContext &context, SourceLoc atLoc,
2644+
SourceRange baseRange, bool implicit,
2645+
ArrayRef<LifetimeEntry> entries);
2646+
2647+
ArrayRef<LifetimeEntry> getLifetimeEntries() const {
2648+
return {getTrailingObjects<LifetimeEntry>(), NumEntries};
2649+
}
2650+
2651+
static bool classof(const DeclAttribute *DA) {
2652+
return DA->getKind() == DeclAttrKind::Lifetime;
2653+
}
2654+
};
2655+
26302656
/// Predicate used to filter MatchingAttributeRange.
26312657
template <typename ATTR, bool AllowInvalid> struct ToAttributeKind {
26322658
ToAttributeKind() {}

include/swift/AST/DeclAttr.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,10 @@ SIMPLE_DECL_ATTR(unsafe, Unsafe,
506506
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
507507
160)
508508

509+
DECL_ATTR(lifetime, Lifetime,
510+
OnAccessor | OnConstructor | OnFunc | OnSubscript | LongAttribute | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
511+
161)
512+
509513
LAST_DECL_ATTR(Unsafe)
510514

511515
#undef DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7952,6 +7952,9 @@ ERROR(lifetime_dependence_function_type, none,
79527952
"lifetime dependencies on function types are not supported",
79537953
())
79547954

7955+
ERROR(lifetime_dependence_immortal_alone, none,
7956+
"cannot specify any other dependence source along with immortal", ())
7957+
79557958
//===----------------------------------------------------------------------===//
79567959
// MARK: Sending
79577960
//===----------------------------------------------------------------------===//

include/swift/AST/LifetimeDependence.h

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- LifetimeDependenceSpecifiers.h ------------------------*- C++ -*-===//
1+
//===--- LifetimeDependence.h ---------------------------------*- C++ -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -43,13 +43,12 @@ enum class ParsedLifetimeDependenceKind : uint8_t {
4343

4444
enum class LifetimeDependenceKind : uint8_t { Inherit = 0, Scope };
4545

46-
class LifetimeDependenceSpecifier {
47-
public:
48-
enum class SpecifierKind { Named, Ordered, Self, Immortal };
46+
enum class LifetimeEntryKind { Named, Ordered, Self, Immortal };
4947

48+
class LifetimeEntry {
5049
private:
5150
SourceLoc loc;
52-
SpecifierKind specifierKind;
51+
LifetimeEntryKind lifetimeEntryKind;
5352
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind;
5453
union Value {
5554
struct {
@@ -65,68 +64,72 @@ class LifetimeDependenceSpecifier {
6564
Value() {}
6665
} value;
6766

68-
LifetimeDependenceSpecifier(
69-
SourceLoc loc, SpecifierKind specifierKind,
70-
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind, Value value)
71-
: loc(loc), specifierKind(specifierKind),
67+
LifetimeEntry(SourceLoc loc, LifetimeEntryKind lifetimeEntryKind,
68+
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind,
69+
Value value)
70+
: loc(loc), lifetimeEntryKind(lifetimeEntryKind),
7271
parsedLifetimeDependenceKind(parsedLifetimeDependenceKind),
7372
value(value) {}
7473

7574
public:
76-
static LifetimeDependenceSpecifier getNamedLifetimeDependenceSpecifier(
77-
SourceLoc loc, ParsedLifetimeDependenceKind kind, Identifier name) {
78-
return {loc, SpecifierKind::Named, kind, name};
75+
static LifetimeEntry
76+
getNamedLifetimeEntry(SourceLoc loc, Identifier name,
77+
ParsedLifetimeDependenceKind kind =
78+
ParsedLifetimeDependenceKind::Default) {
79+
return {loc, LifetimeEntryKind::Named, kind, name};
7980
}
8081

81-
static LifetimeDependenceSpecifier
82-
getImmortalLifetimeDependenceSpecifier(SourceLoc loc) {
83-
return {loc, SpecifierKind::Immortal, {}, {}};
82+
static LifetimeEntry getImmortalLifetimeEntry(SourceLoc loc) {
83+
return {loc, LifetimeEntryKind::Immortal, {}, {}};
8484
}
8585

86-
static LifetimeDependenceSpecifier getOrderedLifetimeDependenceSpecifier(
87-
SourceLoc loc, ParsedLifetimeDependenceKind kind, unsigned index) {
88-
return {loc, SpecifierKind::Ordered, kind, index};
86+
static LifetimeEntry
87+
getOrderedLifetimeEntry(SourceLoc loc, unsigned index,
88+
ParsedLifetimeDependenceKind kind =
89+
ParsedLifetimeDependenceKind::Default) {
90+
return {loc, LifetimeEntryKind::Ordered, kind, index};
8991
}
9092

91-
static LifetimeDependenceSpecifier
92-
getSelfLifetimeDependenceSpecifier(SourceLoc loc,
93-
ParsedLifetimeDependenceKind kind) {
94-
return {loc, SpecifierKind::Self, kind, {}};
93+
static LifetimeEntry
94+
getSelfLifetimeEntry(SourceLoc loc,
95+
ParsedLifetimeDependenceKind kind =
96+
ParsedLifetimeDependenceKind::Default) {
97+
return {loc, LifetimeEntryKind::Self, kind, {}};
9598
}
9699

97100
SourceLoc getLoc() const { return loc; }
98101

99-
SpecifierKind getSpecifierKind() const { return specifierKind; }
102+
LifetimeEntryKind getLifetimeEntryKind() const { return lifetimeEntryKind; }
100103

101104
ParsedLifetimeDependenceKind getParsedLifetimeDependenceKind() const {
102105
return parsedLifetimeDependenceKind;
103106
}
104107

105108
Identifier getName() const {
106-
assert(specifierKind == SpecifierKind::Named);
109+
assert(lifetimeEntryKind == LifetimeEntryKind::Named);
107110
return value.Named.name;
108111
}
109112

110113
unsigned getIndex() const {
111-
assert(specifierKind == SpecifierKind::Ordered);
114+
assert(lifetimeEntryKind == LifetimeEntryKind::Ordered);
112115
return value.Ordered.index;
113116
}
114117

115118
std::string getParamString() const {
116-
switch (specifierKind) {
117-
case SpecifierKind::Named:
119+
switch (lifetimeEntryKind) {
120+
case LifetimeEntryKind::Named:
118121
return value.Named.name.str().str();
119-
case SpecifierKind::Self:
122+
case LifetimeEntryKind::Self:
120123
return "self";
121-
case SpecifierKind::Ordered:
124+
case LifetimeEntryKind::Ordered:
122125
return std::to_string(value.Ordered.index);
123-
case SpecifierKind::Immortal:
126+
case LifetimeEntryKind::Immortal:
124127
return "immortal";
125128
}
126-
llvm_unreachable("Invalid LifetimeDependenceSpecifier::SpecifierKind");
129+
llvm_unreachable("Invalid LifetimeEntryKind");
127130
}
128131

129-
std::string getLifetimeDependenceSpecifierString() const {
132+
std::string getDependsOnString() const {
130133
switch (parsedLifetimeDependenceKind) {
131134
case ParsedLifetimeDependenceKind::Default:
132135
return "dependsOn(" + getParamString() + ")";
@@ -135,8 +138,7 @@ class LifetimeDependenceSpecifier {
135138
case ParsedLifetimeDependenceKind::Inherit:
136139
return "dependsOn(inherited " + getParamString() + ")";
137140
}
138-
llvm_unreachable(
139-
"Invalid LifetimeDependenceSpecifier::ParsedLifetimeDependenceKind");
141+
llvm_unreachable("Invalid LifetimeEntry::ParsedLifetimeDependenceKind");
140142
}
141143
};
142144

@@ -151,10 +153,14 @@ class LifetimeDependenceInfo {
151153
unsigned sourceIndex,
152154
LifetimeDependenceKind kind);
153155

154-
/// Builds LifetimeDependenceInfo on a result or parameter from a swift decl
156+
/// Builds LifetimeDependenceInfo from @lifetime attribute
157+
static std::optional<ArrayRef<LifetimeDependenceInfo>>
158+
fromLifetimeAttribute(AbstractFunctionDecl *afd);
159+
160+
/// Builds LifetimeDependenceInfo from dependsOn type modifier
155161
static std::optional<LifetimeDependenceInfo>
156-
fromTypeRepr(AbstractFunctionDecl *afd, LifetimeDependentTypeRepr *typeRepr,
157-
unsigned targetIndex);
162+
fromDependsOn(AbstractFunctionDecl *afd, TypeRepr *targetRepr,
163+
Type targetType, unsigned targetIndex);
158164

159165
/// Infer LifetimeDependenceInfo on result
160166
static std::optional<LifetimeDependenceInfo> infer(AbstractFunctionDecl *afd);
@@ -169,9 +175,9 @@ class LifetimeDependenceInfo {
169175

170176
/// Builds LifetimeDependenceInfo from SIL function type
171177
static std::optional<LifetimeDependenceInfo>
172-
fromTypeRepr(LifetimeDependentTypeRepr *lifetimeDependentRepr,
173-
unsigned targetIndex, ArrayRef<SILParameterInfo> params,
174-
DeclContext *dc);
178+
fromDependsOn(LifetimeDependentTypeRepr *lifetimeDependentRepr,
179+
unsigned targetIndex, ArrayRef<SILParameterInfo> params,
180+
DeclContext *dc);
175181

176182
public:
177183
LifetimeDependenceInfo(IndexSubset *inheritLifetimeParamIndices,

include/swift/AST/TypeRepr.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,31 +1533,28 @@ class SILBoxTypeRepr final : public TypeRepr,
15331533

15341534
class LifetimeDependentTypeRepr final
15351535
: public SpecifierTypeRepr,
1536-
private llvm::TrailingObjects<LifetimeDependentTypeRepr,
1537-
LifetimeDependenceSpecifier> {
1536+
private llvm::TrailingObjects<LifetimeDependentTypeRepr, LifetimeEntry> {
15381537
friend TrailingObjects;
15391538

15401539
size_t numTrailingObjects(OverloadToken<LifetimeDependentTypeRepr>) const {
15411540
return Bits.LifetimeDependentTypeRepr.NumDependencies;
15421541
}
15431542

15441543
public:
1545-
LifetimeDependentTypeRepr(TypeRepr *base,
1546-
ArrayRef<LifetimeDependenceSpecifier> specifiers)
1544+
LifetimeDependentTypeRepr(TypeRepr *base, ArrayRef<LifetimeEntry> specifiers)
15471545
: SpecifierTypeRepr(TypeReprKind::LifetimeDependent, base,
15481546
specifiers.front().getLoc()) {
15491547
assert(base);
15501548
Bits.LifetimeDependentTypeRepr.NumDependencies = specifiers.size();
15511549
std::uninitialized_copy(specifiers.begin(), specifiers.end(),
1552-
getTrailingObjects<LifetimeDependenceSpecifier>());
1550+
getTrailingObjects<LifetimeEntry>());
15531551
}
15541552

1555-
static LifetimeDependentTypeRepr *
1556-
create(ASTContext &C, TypeRepr *base,
1557-
ArrayRef<LifetimeDependenceSpecifier> specifiers);
1553+
static LifetimeDependentTypeRepr *create(ASTContext &C, TypeRepr *base,
1554+
ArrayRef<LifetimeEntry> specifiers);
15581555

1559-
ArrayRef<LifetimeDependenceSpecifier> getLifetimeDependencies() const {
1560-
return {getTrailingObjects<LifetimeDependenceSpecifier>(),
1556+
ArrayRef<LifetimeEntry> getLifetimeDependencies() const {
1557+
return {getTrailingObjects<LifetimeEntry>(),
15611558
Bits.LifetimeDependentTypeRepr.NumDependencies};
15621559
}
15631560

include/swift/Parse/Parser.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,10 @@ class Parser {
11781178
MacroSyntax syntax, SourceLoc AtLoc, SourceLoc Loc
11791179
);
11801180

1181+
/// Parse the @lifetime attribute.
1182+
ParserResult<LifetimeAttr> parseLifetimeAttribute(SourceLoc AtLoc,
1183+
SourceLoc Loc);
1184+
11811185
/// Parse a specific attribute.
11821186
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
11831187
SourceLoc AtEndLoc,
@@ -1266,8 +1270,8 @@ class Parser {
12661270
ConventionTypeAttr *&result,
12671271
bool justChecking);
12681272

1269-
ParserStatus parseLifetimeDependenceSpecifiers(
1270-
SmallVectorImpl<LifetimeDependenceSpecifier> &specifierList);
1273+
ParserStatus
1274+
parseLifetimeEntries(SmallVectorImpl<LifetimeEntry> &specifierList);
12711275

12721276
ParserResult<ImportDecl> parseDeclImport(ParseDeclOptions Flags,
12731277
DeclAttributes &Attributes);
@@ -1470,7 +1474,7 @@ class Parser {
14701474
SourceLoc ConstLoc;
14711475
SourceLoc SendingLoc;
14721476
SmallVector<TypeOrCustomAttr> Attributes;
1473-
SmallVector<LifetimeDependenceSpecifier> lifetimeDependenceSpecifiers;
1477+
SmallVector<LifetimeEntry> lifetimeEntries;
14741478

14751479
ParsedTypeAttributeList(ParseTypeReason reason) : ParseReason(reason) {}
14761480

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3579,7 +3579,7 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
35793579
for (auto &dep : T->getLifetimeDependencies()) {
35803580
printFieldRaw(
35813581
[&](raw_ostream &out) {
3582-
out << " " << dep.getLifetimeDependenceSpecifierString() << " ";
3582+
out << " " << dep.getDependsOnString() << " ";
35833583
},
35843584
"");
35853585
}

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4110,7 +4110,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
41104110
if (auto *typeRepr = dyn_cast_or_null<LifetimeDependentTypeRepr>(
41114111
decl->getResultTypeRepr())) {
41124112
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4113-
Printer << " " << dep.getLifetimeDependenceSpecifierString() << " ";
4113+
Printer << " " << dep.getDependsOnString() << " ";
41144114
}
41154115
}
41164116
}
@@ -4335,7 +4335,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
43354335
auto *typeRepr =
43364336
cast<LifetimeDependentTypeRepr>(decl->getResultTypeRepr());
43374337
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4338-
Printer << dep.getLifetimeDependenceSpecifierString() << " ";
4338+
Printer << dep.getDependsOnString() << " ";
43394339
}
43404340
// TODO: Handle failable initializers with lifetime dependent returns
43414341
Printer << "Self";

lib/AST/Attr.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,20 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
18131813
break;
18141814
}
18151815

1816+
case DeclAttrKind::Lifetime: {
1817+
auto *attr = cast<LifetimeAttr>(this);
1818+
bool firstElem = true;
1819+
Printer << "@lifetime(";
1820+
for (auto entry : attr->getLifetimeEntries()) {
1821+
if (!firstElem) {
1822+
Printer << ", ";
1823+
}
1824+
Printer << entry.getParamString();
1825+
}
1826+
Printer << ")";
1827+
break;
1828+
}
1829+
18161830
#define SIMPLE_DECL_ATTR(X, CLASS, ...) case DeclAttrKind::CLASS:
18171831
#include "swift/AST/DeclAttr.def"
18181832
llvm_unreachable("handled above");
@@ -2011,6 +2025,8 @@ StringRef DeclAttribute::getAttrName() const {
20112025
} else {
20122026
return "_allowFeatureSuppression";
20132027
}
2028+
case DeclAttrKind::Lifetime:
2029+
return "lifetime";
20142030
}
20152031
llvm_unreachable("bad DeclAttrKind");
20162032
}
@@ -3040,6 +3056,22 @@ AllowFeatureSuppressionAttr *AllowFeatureSuppressionAttr::create(
30403056
AllowFeatureSuppressionAttr(atLoc, range, implicit, inverted, features);
30413057
}
30423058

3059+
LifetimeAttr::LifetimeAttr(SourceLoc atLoc, SourceRange baseRange,
3060+
bool implicit, ArrayRef<LifetimeEntry> entries)
3061+
: DeclAttribute(DeclAttrKind::Lifetime, atLoc, baseRange, implicit),
3062+
NumEntries(entries.size()) {
3063+
std::copy(entries.begin(), entries.end(),
3064+
getTrailingObjects<LifetimeEntry>());
3065+
}
3066+
3067+
LifetimeAttr *LifetimeAttr::create(ASTContext &context, SourceLoc atLoc,
3068+
SourceRange baseRange, bool implicit,
3069+
ArrayRef<LifetimeEntry> entries) {
3070+
unsigned size = totalSizeToAlloc<LifetimeEntry>(entries.size());
3071+
void *mem = context.Allocate(size, alignof(LifetimeEntry));
3072+
return new (mem) LifetimeAttr(atLoc, baseRange, implicit, entries);
3073+
}
3074+
30433075
void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) {
30443076
if (attr)
30453077
attr->print(out);

0 commit comments

Comments
 (0)