Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -2178,8 +2178,8 @@ ERROR(expected_lparen_after_lifetime_dependence, PointsToFirstBadToken,

ERROR(expected_identifier_or_index_or_self_after_lifetime_dependence,
PointsToFirstBadToken,
"expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier",
())
"expected 'copy', 'borrow', or '&' followed by an identifier%select{|, index}0 or 'self' in lifetime dependence specifier",
(bool))

ERROR(expected_rparen_after_lifetime_dependence, PointsToFirstBadToken,
"expected ')' after parameter list in lifetime dependence specifier", ())
Expand Down
3 changes: 2 additions & 1 deletion include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,8 @@ class Parser {

/// Common utility to parse swift @lifetime decl attribute and SIL @lifetime
/// type modifier.
ParserResult<LifetimeEntry> parseLifetimeEntry(SourceLoc loc);
ParserResult<LifetimeEntry> parseLifetimeEntry(SourceLoc loc,
bool allowIndices);

/// Parse a specific attribute.
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
Expand Down
30 changes: 20 additions & 10 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2545,7 +2545,7 @@ static std::optional<Identifier> parseSingleAttrOptionImpl(
}

static std::optional<LifetimeDescriptor>
parseLifetimeDescriptor(Parser &P,
parseLifetimeDescriptor(Parser &P, bool allowIndices,
ParsedLifetimeDependenceKind lifetimeDependenceKind =
ParsedLifetimeDependenceKind::Default) {
auto token = P.Tok;
Expand Down Expand Up @@ -2577,6 +2577,13 @@ parseLifetimeDescriptor(Parser &P,
case tok::integer_literal: {
SourceLoc loc;
unsigned index;
if (!allowIndices) {
P.diagnose(
token,
diag::expected_identifier_or_index_or_self_after_lifetime_dependence,
/* allow indices */ false);
return std::nullopt;
}
if (P.parseUnsignedInteger(
index, loc, diag::expected_param_index_lifetime_dependence)) {
return std::nullopt;
Expand All @@ -2590,7 +2597,8 @@ parseLifetimeDescriptor(Parser &P,
default: {
P.diagnose(
token,
diag::expected_identifier_or_index_or_self_after_lifetime_dependence);
diag::expected_identifier_or_index_or_self_after_lifetime_dependence,
allowIndices);
return std::nullopt;
}
}
Expand All @@ -2601,7 +2609,7 @@ ParserResult<LifetimeAttr> Parser::parseLifetimeAttribute(StringRef attrName,
SourceLoc loc) {
ParserStatus status;

auto lifetimeEntry = parseLifetimeEntry(loc);
auto lifetimeEntry = parseLifetimeEntry(loc, /*allowIndices=*/false);
if (lifetimeEntry.isNull()) {
status.setIsParseError();
return status;
Expand Down Expand Up @@ -5077,7 +5085,7 @@ ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
}

case TypeAttrKind::Lifetime: {
const auto entryResult = parseLifetimeEntry(AtLoc);
const auto entryResult = parseLifetimeEntry(AtLoc, /*allowIndices=*/false);
if (entryResult.isNull()) {
return makeParserError();
}
Expand Down Expand Up @@ -5164,7 +5172,8 @@ ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
llvm_unreachable("bad attribute kind");
}

ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc,
bool allowIndices) {
ParserStatus status;

auto getLifetimeDependenceKind =
Expand Down Expand Up @@ -5198,7 +5207,7 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
std::optional<LifetimeDescriptor> targetDescriptor;
if (Tok.isAny(tok::identifier, tok::integer_literal, tok::kw_self) &&
peekToken().is(tok::colon)) {
targetDescriptor = parseLifetimeDescriptor(*this);
targetDescriptor = parseLifetimeDescriptor(*this, allowIndices);
if (!targetDescriptor) {
status.setIsParseError();
return status;
Expand All @@ -5223,8 +5232,8 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
consumeToken();
}

auto sourceDescriptor =
parseLifetimeDescriptor(*this, lifetimeDependenceKind);
auto sourceDescriptor = parseLifetimeDescriptor(*this, allowIndices,
lifetimeDependenceKind);
if (!sourceDescriptor) {
invalidSourceDescriptor = true;
listStatus.setIsParseError();
Expand All @@ -5241,7 +5250,8 @@ ParserResult<LifetimeEntry> Parser::parseLifetimeEntry(SourceLoc loc) {
if (!foundParamId) {
diagnose(
Tok,
diag::expected_identifier_or_index_or_self_after_lifetime_dependence);
diag::expected_identifier_or_index_or_self_after_lifetime_dependence,
/* allow indices */ isInSILMode());
status.setIsParseError();
return status;
}
Expand Down Expand Up @@ -5583,7 +5593,7 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
}
P.consumeToken(); // consume '@'
auto loc = P.consumeToken(); // consume 'lifetime'
auto result = P.parseLifetimeEntry(loc);
auto result = P.parseLifetimeEntry(loc, /*allowIndices=*/true);
if (result.isNull()) {
status |= result;
continue;
Expand Down
2 changes: 1 addition & 1 deletion test/Parse/lifetime_attr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func testMissingLParenError(_ ne: NE) -> NE {
ne
}

@_lifetime() // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier}}
@_lifetime() // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier or 'self' in lifetime dependence specifier}}
func testMissingDependence(_ ne: NE) -> NE {
ne
}
Expand Down
7 changes: 6 additions & 1 deletion test/Sema/lifetime_attr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ func invalidAttrOnNonExistingSelf(_ ne: NE) -> NE {
ne
}

@_lifetime(2) // expected-error{{invalid parameter index specified '2'}}
@_lifetime(copy 0) // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier or 'self' in lifetime dependence specifier}}
func invalidAttrOnExistingParamIndex(_ ne: NE) -> NE {
ne
}

@_lifetime(2) // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier or 'self' in lifetime dependence specifier}}
func invalidAttrOnNonExistingParamIndex(_ ne: NE) -> NE {
ne
}
Expand Down
2 changes: 1 addition & 1 deletion test/Sema/lifetime_depend_infer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {

// 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}}
@_lifetime(a: inout a) // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier or 'self' in lifetime dependence specifier}}
func f_inout_bad_keyword(a: inout MutableRawSpan) {}

// Don't allow a useless borrow dependency on an inout param--it is misleading.
Expand Down
6 changes: 4 additions & 2 deletions test/Sema/lifetime_dependence_functype.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func transfer(_ ne: NE) -> NE {
}

@_lifetime(copy ne)
func applyAnnotatedTransfer(ne: NE, @_lifetime(0) transfer: (NE) -> NE) -> NE { // expected-error{{'@_lifetime' attribute cannot be applied to this declaration}}
func applyAnnotatedTransfer(ne: NE, @_lifetime(copy ne) transfer: (_ ne: NE) -> NE) -> NE { // expected-error{{'@_lifetime' attribute cannot be applied to this declaration}}
transfer(ne)
}

Expand Down Expand Up @@ -61,7 +61,9 @@ typealias InvalidAttrOnNonExistingParamType = @_lifetime(copy nonexisting) (_ ne

typealias InvalidAttrOnNonExistingSelfType = @_lifetime(copy self) (_ ne: NE) -> NE // expected-error{{invalid lifetime dependence specifier on non-existent self}}

typealias InvalidAttrOnNonExistingParamIndexType = @_lifetime(2) (_ ne: NE) -> NE // expected-error{{invalid parameter index specified '2'}}
typealias InvalidAttrOnExistingParamIndexType = @_lifetime(0) (_ ne: NE) -> NE // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier or 'self' in lifetime dependence specifier}}

typealias InvalidAttrOnNonExistingParamIndexType = @_lifetime(2) (_ ne: NE) -> NE // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier or 'self' in lifetime dependence specifier}}

typealias InvalidDuplicateLifetimeDependenceType = @_lifetime(copy ne, borrow ne) (_ ne: borrowing NE) -> NE // expected-error{{duplicate lifetime dependence specifier}}

Expand Down