Skip to content

Commit b5ca933

Browse files
committed
Update lifetime dependence syntax and inference as per changes in the pitch
Pitch - swiftlang/swift-evolution#2305 Changes highlights: dependsOn(paramName) and dependsOn(scoped argName) syntax dependsOn(paramName) -> copy lifetime dependence for all parameters/self except when we have Escapable parameters/self, we assign scope lifetime dependence. Allow lifetime dependence on parameters without ownership modifier. Always infer copy lifetime dependence except when we have Escapable parameters/self, we infer scope lifetime dependence. Allow lifetime dependence inference on parameters without ownership modifier.
1 parent e3a11ff commit b5ca933

35 files changed

+386
-352
lines changed

include/swift/AST/DiagnosticsSema.def

+15-12
Original file line numberDiff line numberDiff line change
@@ -7845,25 +7845,31 @@ ERROR(lifetime_dependence_invalid_param_name, none,
78457845
"invalid parameter name specified %0", (Identifier))
78467846
ERROR(lifetime_dependence_invalid_param_index, none,
78477847
"invalid parameter index specified %0", (unsigned))
7848-
ERROR(lifetime_dependence_invalid_self, none,
7849-
"invalid lifetime dependence specifier, self is valid in non-static "
7850-
"methods only", ())
7848+
ERROR(lifetime_dependence_invalid_self_in_static, none,
7849+
"invalid lifetime dependence specifier on non-existent self", ())
7850+
ERROR(lifetime_dependence_invalid_self_in_init, none,
7851+
"invalid lifetime dependence on self in an initializer", ())
78517852
ERROR(lifetime_dependence_duplicate_param_id, none,
78527853
"duplicate lifetime dependence specifier", ())
78537854
ERROR(lifetime_dependence_cannot_use_kind, none,
78547855
"invalid use of %0 lifetime dependence for %1 ownership",
78557856
(StringRef, StringRef))
7857+
ERROR(lifetime_dependence_cannot_use_parsed_scoped_consuming, none,
7858+
"invalid use of scoped lifetime dependence with consuming ownership",
7859+
())
7860+
ERROR(lifetime_dependence_cannot_use_inferred_scoped_consuming, none,
7861+
"invalid use of lifetime dependence on an Escapable parameter with "
7862+
"consuming ownership",
7863+
())
7864+
ERROR(lifetime_dependence_invalid_self_ownership, none,
7865+
"invalid scoped lifetime dependence on an Escapable self with consuming "
7866+
"ownership",
7867+
())
78567868
ERROR(lifetime_dependence_only_on_function_method_init_result, none,
78577869
"lifetime dependence specifiers may only be used on result of "
78587870
"functions, methods, initializers", ())
78597871
ERROR(lifetime_dependence_invalid_return_type, none,
78607872
"lifetime dependence can only be specified on ~Escapable results", ())
7861-
ERROR(lifetime_dependence_missing_ownership_modifier, none,
7862-
"lifetime dependence can only be specified on parameters with ownership "
7863-
"modifiers (borrowing, consuming, inout)", ())
7864-
ERROR(lifetime_dependence_cannot_infer_wo_ownership_modifier_on_method, none,
7865-
"cannot infer lifetime dependence, specify ownership modifier for the "
7866-
"method", ())
78677873
ERROR(lifetime_dependence_cannot_infer_ambiguous_candidate, none,
78687874
"cannot infer lifetime dependence, multiple ~Escapable or ~Copyable "
78697875
"parameters with ownership modifiers, specify explicit lifetime "
@@ -7874,9 +7880,6 @@ ERROR(lifetime_dependence_cannot_infer_no_candidates, none,
78747880
ERROR(lifetime_dependence_ctor_non_self_or_nil_return, none,
78757881
"expected nil or self as return values in an initializer with "
78767882
"lifetime dependent specifiers", ())
7877-
ERROR(lifetime_dependence_cannot_use_infer, none,
7878-
"invalid use of %0 lifetime dependence on Escapable type",
7879-
(StringRef))
78807883
ERROR(lifetime_dependence_on_bitwise_copyable, none,
78817884
"invalid lifetime dependence on bitwise copyable type", ())
78827885
ERROR(lifetime_dependence_cannot_infer_implicit_init, none,

include/swift/AST/LifetimeDependence.h

+27-27
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,22 @@ class AbstractFunctionDecl;
3232
class LifetimeDependentReturnTypeRepr;
3333
class SILParameterInfo;
3434

35-
enum class LifetimeDependenceKind : uint8_t {
36-
Copy = 0,
37-
Consume,
38-
Borrow,
39-
Mutate
35+
enum class ParsedLifetimeDependenceKind : uint8_t {
36+
Default = 0,
37+
Scope,
38+
Inherit // Only used with deserialized decls
4039
};
4140

41+
enum class LifetimeDependenceKind : uint8_t { Inherit = 0, Scope };
42+
4243
class LifetimeDependenceSpecifier {
4344
public:
4445
enum class SpecifierKind { Named, Ordered, Self };
4546

4647
private:
4748
SourceLoc loc;
4849
SpecifierKind specifierKind;
49-
LifetimeDependenceKind lifetimeDependenceKind;
50+
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind;
5051
union Value {
5152
struct {
5253
Identifier name;
@@ -61,35 +62,36 @@ class LifetimeDependenceSpecifier {
6162
Value() {}
6263
} value;
6364

64-
LifetimeDependenceSpecifier(SourceLoc loc, SpecifierKind specifierKind,
65-
LifetimeDependenceKind lifetimeDependenceKind,
66-
Value value)
65+
LifetimeDependenceSpecifier(
66+
SourceLoc loc, SpecifierKind specifierKind,
67+
ParsedLifetimeDependenceKind parsedLifetimeDependenceKind, Value value)
6768
: loc(loc), specifierKind(specifierKind),
68-
lifetimeDependenceKind(lifetimeDependenceKind), value(value) {}
69+
parsedLifetimeDependenceKind(parsedLifetimeDependenceKind),
70+
value(value) {}
6971

7072
public:
7173
static LifetimeDependenceSpecifier getNamedLifetimeDependenceSpecifier(
72-
SourceLoc loc, LifetimeDependenceKind kind, Identifier name) {
74+
SourceLoc loc, ParsedLifetimeDependenceKind kind, Identifier name) {
7375
return {loc, SpecifierKind::Named, kind, name};
7476
}
7577

7678
static LifetimeDependenceSpecifier getOrderedLifetimeDependenceSpecifier(
77-
SourceLoc loc, LifetimeDependenceKind kind, unsigned index) {
79+
SourceLoc loc, ParsedLifetimeDependenceKind kind, unsigned index) {
7880
return {loc, SpecifierKind::Ordered, kind, index};
7981
}
8082

8183
static LifetimeDependenceSpecifier
8284
getSelfLifetimeDependenceSpecifier(SourceLoc loc,
83-
LifetimeDependenceKind kind) {
85+
ParsedLifetimeDependenceKind kind) {
8486
return {loc, SpecifierKind::Self, kind, {}};
8587
}
8688

8789
SourceLoc getLoc() const { return loc; }
8890

8991
SpecifierKind getSpecifierKind() const { return specifierKind; }
9092

91-
LifetimeDependenceKind getLifetimeDependenceKind() const {
92-
return lifetimeDependenceKind;
93+
ParsedLifetimeDependenceKind getParsedLifetimeDependenceKind() const {
94+
return parsedLifetimeDependenceKind;
9395
}
9496

9597
Identifier getName() const {
@@ -114,19 +116,17 @@ class LifetimeDependenceSpecifier {
114116
llvm_unreachable("Invalid LifetimeDependenceSpecifier::SpecifierKind");
115117
}
116118

117-
StringRef getLifetimeDependenceKindString() const {
118-
switch (lifetimeDependenceKind) {
119-
case LifetimeDependenceKind::Borrow:
120-
return "_borrow";
121-
case LifetimeDependenceKind::Consume:
122-
return "_consume";
123-
case LifetimeDependenceKind::Copy:
124-
return "_copy";
125-
case LifetimeDependenceKind::Mutate:
126-
return "_mutate";
119+
std::string getLifetimeDependenceSpecifierString() const {
120+
switch (parsedLifetimeDependenceKind) {
121+
case ParsedLifetimeDependenceKind::Default:
122+
return "dependsOn(" + getParamString() + ")";
123+
case ParsedLifetimeDependenceKind::Scope:
124+
return "dependsOn(scoped " + getParamString() + ")";
125+
case ParsedLifetimeDependenceKind::Inherit:
126+
return "dependsOn(inherited " + getParamString() + ")";
127127
}
128128
llvm_unreachable(
129-
"Invalid LifetimeDependenceSpecifier::LifetimeDependenceKind");
129+
"Invalid LifetimeDependenceSpecifier::ParsedLifetimeDependenceKind");
130130
}
131131
};
132132

@@ -137,7 +137,7 @@ class LifetimeDependenceInfo {
137137

138138
static LifetimeDependenceInfo getForParamIndex(AbstractFunctionDecl *afd,
139139
unsigned index,
140-
ValueOwnership ownership);
140+
LifetimeDependenceKind kind);
141141

142142
public:
143143
LifetimeDependenceInfo()

include/swift/Parse/Parser.h

+15-12
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,7 @@ class Parser {
12121212
return true;
12131213
if (Context.LangOpts.hasFeature(Feature::NonescapableTypes) &&
12141214
(Tok.isContextualKeyword("_resultDependsOn") ||
1215-
Tok.isLifetimeDependenceToken(isInSILMode())))
1215+
isLifetimeDependenceToken()))
12161216
return true;
12171217
return false;
12181218
}
@@ -1224,23 +1224,26 @@ class Parser {
12241224
consumeToken();
12251225
}
12261226

1227+
bool isLifetimeDependenceToken() {
1228+
if (!isInSILMode()) {
1229+
return Tok.isContextualKeyword("dependsOn");
1230+
}
1231+
return Tok.isContextualKeyword("_inherit") ||
1232+
Tok.isContextualKeyword("_scope");
1233+
}
1234+
12271235
bool canHaveParameterSpecifierContextualKeyword() {
12281236
// The parameter specifiers like `isolated`, `consuming`, `borrowing` are
12291237
// also valid identifiers and could be the name of a type. Check whether
12301238
// the following token is something that can introduce a type. Thankfully
12311239
// none of these tokens overlap with the set of tokens that can follow an
12321240
// identifier in a type production.
1233-
return Tok.is(tok::identifier)
1234-
&& peekToken().isAny(tok::at_sign,
1235-
tok::kw_inout,
1236-
tok::l_paren,
1237-
tok::identifier,
1238-
tok::l_square,
1239-
tok::kw_Any,
1240-
tok::kw_Self,
1241-
tok::kw__,
1242-
tok::kw_var,
1243-
tok::kw_let);
1241+
return (Tok.is(tok::identifier) &&
1242+
peekToken().isAny(tok::at_sign, tok::kw_inout, tok::l_paren,
1243+
tok::identifier, tok::l_square, tok::kw_Any,
1244+
tok::kw_Self, tok::kw__, tok::kw_var,
1245+
tok::kw_let)) ||
1246+
isLifetimeDependenceToken();
12441247
}
12451248

12461249
struct ParsedTypeAttributeList {

include/swift/Parse/Token.h

-10
Original file line numberDiff line numberDiff line change
@@ -267,16 +267,6 @@ class Token {
267267
return MultilineString;
268268
}
269269

270-
bool isLifetimeDependenceToken(bool isInSILMode) const {
271-
return isContextualKeyword("_copy") || isContextualKeyword("_consume") ||
272-
isContextualKeyword("_borrow") || isContextualKeyword("_mutate") ||
273-
// SIL tests are currently written with _inherit/_scope
274-
// Once we have dependsOn()/dependsOn(borrowed:) other tokens go
275-
// away.
276-
(isInSILMode &&
277-
(isContextualKeyword("_inherit") || isContextualKeyword("_scope")));
278-
}
279-
280270
/// Count of extending escaping '#'.
281271
unsigned getCustomDelimiterLen() const {
282272
return CustomDelimiterLen;

lib/AST/ASTDumper.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -3535,8 +3535,7 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
35353535
for (auto &dep : T->getLifetimeDependencies()) {
35363536
printFieldRaw(
35373537
[&](raw_ostream &out) {
3538-
out << dep.getLifetimeDependenceKindString() << "(";
3539-
out << dep.getParamString() << ")";
3538+
out << " " << dep.getLifetimeDependenceSpecifierString() << " ";
35403539
},
35413540
"");
35423541
}

lib/AST/ASTMangler.cpp

+2-8
Original file line numberDiff line numberDiff line change
@@ -3263,20 +3263,14 @@ void ASTMangler::appendParameterTypeListElement(
32633263

32643264
void ASTMangler::appendLifetimeDependenceKind(LifetimeDependenceKind kind,
32653265
bool isSelfDependence) {
3266-
// If we converge on dependsOn(borrowed: paramName)/dependsOn(paramName)
3267-
// syntax, this can be a single case value check.
3268-
if (kind == LifetimeDependenceKind::Borrow ||
3269-
kind == LifetimeDependenceKind::Mutate) {
3266+
if (kind == LifetimeDependenceKind::Scope) {
32703267
if (isSelfDependence) {
32713268
appendOperator("YLs");
32723269
} else {
32733270
appendOperator("Yls");
32743271
}
32753272
} else {
3276-
// If we converge on dependsOn(borrowed: paramName)/dependsOn(paramName)
3277-
// syntax, this can be a single case value check.
3278-
assert(kind == LifetimeDependenceKind::Copy ||
3279-
kind == LifetimeDependenceKind::Consume);
3273+
assert(kind == LifetimeDependenceKind::Inherit);
32803274
if (isSelfDependence) {
32813275
appendOperator("YLi");
32823276
} else {

lib/AST/ASTPrinter.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -4137,8 +4137,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
41374137
if (auto *typeRepr = dyn_cast_or_null<LifetimeDependentReturnTypeRepr>(
41384138
decl->getResultTypeRepr())) {
41394139
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4140-
Printer << " " << dep.getLifetimeDependenceKindString() << "(";
4141-
Printer << dep.getParamString() << ") ";
4140+
Printer << " " << dep.getLifetimeDependenceSpecifierString() << " ";
41424141
}
41434142
}
41444143
}
@@ -4378,8 +4377,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
43784377
auto *typeRepr =
43794378
cast<LifetimeDependentReturnTypeRepr>(decl->getResultTypeRepr());
43804379
for (auto &dep : typeRepr->getLifetimeDependencies()) {
4381-
Printer << dep.getLifetimeDependenceKindString() << "(";
4382-
Printer << dep.getParamString() << ") ";
4380+
Printer << dep.getLifetimeDependenceSpecifierString() << " ";
43834381
}
43844382
// TODO: Handle failable initializers with lifetime dependent returns
43854383
Printer << "Self";

lib/AST/TypeRepr.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -692,9 +692,9 @@ SourceLoc LifetimeDependentReturnTypeRepr::getLocImpl() const {
692692

693693
void LifetimeDependentReturnTypeRepr::printImpl(
694694
ASTPrinter &Printer, const PrintOptions &Opts) const {
695+
Printer << " ";
695696
for (auto &dep : getLifetimeDependencies()) {
696-
Printer << dep.getLifetimeDependenceKindString() << "(";
697-
Printer << dep.getParamString() << ")";
697+
Printer << dep.getLifetimeDependenceSpecifierString() << " ";
698698
}
699699

700700
printTypeRepr(getBase(), Printer, Opts);

lib/Parse/ParseDecl.cpp

+31-22
Original file line numberDiff line numberDiff line change
@@ -5057,34 +5057,33 @@ ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
50575057
llvm_unreachable("bad attribute kind");
50585058
}
50595059

5060-
static std::optional<LifetimeDependenceKind>
5061-
getLifetimeDependenceKind(const Token &T) {
5062-
if (T.isContextualKeyword("_copy") || T.isContextualKeyword("_inherit")) {
5063-
return LifetimeDependenceKind::Copy;
5060+
static ParsedLifetimeDependenceKind getSILLifetimeDependenceKind(const Token &T) {
5061+
if (T.isContextualKeyword("_inherit")) {
5062+
return ParsedLifetimeDependenceKind::Inherit;
50645063
}
5065-
if (T.isContextualKeyword("_consume")) {
5066-
return LifetimeDependenceKind::Consume;
5067-
}
5068-
if (T.isContextualKeyword("_borrow") || T.isContextualKeyword("_scope")) {
5069-
return LifetimeDependenceKind::Borrow;
5070-
}
5071-
if (T.isContextualKeyword("_mutate")) {
5072-
return LifetimeDependenceKind::Mutate;
5073-
}
5074-
return std::nullopt;
5064+
assert(T.isContextualKeyword("_scope"));
5065+
return ParsedLifetimeDependenceKind::Scope;
50755066
}
50765067

50775068
ParserStatus Parser::parseLifetimeDependenceSpecifiers(
50785069
SmallVectorImpl<LifetimeDependenceSpecifier> &specifierList) {
50795070
ParserStatus status;
50805071
// TODO: Add fixits for diagnostics in this function.
50815072
do {
5082-
auto lifetimeDependenceKind = getLifetimeDependenceKind(Tok);
5083-
if (!lifetimeDependenceKind.has_value()) {
5073+
if (!isLifetimeDependenceToken()) {
50845074
break;
50855075
}
5086-
// consume the lifetime dependence kind
5087-
consumeToken();
5076+
5077+
auto lifetimeDependenceKind = ParsedLifetimeDependenceKind::Default;
5078+
5079+
if (!isInSILMode()) {
5080+
// consume dependsOn
5081+
consumeToken();
5082+
} else {
5083+
lifetimeDependenceKind = getSILLifetimeDependenceKind(Tok);
5084+
// consume _inherit or _scope
5085+
consumeToken();
5086+
}
50885087

50895088
if (!Tok.isFollowingLParen()) {
50905089
diagnose(Tok, diag::expected_lparen_after_lifetime_dependence);
@@ -5093,6 +5092,16 @@ ParserStatus Parser::parseLifetimeDependenceSpecifiers(
50935092
}
50945093
// consume the l_paren
50955094
auto lParenLoc = consumeToken();
5095+
5096+
if (!isInSILMode()) {
5097+
// look for optional "scoped"
5098+
if (Tok.isContextualKeyword("scoped")) {
5099+
lifetimeDependenceKind = ParsedLifetimeDependenceKind::Scope;
5100+
// consume scoped
5101+
consumeToken();
5102+
}
5103+
}
5104+
50965105
SourceLoc rParenLoc;
50975106
bool foundParamId = false;
50985107
status = parseList(
@@ -5108,7 +5117,7 @@ ParserStatus Parser::parseLifetimeDependenceSpecifiers(
51085117
specifierList.push_back(
51095118
LifetimeDependenceSpecifier::
51105119
getNamedLifetimeDependenceSpecifier(
5111-
paramLoc, *lifetimeDependenceKind, paramName));
5120+
paramLoc, lifetimeDependenceKind, paramName));
51125121
break;
51135122
}
51145123
case tok::integer_literal: {
@@ -5123,14 +5132,14 @@ ParserStatus Parser::parseLifetimeDependenceSpecifiers(
51235132
specifierList.push_back(
51245133
LifetimeDependenceSpecifier::
51255134
getOrderedLifetimeDependenceSpecifier(
5126-
paramLoc, *lifetimeDependenceKind, paramNum));
5135+
paramLoc, lifetimeDependenceKind, paramNum));
51275136
break;
51285137
}
51295138
case tok::kw_self: {
51305139
auto paramLoc = consumeToken(tok::kw_self);
51315140
specifierList.push_back(
51325141
LifetimeDependenceSpecifier::getSelfLifetimeDependenceSpecifier(
5133-
paramLoc, *lifetimeDependenceKind));
5142+
paramLoc, lifetimeDependenceKind));
51345143
break;
51355144
}
51365145
default:
@@ -5465,7 +5474,7 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
54655474
continue;
54665475
}
54675476

5468-
if (Tok.isLifetimeDependenceToken(P.isInSILMode())) {
5477+
if (P.isLifetimeDependenceToken()) {
54695478
if (!P.Context.LangOpts.hasFeature(Feature::NonescapableTypes)) {
54705479
P.diagnose(Tok, diag::requires_experimental_feature,
54715480
"lifetime dependence specifier", false,

0 commit comments

Comments
 (0)