@@ -3623,17 +3623,75 @@ bool MissingArgumentsFailure::diagnoseAsError() {
3623
3623
if (diagnoseInvalidTupleDestructuring ())
3624
3624
return true ;
3625
3625
3626
- if (diagnoseSingleMissingArgument () )
3627
- return true ;
3626
+ if (SynthesizedArgs. size () == 1 )
3627
+ return diagnoseSingleMissingArgument () ;
3628
3628
3629
- return false ;
3629
+ // At this point we know that this is a situation when
3630
+ // there are multiple arguments missing, so let's produce
3631
+ // a diagnostic which lists all of them and a fix-it
3632
+ // to add arguments at appropriate positions.
3633
+
3634
+ SmallString<32 > diagnostic;
3635
+ llvm::raw_svector_ostream arguments (diagnostic);
3636
+
3637
+ interleave (
3638
+ SynthesizedArgs,
3639
+ [&](const AnyFunctionType::Param &arg) {
3640
+ if (arg.hasLabel ()) {
3641
+ arguments << " '" << arg.getLabel ().str () << " '" ;
3642
+ } else {
3643
+ auto *typeVar = arg.getPlainType ()->castTo <TypeVariableType>();
3644
+ auto *locator = typeVar->getImpl ().getLocator ();
3645
+ auto paramIdx = locator->findLast <LocatorPathElt::ApplyArgToParam>()
3646
+ ->getParamIdx ();
3647
+
3648
+ arguments << " #" << (paramIdx + 1 );
3649
+ }
3650
+ },
3651
+ [&] { arguments << " , " ; });
3652
+
3653
+ auto diag = emitDiagnostic (anchor->getLoc (), diag::missing_arguments_in_call,
3654
+ arguments.str ());
3655
+
3656
+ Expr *fnExpr = nullptr ;
3657
+ Expr *argExpr = nullptr ;
3658
+ unsigned numArguments = 0 ;
3659
+ bool hasTrailingClosure = false ;
3660
+
3661
+ std::tie (fnExpr, argExpr, numArguments, hasTrailingClosure) =
3662
+ getCallInfo (getRawAnchor ());
3663
+
3664
+ // TODO(diagnostics): We should be able to suggest this fix-it
3665
+ // unconditionally.
3666
+ if (argExpr && numArguments == 0 ) {
3667
+ SmallString<32 > scratch;
3668
+ llvm::raw_svector_ostream fixIt (scratch);
3669
+ interleave (
3670
+ SynthesizedArgs,
3671
+ [&](const AnyFunctionType::Param &arg) { forFixIt (fixIt, arg); },
3672
+ [&] { fixIt << " , " ; });
3673
+
3674
+ auto *tuple = cast<TupleExpr>(argExpr);
3675
+ diag.fixItInsertAfter (tuple->getLParenLoc (), fixIt.str ());
3676
+ }
3677
+
3678
+ diag.flush ();
3679
+
3680
+ if (auto selectedOverload = getChoiceFor (locator)) {
3681
+ if (auto *decl = selectedOverload->choice .getDeclOrNull ()) {
3682
+ emitDiagnostic (decl, diag::decl_declared_here, decl->getFullName ());
3683
+ }
3684
+ }
3685
+
3686
+ return true ;
3630
3687
}
3631
3688
3632
3689
bool MissingArgumentsFailure::diagnoseSingleMissingArgument () const {
3633
3690
auto &ctx = getASTContext ();
3634
3691
3635
3692
auto *anchor = getRawAnchor ();
3636
- if (!(isa<CallExpr>(anchor) || isa<SubscriptExpr>(anchor)))
3693
+ if (!(isa<CallExpr>(anchor) || isa<SubscriptExpr>(anchor) ||
3694
+ isa<UnresolvedMemberExpr>(anchor)))
3637
3695
return false ;
3638
3696
3639
3697
if (SynthesizedArgs.size () != 1 )
@@ -3652,37 +3710,21 @@ bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
3652
3710
if (position != 0 )
3653
3711
insertText << " , " ;
3654
3712
3655
- if (!label.empty ())
3656
- insertText << label.str () << " : " ;
3713
+ forFixIt (insertText, argument);
3657
3714
3658
- // Explode inout type.
3659
- if (argument.isInOut ())
3660
- insertText << " &" ;
3715
+ Expr *fnExpr = nullptr ;
3716
+ Expr *argExpr = nullptr ;
3717
+ unsigned insertableEndIdx = 0 ;
3718
+ bool hasTrailingClosure = false ;
3661
3719
3662
- auto resolvedType = resolveType (argType);
3663
- // @autoclosure; the type should be the result type.
3664
- if (argument.isAutoClosure ())
3665
- resolvedType = resolvedType->castTo <FunctionType>()->getResult ();
3720
+ std::tie (fnExpr, argExpr, insertableEndIdx, hasTrailingClosure) =
3721
+ getCallInfo (anchor);
3666
3722
3667
- insertText << " <#" << resolvedType << " #>" ;
3723
+ if (!argExpr)
3724
+ return false ;
3668
3725
3669
- unsigned insertableEndIdx = 0 ;
3670
- Expr *fnExpr = nullptr ;
3671
- Expr *argExpr = nullptr ;
3672
- if (auto *callExpr = dyn_cast<CallExpr>(anchor)) {
3673
- fnExpr = callExpr->getFn ();
3674
- argExpr = callExpr->getArg ();
3675
- insertableEndIdx = callExpr->getNumArguments ();
3676
- if (callExpr->hasTrailingClosure ())
3677
- insertableEndIdx -= 1 ;
3678
- } else {
3679
- auto *SE = cast<SubscriptExpr>(anchor);
3680
- fnExpr = SE;
3681
- argExpr = SE->getIndex ();
3682
- insertableEndIdx = SE->getNumArguments ();
3683
- if (SE->hasTrailingClosure ())
3684
- insertableEndIdx -= 1 ;
3685
- }
3726
+ if (hasTrailingClosure)
3727
+ insertableEndIdx -= 1 ;
3686
3728
3687
3729
if (position == 0 && insertableEndIdx != 0 )
3688
3730
insertText << " , " ;
@@ -3969,6 +4011,40 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
3969
4011
return TC.isConvertibleTo (argType, paramType, cs.DC );
3970
4012
}
3971
4013
4014
+ std::tuple<Expr *, Expr *, unsigned , bool >
4015
+ MissingArgumentsFailure::getCallInfo (Expr *anchor) const {
4016
+ if (auto *call = dyn_cast<CallExpr>(anchor)) {
4017
+ return std::make_tuple (call->getFn (), call->getArg (),
4018
+ call->getNumArguments (), call->hasTrailingClosure ());
4019
+ } else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(anchor)) {
4020
+ return std::make_tuple (UME, UME->getArgument (), UME->getNumArguments (),
4021
+ UME->hasTrailingClosure ());
4022
+ } else if (auto *SE = dyn_cast<SubscriptExpr>(anchor)) {
4023
+ return std::make_tuple (SE, SE->getIndex (), SE->getNumArguments (),
4024
+ SE->hasTrailingClosure ());
4025
+ }
4026
+
4027
+ return std::make_tuple (nullptr , nullptr , 0 , false );
4028
+ }
4029
+
4030
+ void MissingArgumentsFailure::forFixIt (
4031
+ llvm::raw_svector_ostream &out,
4032
+ const AnyFunctionType::Param &argument) const {
4033
+ if (argument.hasLabel ())
4034
+ out << argument.getLabel ().str () << " : " ;
4035
+
4036
+ // Explode inout type.
4037
+ if (argument.isInOut ())
4038
+ out << " &" ;
4039
+
4040
+ auto resolvedType = resolveType (argument.getPlainType ());
4041
+ // @autoclosure; the type should be the result type.
4042
+ if (argument.isAutoClosure ())
4043
+ resolvedType = resolvedType->castTo <FunctionType>()->getResult ();
4044
+
4045
+ out << " <#" << resolvedType << " #>" ;
4046
+ }
4047
+
3972
4048
bool ClosureParamDestructuringFailure::diagnoseAsError () {
3973
4049
auto *closure = cast<ClosureExpr>(getAnchor ());
3974
4050
auto params = closure->getParameters ();
0 commit comments