@@ -3915,9 +3915,9 @@ bool MissingArgumentsFailure::diagnoseAsError() {
3915
3915
Expr *fnExpr = nullptr ;
3916
3916
Expr *argExpr = nullptr ;
3917
3917
unsigned numArguments = 0 ;
3918
- bool hasTrailingClosure = false ;
3918
+ Optional< unsigned > firstTrailingClosure = None ;
3919
3919
3920
- std::tie (fnExpr, argExpr, numArguments, hasTrailingClosure ) =
3920
+ std::tie (fnExpr, argExpr, numArguments, firstTrailingClosure ) =
3921
3921
getCallInfo (getRawAnchor ());
3922
3922
3923
3923
// TODO(diagnostics): We should be able to suggest this fix-it
@@ -3980,46 +3980,66 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
3980
3980
auto position = argument.first ;
3981
3981
auto label = argument.second .getLabel ();
3982
3982
3983
- SmallString<32 > insertBuf;
3984
- llvm::raw_svector_ostream insertText (insertBuf);
3985
-
3986
- if (position != 0 )
3987
- insertText << " , " ;
3988
-
3989
- forFixIt (insertText, argument.second );
3990
-
3991
3983
Expr *fnExpr = nullptr ;
3992
3984
Expr *argExpr = nullptr ;
3993
- unsigned insertableEndIdx = 0 ;
3994
- bool hasTrailingClosure = false ;
3985
+ unsigned numArgs = 0 ;
3986
+ Optional< unsigned > firstTrailingClosure = None ;
3995
3987
3996
- std::tie (fnExpr, argExpr, insertableEndIdx, hasTrailingClosure ) =
3988
+ std::tie (fnExpr, argExpr, numArgs, firstTrailingClosure ) =
3997
3989
getCallInfo (anchor);
3998
3990
3999
- if (!argExpr)
3991
+ if (!argExpr) {
4000
3992
return false ;
3993
+ }
3994
+
3995
+ // Will the parameter accept a trailing closure?
3996
+ Type paramType = resolveType (argument.second .getPlainType ());
3997
+ bool paramAcceptsTrailingClosure = paramType
3998
+ ->lookThroughAllOptionalTypes ()->is <AnyFunctionType>();
4001
3999
4002
- if (hasTrailingClosure)
4003
- insertableEndIdx -= 1 ;
4000
+ // Determine whether we're inserting as a trailing closure.
4001
+ bool insertingTrailingClosure =
4002
+ firstTrailingClosure && position > *firstTrailingClosure;
4003
+
4004
+ SmallString<32 > insertBuf;
4005
+ llvm::raw_svector_ostream insertText (insertBuf);
4004
4006
4005
- if (position == 0 && insertableEndIdx != 0 )
4007
+ if (insertingTrailingClosure)
4008
+ insertText << " " ;
4009
+ else if (position != 0 )
4010
+ insertText << " , " ;
4011
+
4012
+ forFixIt (insertText, argument.second );
4013
+
4014
+ if (position == 0 && numArgs > 0 &&
4015
+ (!firstTrailingClosure || position < *firstTrailingClosure))
4006
4016
insertText << " , " ;
4007
4017
4008
4018
SourceLoc insertLoc;
4009
- if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
4010
- // fn():
4011
- // fn([argMissing])
4019
+
4020
+ if (position >= numArgs && insertingTrailingClosure) {
4021
+ // Add a trailing closure to the end.
4022
+
4023
+ // fn { closure }:
4024
+ // fn {closure} label: [argMissing]
4025
+ // fn() { closure }:
4026
+ // fn() {closure} label: [argMissing]
4027
+ // fn(argX) { closure }:
4028
+ // fn(argX) { closure } label: [argMissing]
4029
+ insertLoc = Lexer::getLocForEndOfToken (
4030
+ ctx.SourceMgr , argExpr->getEndLoc ());
4031
+ } else if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
4012
4032
// fn(argX, argY):
4013
4033
// fn([argMissing, ]argX, argY)
4014
4034
// fn(argX[, argMissing], argY)
4015
- // fn(argX, argY[, argMissing])
4016
4035
// fn(argX) { closure }:
4017
4036
// fn([argMissing, ]argX) { closure }
4018
4037
// fn(argX[, argMissing]) { closure }
4019
- // fn(argX[, closureLabel: ]{closure}[, argMissing)] // Not impl.
4020
- if (insertableEndIdx == 0 )
4038
+ // fn(argX, argY):
4039
+ // fn(argX, argY[, argMissing])
4040
+ if (numArgs == 0 ) {
4021
4041
insertLoc = TE->getRParenLoc ();
4022
- else if (position != 0 ) {
4042
+ } else if (position != 0 ) {
4023
4043
auto argPos = std::min (TE->getNumElements (), position) - 1 ;
4024
4044
insertLoc = Lexer::getLocForEndOfToken (
4025
4045
ctx.SourceMgr , TE->getElement (argPos)->getEndLoc ());
@@ -4031,25 +4051,25 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
4031
4051
} else {
4032
4052
auto *PE = cast<ParenExpr>(argExpr);
4033
4053
if (PE->getRParenLoc ().isValid ()) {
4054
+ // fn():
4055
+ // fn([argMissing])
4034
4056
// fn(argX):
4035
- // fn([argMissing, ]argX)
4036
4057
// fn(argX[, argMissing])
4058
+ // fn([argMissing, ]argX)
4037
4059
// fn() { closure }:
4038
4060
// fn([argMissing]) {closure}
4039
- // fn([closureLabel: ]{closure}[, argMissing]) // Not impl.
4040
- if (insertableEndIdx == 0 )
4041
- insertLoc = PE->getRParenLoc ();
4042
- else if (position == 0 )
4043
- insertLoc = PE->getSubExpr ()->getStartLoc ();
4044
- else
4061
+ if (position == 0 ) {
4045
4062
insertLoc = Lexer::getLocForEndOfToken (ctx.SourceMgr ,
4046
- PE->getSubExpr ()->getEndLoc ());
4063
+ PE->getLParenLoc ());
4064
+ } else {
4065
+ insertLoc = Lexer::getLocForEndOfToken (
4066
+ ctx.SourceMgr , PE->getSubExpr ()->getEndLoc ());
4067
+ }
4047
4068
} else {
4048
4069
// fn { closure }:
4049
4070
// fn[(argMissing)] { closure }
4050
- // fn[(closureLabel:] { closure }[, missingArg)] // Not impl.
4051
4071
assert (!isExpr<SubscriptExpr>(anchor) && " bracket less subscript" );
4052
- assert (PE-> hasTrailingClosure () &&
4072
+ assert (firstTrailingClosure &&
4053
4073
" paren less ParenExpr without trailing closure" );
4054
4074
insertBuf.insert (insertBuf.begin (), ' (' );
4055
4075
insertBuf.insert (insertBuf.end (), ' )' );
@@ -4061,16 +4081,28 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
4061
4081
if (insertLoc.isInvalid ())
4062
4082
return false ;
4063
4083
4084
+ // If we are trying to insert a trailing closure but the parameter
4085
+ // corresponding to the missing argument doesn't support a trailing closure,
4086
+ // don't provide a Fix-It.
4087
+ // FIXME: It's possible to parenthesize and relabel the argument list to
4088
+ // accomodate this, but it's tricky.
4089
+ bool shouldEmitFixIt =
4090
+ !(insertingTrailingClosure && !paramAcceptsTrailingClosure);
4091
+
4064
4092
if (label.empty ()) {
4065
- emitDiagnosticAt (insertLoc, diag::missing_argument_positional, position + 1 )
4066
- .fixItInsert (insertLoc, insertText.str ());
4093
+ auto diag = emitDiagnosticAt (
4094
+ insertLoc, diag::missing_argument_positional, position + 1 );
4095
+ if (shouldEmitFixIt)
4096
+ diag.fixItInsert (insertLoc, insertText.str ());
4067
4097
} else if (isPropertyWrapperInitialization ()) {
4068
4098
auto *TE = cast<TypeExpr>(fnExpr);
4069
4099
emitDiagnosticAt (TE->getLoc (), diag::property_wrapper_missing_arg_init,
4070
4100
label, resolveType (TE->getInstanceType ())->getString ());
4071
4101
} else {
4072
- emitDiagnosticAt (insertLoc, diag::missing_argument_named, label)
4073
- .fixItInsert (insertLoc, insertText.str ());
4102
+ auto diag = emitDiagnosticAt (
4103
+ insertLoc, diag::missing_argument_named, label);
4104
+ if (shouldEmitFixIt)
4105
+ diag.fixItInsert (insertLoc, insertText.str ());
4074
4106
}
4075
4107
4076
4108
if (auto selectedOverload =
@@ -4298,23 +4330,24 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
4298
4330
return TypeChecker::isConvertibleTo (argType, paramType, solution.getDC ());
4299
4331
}
4300
4332
4301
- std::tuple<Expr *, Expr *, unsigned , bool >
4333
+ std::tuple<Expr *, Expr *, unsigned , Optional< unsigned > >
4302
4334
MissingArgumentsFailure::getCallInfo (ASTNode anchor) const {
4303
4335
if (auto *call = getAsExpr<CallExpr>(anchor)) {
4304
4336
return std::make_tuple (call->getFn (), call->getArg (),
4305
- call->getNumArguments (), call->hasTrailingClosure ());
4337
+ call->getNumArguments (),
4338
+ call->getUnlabeledTrailingClosureIndex ());
4306
4339
} else if (auto *UME = getAsExpr<UnresolvedMemberExpr>(anchor)) {
4307
4340
return std::make_tuple (UME, UME->getArgument (), UME->getNumArguments (),
4308
- UME->hasTrailingClosure ());
4341
+ UME->getUnlabeledTrailingClosureIndex ());
4309
4342
} else if (auto *SE = getAsExpr<SubscriptExpr>(anchor)) {
4310
4343
return std::make_tuple (SE, SE->getIndex (), SE->getNumArguments (),
4311
- SE->hasTrailingClosure ());
4344
+ SE->getUnlabeledTrailingClosureIndex ());
4312
4345
} else if (auto *OLE = getAsExpr<ObjectLiteralExpr>(anchor)) {
4313
4346
return std::make_tuple (OLE, OLE->getArg (), OLE->getNumArguments (),
4314
- OLE->hasTrailingClosure ());
4347
+ OLE->getUnlabeledTrailingClosureIndex ());
4315
4348
}
4316
4349
4317
- return std::make_tuple (nullptr , nullptr , 0 , false );
4350
+ return std::make_tuple (nullptr , nullptr , 0 , None );
4318
4351
}
4319
4352
4320
4353
void MissingArgumentsFailure::forFixIt (
@@ -5509,6 +5542,9 @@ bool ArgumentMismatchFailure::diagnoseAsError() {
5509
5542
if (diagnosePropertyWrapperMismatch ())
5510
5543
return true ;
5511
5544
5545
+ if (diagnoseTrailingClosureMismatch ())
5546
+ return true ;
5547
+
5512
5548
auto argType = getFromType ();
5513
5549
auto paramType = getToType ();
5514
5550
@@ -5743,6 +5779,26 @@ bool ArgumentMismatchFailure::diagnosePropertyWrapperMismatch() const {
5743
5779
return true ;
5744
5780
}
5745
5781
5782
+ bool ArgumentMismatchFailure::diagnoseTrailingClosureMismatch () const {
5783
+ if (!Info.isTrailingClosure ())
5784
+ return false ;
5785
+
5786
+ auto paramType = getToType ();
5787
+ if (paramType->lookThroughAllOptionalTypes ()->is <AnyFunctionType>())
5788
+ return false ;
5789
+
5790
+ emitDiagnostic (diag::trailing_closure_bad_param, paramType)
5791
+ .highlight (getSourceRange ());
5792
+
5793
+ if (auto overload = getCalleeOverloadChoiceIfAvailable (getLocator ())) {
5794
+ if (auto *decl = overload->choice .getDeclOrNull ()) {
5795
+ emitDiagnosticAt (decl, diag::decl_declared_here, decl->getName ());
5796
+ }
5797
+ }
5798
+
5799
+ return true ;
5800
+ }
5801
+
5746
5802
void ExpandArrayIntoVarargsFailure::tryDropArrayBracketsFixIt (
5747
5803
const Expr *anchor) const {
5748
5804
// If this is an array literal, offer to remove the brackets and pass the
0 commit comments