Skip to content

Commit 1481557

Browse files
authored
Merge pull request #76624 from meg-gupta/lifetimedepscoped
Add support for borrow lifetime dependence
2 parents be5f47e + f8f043f commit 1481557

File tree

6 files changed

+55
-20
lines changed

6 files changed

+55
-20
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7983,9 +7983,15 @@ ERROR(lifetime_dependence_immortal_conflict_name, none,
79837983
ERROR(lifetime_dependence_function_type, none,
79847984
"lifetime dependencies on function types are not supported",
79857985
())
7986-
79877986
ERROR(lifetime_dependence_immortal_alone, none,
79887987
"cannot specify any other dependence source along with immortal", ())
7988+
ERROR(lifetime_dependence_invalid_inherit_escapable_type, none,
7989+
"invalid lifetime dependence on a source of Escapable type, use borrow "
7990+
"dependence instead",
7991+
())
7992+
ERROR(lifetime_dependence_cannot_use_parsed_borrow_consuming, none,
7993+
"invalid use of borrow dependence with consuming ownership",
7994+
())
79897995

79907996
//===----------------------------------------------------------------------===//
79917997
// MARK: Sending

lib/AST/LifetimeDependence.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -218,18 +218,26 @@ getLifetimeDependenceKind(LifetimeEntry specifier, AbstractFunctionDecl *afd,
218218
auto ownership = decl->getValueOwnership();
219219
auto type = decl->getTypeInContext();
220220

221-
// For @lifetime attribute, we determine lifetime dependence kind based on
222-
// type.
221+
// For @lifetime attribute, we check if we had a "borrow" modifier, if not
222+
// we infer inherit dependence.
223223
if (afd->getAttrs().hasAttribute<LifetimeAttr>()) {
224-
auto lifetimeKind = getLifetimeDependenceKindFromType(type);
225-
bool isCompatible = isLifetimeDependenceCompatibleWithOwnership(
226-
lifetimeKind, type, ownership, afd);
227-
if (!isCompatible) {
228-
assert(lifetimeKind == LifetimeDependenceKind::Scope);
229-
diags.diagnose(
230-
loc, diag::lifetime_dependence_cannot_use_inferred_scoped_consuming);
224+
auto parsedLifetimeKind = specifier.getParsedLifetimeDependenceKind();
225+
if (parsedLifetimeKind == ParsedLifetimeDependenceKind::Scope) {
226+
bool isCompatible = isLifetimeDependenceCompatibleWithOwnership(
227+
LifetimeDependenceKind::Scope, type, ownership, afd);
228+
if (!isCompatible) {
229+
diags.diagnose(
230+
loc, diag::lifetime_dependence_cannot_use_parsed_borrow_consuming);
231+
return std::nullopt;
232+
}
233+
return LifetimeDependenceKind::Scope;
234+
}
235+
if (type->isEscapable()) {
236+
diags.diagnose(loc,
237+
diag::lifetime_dependence_invalid_inherit_escapable_type);
231238
return std::nullopt;
232239
}
240+
return LifetimeDependenceKind::Inherit;
233241
}
234242

235243
// For dependsOn type modifier, we check if we had a "scoped" modifier, if not

lib/Parse/ParseDecl.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,6 +2823,15 @@ ParserResult<LifetimeAttr> Parser::parseLifetimeAttribute(SourceLoc atLoc,
28232823
diag::expected_rparen_after_lifetime_dependence, [&]() -> ParserStatus {
28242824
ParserStatus listStatus;
28252825
foundParamId = true;
2826+
2827+
auto lifetimeDependenceKind = ParsedLifetimeDependenceKind::Default;
2828+
if (Tok.isContextualKeyword("borrow") &&
2829+
peekToken().isAny(tok::identifier, tok::integer_literal,
2830+
tok::kw_self)) {
2831+
lifetimeDependenceKind = ParsedLifetimeDependenceKind::Scope;
2832+
consumeToken();
2833+
}
2834+
28262835
switch (Tok.getKind()) {
28272836
case tok::identifier: {
28282837
Identifier paramName;
@@ -2832,8 +2841,8 @@ ParserResult<LifetimeAttr> Parser::parseLifetimeAttribute(SourceLoc atLoc,
28322841
lifetimeEntries.push_back(
28332842
LifetimeEntry::getImmortalLifetimeEntry(paramLoc));
28342843
} else {
2835-
lifetimeEntries.push_back(
2836-
LifetimeEntry::getNamedLifetimeEntry(paramLoc, paramName));
2844+
lifetimeEntries.push_back(LifetimeEntry::getNamedLifetimeEntry(
2845+
paramLoc, paramName, lifetimeDependenceKind));
28372846
}
28382847
break;
28392848
}
@@ -2846,14 +2855,14 @@ ParserResult<LifetimeAttr> Parser::parseLifetimeAttribute(SourceLoc atLoc,
28462855
listStatus.setIsParseError();
28472856
return listStatus;
28482857
}
2849-
lifetimeEntries.push_back(
2850-
LifetimeEntry::getOrderedLifetimeEntry(paramLoc, paramNum));
2858+
lifetimeEntries.push_back(LifetimeEntry::getOrderedLifetimeEntry(
2859+
paramLoc, paramNum, lifetimeDependenceKind));
28512860
break;
28522861
}
28532862
case tok::kw_self: {
28542863
auto paramLoc = consumeToken(tok::kw_self);
2855-
lifetimeEntries.push_back(
2856-
LifetimeEntry::getSelfLifetimeEntry(paramLoc));
2864+
lifetimeEntries.push_back(LifetimeEntry::getSelfLifetimeEntry(
2865+
paramLoc, lifetimeDependenceKind));
28572866
break;
28582867
}
28592868
default:

test/Parse/lifetime_attr.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature NonescapableTypes
22
// REQUIRES: asserts
33

4-
struct NE : ~Escapable {
4+
struct E {}
55

6-
}
6+
struct NE : ~Escapable {}
77

88
@lifetime(ne)
99
func derive(_ ne: NE) -> NE {
1010
ne
1111
}
1212

13+
@lifetime(borrow ne1, ne2)
14+
func derive(_ ne1: NE, _ ne2: NE) -> NE {
15+
if (Int.random(in: 1..<100) < 50) {
16+
return ne1
17+
}
18+
return ne2
19+
}
20+
1321
@lifetime // expected-error{{expected '(' after lifetime dependence specifier}}
1422
func testMissingLParenError(_ ne: NE) -> NE {
1523
ne
@@ -20,3 +28,7 @@ func testMissingDependence(_ ne: NE) -> NE {
2028
ne
2129
}
2230

31+
@lifetime(borrow borrow)
32+
func testNameConflict(_ borrow: E) -> NE {
33+
NE()
34+
}

test/SIL/lifetime_dependence_span_lifetime_attr.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ extension Span {
160160

161161
extension ContiguousArray {
162162
public var view: Span<Element> {
163-
@lifetime(self)
163+
@lifetime(borrow self)
164164
borrowing _read {
165165
yield Span(
166166
baseAddress: _baseAddressIfContiguous!, count: count, dependsOn: self

test/Sema/lifetime_attr.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func invalidDuplicateLifetimeDependence1(_ ne: borrowing NE) -> NE {
2828

2929
class Klass {}
3030

31-
@lifetime(x) // expected-error{{invalid use of lifetime dependence on an Escapable parameter with consuming ownership}}
31+
@lifetime(borrow x) // expected-error{{invalid use of borrow dependence with consuming ownership}}
3232
func invalidDependence(_ x: consuming Klass) -> NE {
3333
NE()
3434
}

0 commit comments

Comments
 (0)