diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index a7062f6d8fe..b60a0333d08 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -2147,7 +2147,7 @@ ERROR(expected_lparen_after_lifetime_dependence, PointsToFirstBadToken, ERROR(expected_identifier_or_index_or_self_after_lifetime_dependence, PointsToFirstBadToken, - "expected identifier, index or self in lifetime dependence specifier", + "expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier", ()) ERROR(expected_rparen_after_lifetime_dependence, PointsToFirstBadToken, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 2ccab361f60..0d217b191d1 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -5014,6 +5014,7 @@ ParserResult Parser::parseLifetimeEntry(SourceLoc loc) { SmallVector sources; SourceLoc rParenLoc; bool foundParamId = false; + bool invalidSourceDescriptor = false; status = parseList( tok::r_paren, lParenLoc, rParenLoc, /*AllowSepAfterLast=*/false, diag::expected_rparen_after_lifetime_dependence, [&]() -> ParserStatus { @@ -5030,6 +5031,7 @@ ParserResult Parser::parseLifetimeEntry(SourceLoc loc) { auto sourceDescriptor = parseLifetimeDescriptor(*this, lifetimeDependenceKind); if (!sourceDescriptor) { + invalidSourceDescriptor = true; listStatus.setIsParseError(); return listStatus; } @@ -5037,6 +5039,10 @@ ParserResult Parser::parseLifetimeEntry(SourceLoc loc) { return listStatus; }); + if (invalidSourceDescriptor) { + status.setIsParseError(); + return status; + } if (!foundParamId) { diagnose( Tok, diff --git a/test/Parse/lifetime_attr.swift b/test/Parse/lifetime_attr.swift index 091ca62ad2e..d679b0c4b6a 100644 --- a/test/Parse/lifetime_attr.swift +++ b/test/Parse/lifetime_attr.swift @@ -24,7 +24,7 @@ func testMissingLParenError(_ ne: NE) -> NE { // expected-error{{cannot infer th ne } -@_lifetime() // expected-error{{expected identifier, index or self in lifetime dependence specifier}} +@_lifetime() // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier}} 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)'}} ne } diff --git a/test/Sema/lifetime_depend_infer.swift b/test/Sema/lifetime_depend_infer.swift index d4ae81ddcb7..d1afc5df1aa 100644 --- a/test/Sema/lifetime_depend_infer.swift +++ b/test/Sema/lifetime_depend_infer.swift @@ -588,3 +588,8 @@ struct NonEscapableMutableSelf: ~Escapable { // func f_inout_no_infer(a: inout MutNE, b: NE) {} // expected-error{{a function with a ~Escapable 'inout' parameter requires '@_lifetime(a: ...)'}} // expected-note @-1{{use '@_lifetime(a: copy a) to forward the inout dependency}} + +// Invalid keyword for the dependence kind. +// +@_lifetime(a: inout a) // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier}} +func f_inout_bad_keyword(a: inout MutableRawSpan) {}