@@ -3943,9 +3943,9 @@ bool MissingArgumentsFailure::diagnoseAsError() {
3943
3943
Expr *fnExpr = nullptr ;
3944
3944
Expr *argExpr = nullptr ;
3945
3945
unsigned numArguments = 0 ;
3946
- bool hasTrailingClosure = false ;
3946
+ Optional< unsigned > firstTrailingClosure = None ;
3947
3947
3948
- std::tie (fnExpr, argExpr, numArguments, hasTrailingClosure ) =
3948
+ std::tie (fnExpr, argExpr, numArguments, firstTrailingClosure ) =
3949
3949
getCallInfo (getRawAnchor ());
3950
3950
3951
3951
// TODO(diagnostics): We should be able to suggest this fix-it
@@ -4008,46 +4008,66 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
4008
4008
auto position = argument.first ;
4009
4009
auto label = argument.second .getLabel ();
4010
4010
4011
- SmallString<32 > insertBuf;
4012
- llvm::raw_svector_ostream insertText (insertBuf);
4013
-
4014
- if (position != 0 )
4015
- insertText << " , " ;
4016
-
4017
- forFixIt (insertText, argument.second );
4018
-
4019
4011
Expr *fnExpr = nullptr ;
4020
4012
Expr *argExpr = nullptr ;
4021
- unsigned insertableEndIdx = 0 ;
4022
- bool hasTrailingClosure = false ;
4013
+ unsigned numArgs = 0 ;
4014
+ Optional< unsigned > firstTrailingClosure = None ;
4023
4015
4024
- std::tie (fnExpr, argExpr, insertableEndIdx, hasTrailingClosure ) =
4016
+ std::tie (fnExpr, argExpr, numArgs, firstTrailingClosure ) =
4025
4017
getCallInfo (anchor);
4026
4018
4027
- if (!argExpr)
4019
+ if (!argExpr) {
4028
4020
return false ;
4021
+ }
4022
+
4023
+ // Will the parameter accept a trailing closure?
4024
+ Type paramType = resolveType (argument.second .getPlainType ());
4025
+ bool paramAcceptsTrailingClosure = paramType
4026
+ ->lookThroughAllOptionalTypes ()->is <AnyFunctionType>();
4029
4027
4030
- if (hasTrailingClosure)
4031
- insertableEndIdx -= 1 ;
4028
+ // Determine whether we're inserting as a trailing closure.
4029
+ bool insertingTrailingClosure =
4030
+ firstTrailingClosure && position > *firstTrailingClosure;
4031
+
4032
+ SmallString<32 > insertBuf;
4033
+ llvm::raw_svector_ostream insertText (insertBuf);
4032
4034
4033
- if (position == 0 && insertableEndIdx != 0 )
4035
+ if (insertingTrailingClosure)
4036
+ insertText << " " ;
4037
+ else if (position != 0 )
4038
+ insertText << " , " ;
4039
+
4040
+ forFixIt (insertText, argument.second );
4041
+
4042
+ if (position == 0 && numArgs > 0 &&
4043
+ (!firstTrailingClosure || position < *firstTrailingClosure))
4034
4044
insertText << " , " ;
4035
4045
4036
4046
SourceLoc insertLoc;
4037
- if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
4038
- // fn():
4039
- // fn([argMissing])
4047
+
4048
+ if (position >= numArgs && insertingTrailingClosure) {
4049
+ // Add a trailing closure to the end.
4050
+
4051
+ // fn { closure }:
4052
+ // fn {closure} label: [argMissing]
4053
+ // fn() { closure }:
4054
+ // fn() {closure} label: [argMissing]
4055
+ // fn(argX) { closure }:
4056
+ // fn(argX) { closure } label: [argMissing]
4057
+ insertLoc = Lexer::getLocForEndOfToken (
4058
+ ctx.SourceMgr , argExpr->getEndLoc ());
4059
+ } else if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
4040
4060
// fn(argX, argY):
4041
4061
// fn([argMissing, ]argX, argY)
4042
4062
// fn(argX[, argMissing], argY)
4043
- // fn(argX, argY[, argMissing])
4044
4063
// fn(argX) { closure }:
4045
4064
// fn([argMissing, ]argX) { closure }
4046
4065
// fn(argX[, argMissing]) { closure }
4047
- // fn(argX[, closureLabel: ]{closure}[, argMissing)] // Not impl.
4048
- if (insertableEndIdx == 0 )
4066
+ // fn(argX, argY):
4067
+ // fn(argX, argY[, argMissing])
4068
+ if (numArgs == 0 ) {
4049
4069
insertLoc = TE->getRParenLoc ();
4050
- else if (position != 0 ) {
4070
+ } else if (position != 0 ) {
4051
4071
auto argPos = std::min (TE->getNumElements (), position) - 1 ;
4052
4072
insertLoc = Lexer::getLocForEndOfToken (
4053
4073
ctx.SourceMgr , TE->getElement (argPos)->getEndLoc ());
@@ -4059,25 +4079,25 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
4059
4079
} else {
4060
4080
auto *PE = cast<ParenExpr>(argExpr);
4061
4081
if (PE->getRParenLoc ().isValid ()) {
4082
+ // fn():
4083
+ // fn([argMissing])
4062
4084
// fn(argX):
4063
- // fn([argMissing, ]argX)
4064
4085
// fn(argX[, argMissing])
4086
+ // fn([argMissing, ]argX)
4065
4087
// fn() { closure }:
4066
4088
// fn([argMissing]) {closure}
4067
- // fn([closureLabel: ]{closure}[, argMissing]) // Not impl.
4068
- if (insertableEndIdx == 0 )
4069
- insertLoc = PE->getRParenLoc ();
4070
- else if (position == 0 )
4071
- insertLoc = PE->getSubExpr ()->getStartLoc ();
4072
- else
4089
+ if (position == 0 ) {
4073
4090
insertLoc = Lexer::getLocForEndOfToken (ctx.SourceMgr ,
4074
- PE->getSubExpr ()->getEndLoc ());
4091
+ PE->getLParenLoc ());
4092
+ } else {
4093
+ insertLoc = Lexer::getLocForEndOfToken (
4094
+ ctx.SourceMgr , PE->getSubExpr ()->getEndLoc ());
4095
+ }
4075
4096
} else {
4076
4097
// fn { closure }:
4077
4098
// fn[(argMissing)] { closure }
4078
- // fn[(closureLabel:] { closure }[, missingArg)] // Not impl.
4079
4099
assert (!isExpr<SubscriptExpr>(anchor) && " bracket less subscript" );
4080
- assert (PE-> hasTrailingClosure () &&
4100
+ assert (firstTrailingClosure &&
4081
4101
" paren less ParenExpr without trailing closure" );
4082
4102
insertBuf.insert (insertBuf.begin (), ' (' );
4083
4103
insertBuf.insert (insertBuf.end (), ' )' );
@@ -4089,16 +4109,28 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
4089
4109
if (insertLoc.isInvalid ())
4090
4110
return false ;
4091
4111
4112
+ // If we are trying to insert a trailing closure but the parameter
4113
+ // corresponding to the missing argument doesn't support a trailing closure,
4114
+ // don't provide a Fix-It.
4115
+ // FIXME: It's possible to parenthesize and relabel the argument list to
4116
+ // accomodate this, but it's tricky.
4117
+ bool shouldEmitFixIt =
4118
+ !(insertingTrailingClosure && !paramAcceptsTrailingClosure);
4119
+
4092
4120
if (label.empty ()) {
4093
- emitDiagnosticAt (insertLoc, diag::missing_argument_positional, position + 1 )
4094
- .fixItInsert (insertLoc, insertText.str ());
4121
+ auto diag = emitDiagnosticAt (
4122
+ insertLoc, diag::missing_argument_positional, position + 1 );
4123
+ if (shouldEmitFixIt)
4124
+ diag.fixItInsert (insertLoc, insertText.str ());
4095
4125
} else if (isPropertyWrapperInitialization ()) {
4096
4126
auto *TE = cast<TypeExpr>(fnExpr);
4097
4127
emitDiagnosticAt (TE->getLoc (), diag::property_wrapper_missing_arg_init,
4098
4128
label, resolveType (TE->getInstanceType ())->getString ());
4099
4129
} else {
4100
- emitDiagnosticAt (insertLoc, diag::missing_argument_named, label)
4101
- .fixItInsert (insertLoc, insertText.str ());
4130
+ auto diag = emitDiagnosticAt (
4131
+ insertLoc, diag::missing_argument_named, label);
4132
+ if (shouldEmitFixIt)
4133
+ diag.fixItInsert (insertLoc, insertText.str ());
4102
4134
}
4103
4135
4104
4136
if (auto selectedOverload =
@@ -4327,23 +4359,24 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
4327
4359
return TypeChecker::isConvertibleTo (argType, paramType, cs.DC );
4328
4360
}
4329
4361
4330
- std::tuple<Expr *, Expr *, unsigned , bool >
4362
+ std::tuple<Expr *, Expr *, unsigned , Optional< unsigned > >
4331
4363
MissingArgumentsFailure::getCallInfo (TypedNode anchor) const {
4332
4364
if (auto *call = getAsExpr<CallExpr>(anchor)) {
4333
4365
return std::make_tuple (call->getFn (), call->getArg (),
4334
- call->getNumArguments (), call->hasTrailingClosure ());
4366
+ call->getNumArguments (),
4367
+ call->getUnlabeledTrailingClosureIndex ());
4335
4368
} else if (auto *UME = getAsExpr<UnresolvedMemberExpr>(anchor)) {
4336
4369
return std::make_tuple (UME, UME->getArgument (), UME->getNumArguments (),
4337
- UME->hasTrailingClosure ());
4370
+ UME->getUnlabeledTrailingClosureIndex ());
4338
4371
} else if (auto *SE = getAsExpr<SubscriptExpr>(anchor)) {
4339
4372
return std::make_tuple (SE, SE->getIndex (), SE->getNumArguments (),
4340
- SE->hasTrailingClosure ());
4373
+ SE->getUnlabeledTrailingClosureIndex ());
4341
4374
} else if (auto *OLE = getAsExpr<ObjectLiteralExpr>(anchor)) {
4342
4375
return std::make_tuple (OLE, OLE->getArg (), OLE->getNumArguments (),
4343
- OLE->hasTrailingClosure ());
4376
+ OLE->getUnlabeledTrailingClosureIndex ());
4344
4377
}
4345
4378
4346
- return std::make_tuple (nullptr , nullptr , 0 , false );
4379
+ return std::make_tuple (nullptr , nullptr , 0 , None );
4347
4380
}
4348
4381
4349
4382
void MissingArgumentsFailure::forFixIt (
@@ -5527,6 +5560,9 @@ bool ArgumentMismatchFailure::diagnoseAsError() {
5527
5560
if (diagnosePropertyWrapperMismatch ())
5528
5561
return true ;
5529
5562
5563
+ if (diagnoseTrailingClosureMismatch ())
5564
+ return true ;
5565
+
5530
5566
auto argType = getFromType ();
5531
5567
auto paramType = getToType ();
5532
5568
@@ -5759,6 +5795,26 @@ bool ArgumentMismatchFailure::diagnosePropertyWrapperMismatch() const {
5759
5795
return true ;
5760
5796
}
5761
5797
5798
+ bool ArgumentMismatchFailure::diagnoseTrailingClosureMismatch () const {
5799
+ if (!Info.isTrailingClosure ())
5800
+ return false ;
5801
+
5802
+ auto paramType = getToType ();
5803
+ if (paramType->lookThroughAllOptionalTypes ()->is <AnyFunctionType>())
5804
+ return false ;
5805
+
5806
+ emitDiagnostic (diag::trailing_closure_bad_param, paramType)
5807
+ .highlight (getSourceRange ());
5808
+
5809
+ if (auto overload = getCalleeOverloadChoiceIfAvailable (getLocator ())) {
5810
+ if (auto *decl = overload->choice .getDeclOrNull ()) {
5811
+ emitDiagnosticAt (decl, diag::decl_declared_here, decl->getName ());
5812
+ }
5813
+ }
5814
+
5815
+ return true ;
5816
+ }
5817
+
5762
5818
void ExpandArrayIntoVarargsFailure::tryDropArrayBracketsFixIt (
5763
5819
const Expr *anchor) const {
5764
5820
// If this is an array literal, offer to remove the brackets and pass the
0 commit comments