Skip to content

Commit 080b682

Browse files
committed
Fix a compiler crash with '@'_lifetime(inout x), add diagnostic
This is a common mistake made more common be suggestions of existing diagnostic that tell users not to use a 'copy' dependency. Report a diagnostic error rather than crashing the compiler. Fix the diagnostic output to make sense relative to the source location. Fixes rdar://154136015 ([nonescapable] compiler assertion with @_lifetime(x: inout x))
1 parent 05fa82b commit 080b682

File tree

4 files changed

+13
-2
lines changed

4 files changed

+13
-2
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2147,7 +2147,7 @@ ERROR(expected_lparen_after_lifetime_dependence, PointsToFirstBadToken,
21472147

21482148
ERROR(expected_identifier_or_index_or_self_after_lifetime_dependence,
21492149
PointsToFirstBadToken,
2150-
"expected identifier, index or self in lifetime dependence specifier",
2150+
"expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier",
21512151
())
21522152

21532153
ERROR(expected_rparen_after_lifetime_dependence, PointsToFirstBadToken,

lib/Parse/ParseDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5014,6 +5014,7 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
50145014
SmallVector<LifetimeDescriptor> sources;
50155015
SourceLoc rParenLoc;
50165016
bool foundParamId = false;
5017+
bool invalidSourceDescriptor = false;
50175018
status = parseList(
50185019
tok::r_paren, lParenLoc, rParenLoc, /*AllowSepAfterLast=*/false,
50195020
diag::expected_rparen_after_lifetime_dependence, [&]() -> ParserStatus {
@@ -5030,13 +5031,18 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
50305031
auto sourceDescriptor =
50315032
parseLifetimeDescriptor(*this, lifetimeDependenceKind);
50325033
if (!sourceDescriptor) {
5034+
invalidSourceDescriptor = true;
50335035
listStatus.setIsParseError();
50345036
return listStatus;
50355037
}
50365038
sources.push_back(*sourceDescriptor);
50375039
return listStatus;
50385040
});
50395041

5042+
if (invalidSourceDescriptor) {
5043+
status.setIsParseError();
5044+
return status;
5045+
}
50405046
if (!foundParamId) {
50415047
diagnose(
50425048
Tok,

test/Parse/lifetime_attr.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func testMissingLParenError(_ ne: NE) -> NE { // expected-error{{cannot infer th
2424
ne
2525
}
2626

27-
@_lifetime() // expected-error{{expected identifier, index or self in lifetime dependence specifier}}
27+
@_lifetime() // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier}}
2828
func testMissingDependence(_ ne: NE) -> NE { // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
2929
ne
3030
}

test/Sema/lifetime_depend_infer.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,3 +588,8 @@ struct NonEscapableMutableSelf: ~Escapable {
588588
//
589589
func f_inout_no_infer(a: inout MutNE, b: NE) {} // expected-error{{a function with a ~Escapable 'inout' parameter requires '@_lifetime(a: ...)'}}
590590
// expected-note @-1{{use '@_lifetime(a: copy a) to forward the inout dependency}}
591+
592+
// Invalid keyword for the dependence kind.
593+
//
594+
@_lifetime(a: inout a) // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier}}
595+
func f_inout_bad_keyword(a: inout MutableRawSpan) {}

0 commit comments

Comments
 (0)