Skip to content

Commit 4d998c8

Browse files
committed
---
yaml --- r: 349178 b: refs/heads/master-next c: 60bcc94 h: refs/heads/master
1 parent feba36c commit 4d998c8

File tree

3 files changed

+154
-19
lines changed

3 files changed

+154
-19
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
refs/heads/master: 3574c513bbc5578dd9346b4ea9ab5995c5927bb5
3-
refs/heads/master-next: ee8c78eef532c3802301fdd01142c5aa66e65834
3+
refs/heads/master-next: 60bcc9457516cab412b06d9ef907e1ca46bf443e
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea
66
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-b: 66d897bfcf64a82cb9a87f5e663d889189d06d07

branches/master-next/lib/Sema/CSDiagnostics.cpp

Lines changed: 151 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3508,23 +3508,6 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
35083508
return true;
35093509
}
35103510

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-
35283511
return false;
35293512
}
35303513

@@ -3585,7 +3568,6 @@ bool MissingArgumentsFailure::diagnoseAsError() {
35853568
auto *locator = getLocator();
35863569
auto path = locator->getPath();
35873570

3588-
// TODO: Currently this is only intended to diagnose contextual failures.
35893571
if (path.empty() ||
35903572
!(path.back().getKind() == ConstraintLocator::ApplyArgToParam ||
35913573
path.back().getKind() == ConstraintLocator::ContextualType ||
@@ -3618,9 +3600,160 @@ bool MissingArgumentsFailure::diagnoseAsError() {
36183600
return true;
36193601
}
36203602

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+
36213623
return false;
36223624
}
36233625

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+
36243757
bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) {
36253758
auto &cs = getConstraintSystem();
36263759
FunctionType *funcType = nullptr;

branches/master-next/lib/Sema/CSDiagnostics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,8 @@ class MissingArgumentsFailure final : public FailureDiagnostic {
11981198
bool diagnoseAsError() override;
11991199

12001200
private:
1201+
bool diagnoseSingleMissingArgument() const;
1202+
12011203
/// If missing arguments come from a closure,
12021204
/// let's produce tailored diagnostics.
12031205
bool diagnoseClosure(ClosureExpr *closure);

0 commit comments

Comments
 (0)