@@ -3508,23 +3508,6 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
3508
3508
return true ;
3509
3509
}
3510
3510
3511
- // Function type has fewer arguments than expected by context:
3512
- //
3513
- // ```
3514
- // func foo() {}
3515
- // let _: (Int) -> Void = foo
3516
- // ```
3517
- if (locator->isLastElement (ConstraintLocator::ContextualType)) {
3518
- auto &cs = getConstraintSystem ();
3519
- emitDiagnostic (anchor->getLoc (), diag::cannot_convert_initializer_value,
3520
- getType (anchor), resolveType (cs.getContextualType ()));
3521
- // TODO: It would be great so somehow point out which arguments are missing.
3522
- return true ;
3523
- }
3524
-
3525
- if (diagnoseInvalidTupleDestructuring ())
3526
- return true ;
3527
-
3528
3511
return false ;
3529
3512
}
3530
3513
@@ -3585,7 +3568,6 @@ bool MissingArgumentsFailure::diagnoseAsError() {
3585
3568
auto *locator = getLocator ();
3586
3569
auto path = locator->getPath ();
3587
3570
3588
- // TODO: Currently this is only intended to diagnose contextual failures.
3589
3571
if (path.empty () ||
3590
3572
!(path.back ().getKind () == ConstraintLocator::ApplyArgToParam ||
3591
3573
path.back ().getKind () == ConstraintLocator::ContextualType ||
@@ -3618,9 +3600,160 @@ bool MissingArgumentsFailure::diagnoseAsError() {
3618
3600
return true ;
3619
3601
}
3620
3602
3603
+ // Function type has fewer arguments than expected by context:
3604
+ //
3605
+ // ```
3606
+ // func foo() {}
3607
+ // let _: (Int) -> Void = foo
3608
+ // ```
3609
+ if (locator->isLastElement (ConstraintLocator::ContextualType)) {
3610
+ auto &cs = getConstraintSystem ();
3611
+ emitDiagnostic (anchor->getLoc (), diag::cannot_convert_initializer_value,
3612
+ getType (anchor), resolveType (cs.getContextualType ()));
3613
+ // TODO: It would be great so somehow point out which arguments are missing.
3614
+ return true ;
3615
+ }
3616
+
3617
+ if (diagnoseInvalidTupleDestructuring ())
3618
+ return true ;
3619
+
3620
+ if (diagnoseSingleMissingArgument ())
3621
+ return true ;
3622
+
3621
3623
return false ;
3622
3624
}
3623
3625
3626
+ bool MissingArgumentsFailure::diagnoseSingleMissingArgument () const {
3627
+ auto &ctx = getASTContext ();
3628
+
3629
+ auto *anchor = getRawAnchor ();
3630
+ if (!(isa<CallExpr>(anchor) || isa<SubscriptExpr>(anchor)))
3631
+ return false ;
3632
+
3633
+ if (SynthesizedArgs.size () != 1 )
3634
+ return false ;
3635
+
3636
+ const auto &argument = SynthesizedArgs.front ();
3637
+ auto *argType = argument.getPlainType ()->castTo <TypeVariableType>();
3638
+ auto *argLocator = argType->getImpl ().getLocator ();
3639
+ auto position =
3640
+ argLocator->findLast <LocatorPathElt::ApplyArgToParam>()->getParamIdx ();
3641
+ auto label = argument.getLabel ();
3642
+
3643
+ SmallString<32 > insertBuf;
3644
+ llvm::raw_svector_ostream insertText (insertBuf);
3645
+
3646
+ if (position != 0 )
3647
+ insertText << " , " ;
3648
+
3649
+ if (!label.empty ())
3650
+ insertText << label.str () << " : " ;
3651
+
3652
+ // Explode inout type.
3653
+ if (argument.isInOut ())
3654
+ insertText << " &" ;
3655
+
3656
+ auto resolvedType = resolveType (argType);
3657
+ // @autoclosure; the type should be the result type.
3658
+ if (argument.isAutoClosure ())
3659
+ resolvedType = resolvedType->castTo <FunctionType>()->getResult ();
3660
+
3661
+ insertText << " <#" << resolvedType << " #>" ;
3662
+
3663
+ unsigned insertableEndIdx = 0 ;
3664
+ Expr *fnExpr = nullptr ;
3665
+ Expr *argExpr = nullptr ;
3666
+ if (auto *callExpr = dyn_cast<CallExpr>(anchor)) {
3667
+ fnExpr = callExpr->getFn ();
3668
+ argExpr = callExpr->getArg ();
3669
+ insertableEndIdx = callExpr->getNumArguments ();
3670
+ if (callExpr->hasTrailingClosure ())
3671
+ insertableEndIdx -= 1 ;
3672
+ } else {
3673
+ auto *SE = cast<SubscriptExpr>(anchor);
3674
+ fnExpr = SE;
3675
+ argExpr = SE->getIndex ();
3676
+ insertableEndIdx = SE->getNumArguments ();
3677
+ if (SE->hasTrailingClosure ())
3678
+ insertableEndIdx -= 1 ;
3679
+ }
3680
+
3681
+ if (position == 0 && insertableEndIdx != 0 )
3682
+ insertText << " , " ;
3683
+
3684
+ SourceLoc insertLoc;
3685
+ if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
3686
+ // fn():
3687
+ // fn([argMissing])
3688
+ // fn(argX, argY):
3689
+ // fn([argMissing, ]argX, argY)
3690
+ // fn(argX[, argMissing], argY)
3691
+ // fn(argX, argY[, argMissing])
3692
+ // fn(argX) { closure }:
3693
+ // fn([argMissing, ]argX) { closure }
3694
+ // fn(argX[, argMissing]) { closure }
3695
+ // fn(argX[, closureLabel: ]{closure}[, argMissing)] // Not impl.
3696
+ if (insertableEndIdx == 0 )
3697
+ insertLoc = TE->getRParenLoc ();
3698
+ else if (position != 0 ) {
3699
+ auto argPos = std::min (TE->getNumElements (), position) - 1 ;
3700
+ insertLoc = Lexer::getLocForEndOfToken (
3701
+ ctx.SourceMgr , TE->getElement (argPos)->getEndLoc ());
3702
+ } else {
3703
+ insertLoc = TE->getElementNameLoc (0 );
3704
+ if (insertLoc.isInvalid ())
3705
+ insertLoc = TE->getElement (0 )->getStartLoc ();
3706
+ }
3707
+ } else {
3708
+ auto *PE = cast<ParenExpr>(argExpr);
3709
+ if (PE->getRParenLoc ().isValid ()) {
3710
+ // fn(argX):
3711
+ // fn([argMissing, ]argX)
3712
+ // fn(argX[, argMissing])
3713
+ // fn() { closure }:
3714
+ // fn([argMissing]) {closure}
3715
+ // fn([closureLabel: ]{closure}[, argMissing]) // Not impl.
3716
+ if (insertableEndIdx == 0 )
3717
+ insertLoc = PE->getRParenLoc ();
3718
+ else if (position == 0 )
3719
+ insertLoc = PE->getSubExpr ()->getStartLoc ();
3720
+ else
3721
+ insertLoc = Lexer::getLocForEndOfToken (ctx.SourceMgr ,
3722
+ PE->getSubExpr ()->getEndLoc ());
3723
+ } else {
3724
+ // fn { closure }:
3725
+ // fn[(argMissing)] { closure }
3726
+ // fn[(closureLabel:] { closure }[, missingArg)] // Not impl.
3727
+ assert (!isa<SubscriptExpr>(anchor) && " bracket less subscript" );
3728
+ assert (PE->hasTrailingClosure () &&
3729
+ " paren less ParenExpr without trailing closure" );
3730
+ insertBuf.insert (insertBuf.begin (), ' (' );
3731
+ insertBuf.insert (insertBuf.end (), ' )' );
3732
+ insertLoc =
3733
+ Lexer::getLocForEndOfToken (ctx.SourceMgr , fnExpr->getEndLoc ());
3734
+ }
3735
+ }
3736
+
3737
+ if (insertLoc.isInvalid ())
3738
+ return false ;
3739
+
3740
+ if (label.empty ()) {
3741
+ emitDiagnostic (insertLoc, diag::missing_argument_positional, position + 1 )
3742
+ .fixItInsert (insertLoc, insertText.str ());
3743
+ } else {
3744
+ emitDiagnostic (insertLoc, diag::missing_argument_named, label)
3745
+ .fixItInsert (insertLoc, insertText.str ());
3746
+ }
3747
+
3748
+ if (auto selectedOverload = getChoiceFor (getLocator ())) {
3749
+ if (auto *decl = selectedOverload->choice .getDeclOrNull ()) {
3750
+ emitDiagnostic (decl, diag::decl_declared_here, decl->getFullName ());
3751
+ }
3752
+ }
3753
+
3754
+ return true ;
3755
+ }
3756
+
3624
3757
bool MissingArgumentsFailure::diagnoseClosure (ClosureExpr *closure) {
3625
3758
auto &cs = getConstraintSystem ();
3626
3759
FunctionType *funcType = nullptr ;
0 commit comments