Ungate accepted parts of SE439

This commit is contained in:
Mateus Rodrigues
2024-07-22 09:55:16 -03:00
parent e1f537107f
commit e0d416cdab
6 changed files with 525 additions and 522 deletions

View File

@@ -398,7 +398,7 @@ EXPERIMENTAL_FEATURE(ReinitializeConsumeInMultiBlockDefer, false)
EXPERIMENTAL_FEATURE(SE427NoInferenceOnExtension, false) EXPERIMENTAL_FEATURE(SE427NoInferenceOnExtension, false)
// Enable trailing comma for comma-separated lists. // Enable trailing comma for comma-separated lists.
EXPERIMENTAL_FEATURE(TrailingComma, true) EXPERIMENTAL_FEATURE(TrailingComma, false)
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE #undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
#undef EXPERIMENTAL_FEATURE #undef EXPERIMENTAL_FEATURE

View File

@@ -2549,10 +2549,9 @@ Parser::parseMacroRoleAttribute(
bool sawNames = false; bool sawNames = false;
SmallVector<MacroIntroducedDeclName, 2> names; SmallVector<MacroIntroducedDeclName, 2> names;
SmallVector<TypeExpr *, 2> conformances; SmallVector<TypeExpr *, 2> conformances;
auto argumentsStatus = parseList(tok::r_paren, lParenLoc, rParenLoc, auto argumentsStatus = parseList(
/*AllowSepAfterLast=*/Context.LangOpts.hasFeature(Feature::TrailingComma), tok::r_paren, lParenLoc, rParenLoc,
diag::expected_rparen_expr_list, /*AllowSepAfterLast=*/true, diag::expected_rparen_expr_list, [&] {
[&] {
ParserStatus status; ParserStatus status;
if (consumeIf(tok::code_complete)) { if (consumeIf(tok::code_complete)) {
@@ -2561,12 +2560,14 @@ Parser::parseMacroRoleAttribute(
sawRole = true; sawRole = true;
if (this->CodeCompletionCallbacks) { if (this->CodeCompletionCallbacks) {
this->CodeCompletionCallbacks->completeDeclAttrParam( this->CodeCompletionCallbacks->completeDeclAttrParam(
getCustomSyntaxAttributeKind(isAttached), 0, /*HasLabel=*/false); getCustomSyntaxAttributeKind(isAttached), 0,
/*HasLabel=*/false);
} }
} else if (!sawNames) { } else if (!sawNames) {
if (this->CodeCompletionCallbacks) { if (this->CodeCompletionCallbacks) {
this->CodeCompletionCallbacks->completeDeclAttrParam( this->CodeCompletionCallbacks->completeDeclAttrParam(
getCustomSyntaxAttributeKind(isAttached), 1, /*HasLabel=*/false); getCustomSyntaxAttributeKind(isAttached), 1,
/*HasLabel=*/false);
} }
} }
} }
@@ -2579,21 +2580,20 @@ Parser::parseMacroRoleAttribute(
// If there is a field name, it better be 'names'. // If there is a field name, it better be 'names'.
if (!(fieldName.empty() || fieldName.is("names") || if (!(fieldName.empty() || fieldName.is("names") ||
fieldName.is("conformances"))) { fieldName.is("conformances"))) {
diagnose( diagnose(fieldNameLoc, diag::macro_attribute_unknown_label,
fieldNameLoc, diag::macro_attribute_unknown_label, isAttached, isAttached, fieldName);
fieldName);
status.setIsParseError(); status.setIsParseError();
return status; return status;
} }
// If there is no field name and we haven't seen either names or the role, // If there is no field name and we haven't seen either names or the
// this is the role. // role, this is the role.
if (fieldName.empty() && !sawConformances && !sawNames && !sawRole) { if (fieldName.empty() && !sawConformances && !sawNames && !sawRole) {
// Whether we saw anything we tried to treat as a role. // Whether we saw anything we tried to treat as a role.
sawRole = true; sawRole = true;
auto diagKind = isAttached auto diagKind =
? diag::macro_role_attr_expected_attached_kind isAttached ? diag::macro_role_attr_expected_attached_kind
: diag::macro_role_attr_expected_freestanding_kind; : diag::macro_role_attr_expected_freestanding_kind;
Identifier roleName; Identifier roleName;
SourceLoc roleNameLoc; SourceLoc roleNameLoc;
@@ -2610,7 +2610,8 @@ Parser::parseMacroRoleAttribute(
role = getMacroRole(roleName.str()); role = getMacroRole(roleName.str());
if (!role) { if (!role) {
diagnose(roleNameLoc, diag::macro_role_attr_expected_kind, isAttached); diagnose(roleNameLoc, diag::macro_role_attr_expected_kind,
isAttached);
status.setIsParseError(); status.setIsParseError();
return status; return status;
} }
@@ -2622,9 +2623,8 @@ Parser::parseMacroRoleAttribute(
// Check that the role makes sense. // Check that the role makes sense.
if (isAttached == !isAttachedMacro(*role)) { if (isAttached == !isAttachedMacro(*role)) {
diagnose( diagnose(roleNameLoc, diag::macro_role_syntax_mismatch, isAttached,
roleNameLoc, diag::macro_role_syntax_mismatch, isAttached, roleName roleName);
);
status.setIsParseError(); status.setIsParseError();
return status; return status;
@@ -2637,8 +2637,7 @@ Parser::parseMacroRoleAttribute(
(fieldName.empty() && sawConformances && !sawNames)) { (fieldName.empty() && sawConformances && !sawNames)) {
if (fieldName.is("conformances") && sawConformances) { if (fieldName.is("conformances") && sawConformances) {
diagnose(fieldNameLoc.isValid() ? fieldNameLoc : Tok.getLoc(), diagnose(fieldNameLoc.isValid() ? fieldNameLoc : Tok.getLoc(),
diag::macro_attribute_duplicate_label, diag::macro_attribute_duplicate_label, isAttached,
isAttached,
"conformances"); "conformances");
} }
@@ -2652,14 +2651,13 @@ Parser::parseMacroRoleAttribute(
return status; return status;
} }
// If the field name is empty and we haved seen "names", or the field name // If the field name is empty and we haved seen "names", or the field
// is "names" but we've already seen the argument label, complain. // name is "names" but we've already seen the argument label, complain.
if (fieldName.empty() != sawNames) { if (fieldName.empty() != sawNames) {
diagnose(fieldNameLoc.isValid() ? fieldNameLoc : Tok.getLoc(), diagnose(fieldNameLoc.isValid() ? fieldNameLoc : Tok.getLoc(),
sawNames ? diag::macro_attribute_duplicate_label sawNames ? diag::macro_attribute_duplicate_label
: diag::macro_attribute_missing_label, : diag::macro_attribute_missing_label,
isAttached, isAttached, "names");
"names");
} }
sawNames = true; sawNames = true;
@@ -2679,12 +2677,11 @@ Parser::parseMacroRoleAttribute(
return status; return status;
} }
auto introducedKind = getMacroIntroducedDeclNameKind(introducedNameKind); auto introducedKind =
getMacroIntroducedDeclNameKind(introducedNameKind);
if (!introducedKind) { if (!introducedKind) {
diagnose( diagnose(introducedNameKindLoc,
introducedNameKindLoc, diag::macro_attribute_unknown_name_kind, diag::macro_attribute_unknown_name_kind, introducedNameKind);
introducedNameKind
);
status.setIsParseError(); status.setIsParseError();
return status; return status;
} }
@@ -2693,8 +2690,8 @@ Parser::parseMacroRoleAttribute(
if (!macroIntroducedNameRequiresArgument(*introducedKind)) { if (!macroIntroducedNameRequiresArgument(*introducedKind)) {
// If there is an argument, complain about it. // If there is an argument, complain about it.
if (Tok.is(tok::l_paren)) { if (Tok.is(tok::l_paren)) {
diagnose( diagnose(Tok,
Tok, diag::macro_attribute_introduced_name_requires_no_argument, diag::macro_attribute_introduced_name_requires_no_argument,
introducedNameKind); introducedNameKind);
skipSingle(); skipSingle();
} }
@@ -2704,8 +2701,7 @@ Parser::parseMacroRoleAttribute(
} }
if (!Tok.is(tok::l_paren)) { if (!Tok.is(tok::l_paren)) {
diagnose( diagnose(Tok, diag::macro_attribute_introduced_name_requires_argument,
Tok, diag::macro_attribute_introduced_name_requires_argument,
introducedNameKind); introducedNameKind);
status.setIsParseError(); status.setIsParseError();
return status; return status;
@@ -2716,8 +2712,7 @@ Parser::parseMacroRoleAttribute(
DeclNameLoc nameLoc; DeclNameLoc nameLoc;
DeclNameRef name = parseDeclNameRef( DeclNameRef name = parseDeclNameRef(
nameLoc, diag::macro_attribute_unknown_argument_form, nameLoc, diag::macro_attribute_unknown_argument_form,
(DeclNameFlag::AllowOperators | (DeclNameFlag::AllowOperators | DeclNameFlag::AllowKeywords |
DeclNameFlag::AllowKeywords |
DeclNameFlag::AllowKeywordsUsingSpecialNames | DeclNameFlag::AllowKeywordsUsingSpecialNames |
DeclNameFlag::AllowCompoundNames | DeclNameFlag::AllowCompoundNames |
DeclNameFlag::AllowZeroArgCompoundNames)); DeclNameFlag::AllowZeroArgCompoundNames));
@@ -6804,10 +6799,13 @@ ParserStatus Parser::parseInheritance(
ParserStatus Status; ParserStatus Status;
SourceLoc prevComma; SourceLoc prevComma;
bool HasNextType; bool HasNextType;
bool IsEndOfList;
do { do {
SWIFT_DEFER { SWIFT_DEFER {
// Check for a ',', which indicates that there are more protocols coming. // Check for a ',', which indicates that there are more protocols coming.
HasNextType = consumeIf(tok::comma, prevComma); HasNextType = consumeIf(tok::comma, prevComma);
IsEndOfList = (Context.LangOpts.hasFeature(Feature::TrailingComma) &&
(Tok.is(tok::l_brace) || Tok.is(tok::kw_where)));
}; };
// Parse the 'class' keyword for a class requirement. // Parse the 'class' keyword for a class requirement.
if (Tok.is(tok::kw_class)) { if (Tok.is(tok::kw_class)) {
@@ -6859,7 +6857,7 @@ ParserStatus Parser::parseInheritance(
// Record the type if its a single type. // Record the type if its a single type.
if (ParsedTypeResult.isNonNull()) if (ParsedTypeResult.isNonNull())
Inherited.push_back(InheritedEntry(ParsedTypeResult.get())); Inherited.push_back(InheritedEntry(ParsedTypeResult.get()));
} while (HasNextType); } while (HasNextType && !IsEndOfList);
return Status; return Status;
} }

View File

@@ -1926,8 +1926,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
default: default:
UnknownCharacter: UnknownCharacter:
checkForInputIncomplete(); checkForInputIncomplete();
if (Context.LangOpts.hasFeature(Feature::TrailingComma) && if (Tok.is(tok::eof) && Tok.getText() == ")") {
Tok.is(tok::eof) && Tok.getText() == ")") {
return nullptr; return nullptr;
} }
// FIXME: offer a fixit: 'Self' -> 'self' // FIXME: offer a fixit: 'Self' -> 'self'
@@ -2774,8 +2773,7 @@ ParserStatus Parser::parseClosureSignatureIfPresent(
VD->setIsSelfParamCapture(); VD->setIsSelfParamCapture();
captureList.push_back(CLE); captureList.push_back(CLE);
} while (HasNext && !(Context.LangOpts.hasFeature(Feature::TrailingComma) && } while (HasNext && !Tok.is(tok::r_square));
Tok.is(tok::r_square)));
// The capture list needs to be closed off with a ']'. // The capture list needs to be closed off with a ']'.
SourceLoc rBracketLoc = Tok.getLoc(); SourceLoc rBracketLoc = Tok.getLoc();
@@ -3295,11 +3293,12 @@ ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
StructureMarkerRAII ParsingExprList(*this, Tok); StructureMarkerRAII ParsingExprList(*this, Tok);
leftLoc = consumeToken(leftTok); leftLoc = consumeToken(leftTok);
return parseList(rightTok, leftLoc, rightLoc, /*AllowSepAfterLast=*/Context.LangOpts.hasFeature(Feature::TrailingComma), return parseList(rightTok, leftLoc, rightLoc, /*AllowSepAfterLast=*/true,
rightTok == tok::r_paren ? diag::expected_rparen_expr_list rightTok == tok::r_paren ? diag::expected_rparen_expr_list
: diag::expected_rsquare_expr_list, : diag::expected_rsquare_expr_list,
[&] () -> ParserStatus { [&]() -> ParserStatus {
return parseExprListElement(rightTok, isArgumentList, leftLoc, elts); return parseExprListElement(rightTok, isArgumentList,
leftLoc, elts);
}); });
} }

View File

@@ -134,8 +134,7 @@ Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
// Parse the comma, if the list continues. // Parse the comma, if the list continues.
HasNextParam = consumeIf(tok::comma); HasNextParam = consumeIf(tok::comma);
IsEndOfList = (Context.LangOpts.hasFeature(Feature::TrailingComma) && IsEndOfList = startsWithGreater(Tok);
startsWithGreater(Tok));
} while (HasNextParam && !IsEndOfList); } while (HasNextParam && !IsEndOfList);
return Result; return Result;

View File

@@ -213,9 +213,9 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
// Parse the parameter list. // Parse the parameter list.
bool isClosure = paramContext == ParameterContextKind::Closure; bool isClosure = paramContext == ParameterContextKind::Closure;
return parseList(tok::r_paren, leftParenLoc, rightParenLoc, return parseList(
/*AllowSepAfterLast=*/Context.LangOpts.hasFeature(Feature::TrailingComma), tok::r_paren, leftParenLoc, rightParenLoc,
diag::expected_rparen_parameter, /*AllowSepAfterLast=*/true, diag::expected_rparen_parameter,
[&]() -> ParserStatus { [&]() -> ParserStatus {
ParsedParameter param; ParsedParameter param;
ParserStatus status; ParserStatus status;
@@ -228,7 +228,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
auto AttrStatus = parseDeclAttributeList(param.Attrs); auto AttrStatus = parseDeclAttributeList(param.Attrs);
if (AttrStatus.hasCodeCompletion()) { if (AttrStatus.hasCodeCompletion()) {
if (this->CodeCompletionCallbacks) if (this->CodeCompletionCallbacks)
this->CodeCompletionCallbacks->setAttrTargetDeclKind(DeclKind::Param); this->CodeCompletionCallbacks->setAttrTargetDeclKind(
DeclKind::Param);
status.setHasCodeCompletionAndIsError(); status.setHasCodeCompletionAndIsError();
} }
} }
@@ -237,23 +238,24 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
// ('inout' | '__shared' | '__owned' | isolated)? // ('inout' | '__shared' | '__owned' | isolated)?
bool hasSpecifier = false; bool hasSpecifier = false;
while (isParameterSpecifier()) { while (isParameterSpecifier()) {
// Placing 'inout' in front of the parameter specifiers was allowed in // Placing 'inout' in front of the parameter specifiers was allowed
// the Swift 2-ish era and got moved to the return type in Swift 3 // in the Swift 2-ish era and got moved to the return type in Swift
// (SE-0031). // 3 (SE-0031). But new parameters that don't store there location
// But new parameters that don't store there location in // in `SpecifierLoc` were added afterwards and didn't get diagnosed.
// `SpecifierLoc` were added afterwards and didn't get diagnosed. // We thus need to parameter specifiers that don't store their
// We thus need to parameter specifiers that don't store their location // location in `SpecifierLoc` here. `SpecifierLoc` parameters get
// in `SpecifierLoc` here. `SpecifierLoc` parameters get diagnosed in // diagnosed in `validateParameterWithOwnership`
// `validateParameterWithOwnership`
// is this token the identifier of an argument label? `inout` is a // is this token the identifier of an argument label? `inout` is a
// reserved keyword but the other modifiers are not. // reserved keyword but the other modifiers are not.
if (!Tok.is(tok::kw_inout)) { if (!Tok.is(tok::kw_inout)) {
bool partOfArgumentLabel = lookahead<bool>(1, [&](CancellableBacktrackingScope &) { bool partOfArgumentLabel =
lookahead<bool>(1, [&](CancellableBacktrackingScope &) {
if (Tok.is(tok::colon)) if (Tok.is(tok::colon))
return true; // isolated : return true; // isolated :
return Tok.canBeArgumentLabel() && peekToken().is(tok::colon); return Tok.canBeArgumentLabel() &&
peekToken().is(tok::colon);
}); });
if (partOfArgumentLabel) if (partOfArgumentLabel)
@@ -261,7 +263,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
} }
if (Tok.isContextualKeyword("isolated")) { if (Tok.isContextualKeyword("isolated")) {
diagnose(Tok, diag::parameter_specifier_as_attr_disallowed, Tok.getText()) diagnose(Tok, diag::parameter_specifier_as_attr_disallowed,
Tok.getText())
.warnUntilSwiftVersion(6); .warnUntilSwiftVersion(6);
// did we already find an 'isolated' type modifier? // did we already find an 'isolated' type modifier?
if (param.IsolatedLoc.isValid()) { if (param.IsolatedLoc.isValid()) {
@@ -277,7 +280,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
} }
if (Tok.isContextualKeyword("_const")) { if (Tok.isContextualKeyword("_const")) {
diagnose(Tok, diag::parameter_specifier_as_attr_disallowed, Tok.getText()) diagnose(Tok, diag::parameter_specifier_as_attr_disallowed,
Tok.getText())
.warnUntilSwiftVersion(6); .warnUntilSwiftVersion(6);
param.CompileConstLoc = consumeToken(); param.CompileConstLoc = consumeToken();
continue; continue;
@@ -285,7 +289,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
if (Context.LangOpts.hasFeature(Feature::SendingArgsAndResults) && if (Context.LangOpts.hasFeature(Feature::SendingArgsAndResults) &&
Tok.isContextualKeyword("transferring")) { Tok.isContextualKeyword("transferring")) {
diagnose(Tok, diag::parameter_specifier_as_attr_disallowed, Tok.getText()) diagnose(Tok, diag::parameter_specifier_as_attr_disallowed,
Tok.getText())
.warnUntilSwiftVersion(6); .warnUntilSwiftVersion(6);
if (param.TransferringLoc.isValid()) { if (param.TransferringLoc.isValid()) {
diagnose(Tok, diag::parameter_specifier_repeated) diagnose(Tok, diag::parameter_specifier_repeated)
@@ -379,8 +384,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
auto parseParamType = [&]() -> ParserResult<TypeRepr> { auto parseParamType = [&]() -> ParserResult<TypeRepr> {
// Currently none of the parameter type completions are relevant for // Currently none of the parameter type completions are relevant for
// enum cases, so don't include them. We'll complete for a regular type // enum cases, so don't include them. We'll complete for a regular
// beginning instead. // type beginning instead.
if (paramContext != ParameterContextKind::EnumElement) { if (paramContext != ParameterContextKind::EnumElement) {
if (auto CCLoc = tryCompleteFunctionParamTypeBeginning()) { if (auto CCLoc = tryCompleteFunctionParamTypeBeginning()) {
auto *ET = ErrorTypeRepr::create(Context, CCLoc); auto *ET = ErrorTypeRepr::create(Context, CCLoc);
@@ -392,20 +397,21 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
if (startsParameterName(isClosure)) { if (startsParameterName(isClosure)) {
// identifier-or-none for the first name // identifier-or-none for the first name
param.FirstNameLoc = consumeArgumentLabel(param.FirstName, param.FirstNameLoc =
consumeArgumentLabel(param.FirstName,
/*diagnoseDollarPrefix=*/!isClosure); /*diagnoseDollarPrefix=*/!isClosure);
// identifier-or-none? for the second name // identifier-or-none? for the second name
if (Tok.canBeArgumentLabel()) if (Tok.canBeArgumentLabel())
param.SecondNameLoc = consumeArgumentLabel(param.SecondName, param.SecondNameLoc =
consumeArgumentLabel(param.SecondName,
/*diagnoseDollarPrefix=*/true); /*diagnoseDollarPrefix=*/true);
// Operators, closures, and enum elements cannot have API names. // Operators, closures, and enum elements cannot have API names.
if ((paramContext == ParameterContextKind::Operator || if ((paramContext == ParameterContextKind::Operator ||
paramContext == ParameterContextKind::Closure || paramContext == ParameterContextKind::Closure ||
paramContext == ParameterContextKind::EnumElement) && paramContext == ParameterContextKind::EnumElement) &&
!param.FirstName.empty() && !param.FirstName.empty() && param.SecondNameLoc.isValid()) {
param.SecondNameLoc.isValid()) {
enum KeywordArgumentDiagnosticContextKind { enum KeywordArgumentDiagnosticContextKind {
Operator = 0, Operator = 0,
Closure = 1, Closure = 1,
@@ -425,7 +431,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
default: default:
llvm_unreachable("Unhandled parameter context kind!"); llvm_unreachable("Unhandled parameter context kind!");
} }
diagnose(param.FirstNameLoc, diag::parameter_operator_keyword_argument, diagnose(param.FirstNameLoc,
diag::parameter_operator_keyword_argument,
unsigned(diagContextKind)) unsigned(diagContextKind))
.fixItRemoveChars(param.FirstNameLoc, param.SecondNameLoc); .fixItRemoveChars(param.FirstNameLoc, param.SecondNameLoc);
param.FirstName = param.SecondName; param.FirstName = param.SecondName;
@@ -441,8 +448,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
status |= type; status |= type;
param.Type = type.getPtrOrNull(); param.Type = type.getPtrOrNull();
// If we didn't parse a type, then we already diagnosed that the type // If we didn't parse a type, then we already diagnosed that the
// was invalid. Remember that. // type was invalid. Remember that.
if (type.isNull() && !type.hasCodeCompletion()) if (type.isNull() && !type.hasCodeCompletion())
param.isInvalid = true; param.isInvalid = true;
} else if (paramContext != Parser::ParameterContextKind::Closure) { } else if (paramContext != Parser::ParameterContextKind::Closure) {
@@ -455,8 +462,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
bool isBareType = false; bool isBareType = false;
{ {
BacktrackingScope backtrack(*this); BacktrackingScope backtrack(*this);
isBareType = canParseType() && Tok.isAny(tok::comma, tok::r_paren, isBareType = canParseType() &&
tok::equal); Tok.isAny(tok::comma, tok::r_paren, tok::equal);
} }
if (isBareType && paramContext == ParameterContextKind::EnumElement) { if (isBareType && paramContext == ParameterContextKind::EnumElement) {
@@ -468,12 +475,11 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
param.SecondName = Identifier(); param.SecondName = Identifier();
param.SecondNameLoc = SourceLoc(); param.SecondNameLoc = SourceLoc();
} else if (isBareType && !Tok.is(tok::code_complete)) { } else if (isBareType && !Tok.is(tok::code_complete)) {
// Otherwise, if this is a bare type, then the user forgot to name the // Otherwise, if this is a bare type, then the user forgot to name
// parameter, e.g. "func foo(Int) {}" // the parameter, e.g. "func foo(Int) {}" Don't enter this case if
// Don't enter this case if the element could only be parsed as a bare // the element could only be parsed as a bare type because a code
// type because a code completion token is positioned here. In this case // completion token is positioned here. In this case the user is
// the user is about to type the parameter label and we shouldn't // about to type the parameter label and we shouldn't suggest types.
// suggest types.
SourceLoc typeStartLoc = Tok.getLoc(); SourceLoc typeStartLoc = Tok.getLoc();
auto type = parseParamType(); auto type = parseParamType();
status |= type; status |= type;
@@ -495,10 +501,11 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
// SE-110 depending on the kind of declaration. We now need to // SE-110 depending on the kind of declaration. We now need to
// warn about the misuse of this syntax and offer to // warn about the misuse of this syntax and offer to
// fix it. // fix it.
// An exception to this rule is when the type is declared with type sugar // An exception to this rule is when the type is declared with
// Reference: https://github.com/apple/swift/issues/54133 // type sugar Reference:
if (isa<OptionalTypeRepr>(param.Type) // https://github.com/apple/swift/issues/54133
|| isa<ImplicitlyUnwrappedOptionalTypeRepr>(param.Type)) { if (isa<OptionalTypeRepr>(param.Type) ||
isa<ImplicitlyUnwrappedOptionalTypeRepr>(param.Type)) {
diagnose(typeStartLoc, diag::parameter_unnamed) diagnose(typeStartLoc, diag::parameter_unnamed)
.fixItInsert(typeStartLoc, "_: "); .fixItInsert(typeStartLoc, "_: ");
} else { } else {
@@ -509,8 +516,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
} }
} }
} else { } else {
// Otherwise, we're not sure what is going on, but this doesn't smell // Otherwise, we're not sure what is going on, but this doesn't
// like a parameter. // smell like a parameter.
diagnose(Tok, diag::expected_parameter_name); diagnose(Tok, diag::expected_parameter_name);
param.isInvalid = true; param.isInvalid = true;
param.FirstNameLoc = Tok.getLoc(); param.FirstNameLoc = Tok.getLoc();
@@ -535,7 +542,8 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
SourceLoc EqualLoc = Tok.getLoc(); SourceLoc EqualLoc = Tok.getLoc();
if (isEqualBinaryOperator) { if (isEqualBinaryOperator) {
diagnose(Tok, diag::expected_assignment_instead_of_comparison_operator) diagnose(Tok,
diag::expected_assignment_instead_of_comparison_operator)
.fixItReplace(EqualLoc, "="); .fixItReplace(EqualLoc, "=");
} }
@@ -545,9 +553,10 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
// If we haven't made progress, don't add the parameter. // If we haven't made progress, don't add the parameter.
if (Tok.getLoc() == StartLoc) { if (Tok.getLoc() == StartLoc) {
// If we took a default argument index for this parameter, but didn't add // If we took a default argument index for this parameter, but didn't
// one, then give it back. // add one, then give it back.
if (defaultArgs) --defaultArgs->NextIndex; if (defaultArgs)
--defaultArgs->NextIndex;
return status; return status;
} }
@@ -1312,11 +1321,10 @@ ParserResult<Pattern> Parser::parsePatternTuple() {
// Parse all the elements. // Parse all the elements.
SmallVector<TuplePatternElt, 8> elts; SmallVector<TuplePatternElt, 8> elts;
ParserStatus ListStatus = ParserStatus ListStatus = parseList(
parseList(tok::r_paren, LPLoc, RPLoc, tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/Context.LangOpts.hasFeature(Feature::TrailingComma), /*AllowSepAfterLast=*/true, diag::expected_rparen_tuple_pattern_list,
diag::expected_rparen_tuple_pattern_list, [&]() -> ParserStatus {
[&] () -> ParserStatus {
// Parse the pattern tuple element. // Parse the pattern tuple element.
ParserStatus EltStatus; ParserStatus EltStatus;
std::optional<TuplePatternElt> elt; std::optional<TuplePatternElt> elt;

View File

@@ -1523,8 +1523,7 @@ Parser::parseAvailabilitySpecList(SmallVectorImpl<AvailabilitySpec *> &Specs,
Status.setIsParseError(); Status.setIsParseError();
} else if (consumeIf(tok::comma)) { } else if (consumeIf(tok::comma)) {
// End of list with a trailing comma. // End of list with a trailing comma.
if (Context.LangOpts.hasFeature(Feature::TrailingComma) && if (Source != AvailabilitySpecSource::Available && Tok.is(tok::r_paren)) {
Tok.is(tok::r_paren)) {
break; break;
} }
// There is more to parse in this list. // There is more to parse in this list.