Partially Revert #27862

When SE-110 was being implemented, we accidentally began to accept
closure parameter declarations that had no associated parameter names,
e.g.

foo { ([Int]) in /**/ }

This syntax has never been sanctioned by any version of Swift and should
be banned.  However, the change was made long enough ago and there are
enough clients relying on this, that we cannot accept the source break
at the moment.  For now, add a bit to ParamDecl that marks a parameter
as destructured, and back out setting the invalid bit on the type repr
for these kinds of declarations.

To prevent further spread of this syntax, stub in a warning that offers
to insert an anonymous parameter.

Resolves part of rdar://56673657 and improves QoI for errors like
rdar://56911630
This commit is contained in:
Robert Widmann
2019-11-08 17:29:16 -08:00
parent 1ea23d917f
commit dd1b15775d
9 changed files with 45 additions and 11 deletions

View File

@@ -363,12 +363,18 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
if (param.Type) {
// Mark current parameter type as invalid so it is possible
// to diagnose it as destructuring of the closure parameter list.
param.Type->setInvalid();
param.isInvalid = true;
param.isPotentiallyDestructured = true;
if (!isClosure) {
// Unnamed parameters must be written as "_: Type".
diagnose(typeStartLoc, diag::parameter_unnamed)
.fixItInsert(typeStartLoc, "_: ");
} else {
// Unnamed parameters were accidentally possibly accepted after
// SE-110 depending on the kind of declaration. We now need to
// warn about the misuse of this syntax and offer to
// fix it.
diagnose(typeStartLoc, diag::parameter_unnamed_warn)
.fixItInsert(typeStartLoc, "_: ");
}
}
} else {
@@ -492,7 +498,13 @@ mapParsedParameters(Parser &parser,
// If we diagnosed this parameter as a parse error, propagate to the decl.
if (paramInfo.isInvalid)
param->setInvalid();
// If we need to diagnose this parameter as a destructuring, propagate that
// to the decl.
// FIXME: This is a terrible way to catch this.
if (paramInfo.isPotentiallyDestructured)
param->setDestructured(true);
// If a type was provided, create the type for the parameter.
if (auto type = paramInfo.Type) {
// If 'inout' was specified, turn the type into an in-out type.