Skip to content

Commit 7dda51b

Browse files
committed
[Diagnostics] Transform tryDiagnoseTrailingClosureAmbiguity into a failure
1 parent ea62075 commit 7dda51b

File tree

3 files changed

+75
-58
lines changed

3 files changed

+75
-58
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CSDiagnostics.h"
18-
#include "ConstraintSystem.h"
1918
#include "CSDiag.h"
19+
#include "ConstraintSystem.h"
2020
#include "MiscDiagnostics.h"
21+
#include "swift/AST/Decl.h"
2122
#include "swift/AST/Expr.h"
2223
#include "swift/AST/GenericSignature.h"
24+
#include "swift/AST/ParameterList.h"
2325
#include "swift/AST/Types.h"
2426
#include "llvm/ADT/ArrayRef.h"
2527
#include "llvm/ADT/SmallString.h"
@@ -611,3 +613,56 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
611613
subElementDiagID, rvalueDiagID);
612614
return true;
613615
}
616+
617+
bool TrailingClosureAmbiguityFailure::diagnoseAsNote() {
618+
const auto *expr = getParentExpr();
619+
auto *callExpr = dyn_cast<CallExpr>(expr);
620+
if (!callExpr)
621+
return false;
622+
if (!callExpr->hasTrailingClosure())
623+
return false;
624+
if (callExpr->getFn() != getAnchor())
625+
return false;
626+
627+
llvm::SmallMapVector<Identifier, const ValueDecl *, 8> choicesByLabel;
628+
for (const auto &choice : Choices) {
629+
auto *callee = dyn_cast<AbstractFunctionDecl>(choice.getDecl());
630+
if (!callee)
631+
return false;
632+
633+
const ParameterList *paramList = callee->getParameters();
634+
const ParamDecl *param = paramList->getArray().back();
635+
636+
// Sanity-check that the trailing closure corresponds to this parameter.
637+
if (!param->hasValidSignature() ||
638+
!param->getInterfaceType()->is<AnyFunctionType>())
639+
return false;
640+
641+
Identifier trailingClosureLabel = param->getArgumentName();
642+
auto &choiceForLabel = choicesByLabel[trailingClosureLabel];
643+
644+
// FIXME: Cargo-culted from diagnoseAmbiguity: apparently the same decl can
645+
// appear more than once?
646+
if (choiceForLabel == callee)
647+
continue;
648+
649+
// If just providing the trailing closure label won't solve the ambiguity,
650+
// don't bother offering the fix-it.
651+
if (choiceForLabel != nullptr)
652+
return false;
653+
654+
choiceForLabel = callee;
655+
}
656+
657+
// If we got here, then all of the choices have unique labels. Offer them in
658+
// order.
659+
for (const auto &choicePair : choicesByLabel) {
660+
auto diag = emitDiagnostic(
661+
expr->getLoc(), diag::ambiguous_because_of_trailing_closure,
662+
choicePair.first.empty(), choicePair.second->getFullName());
663+
swift::fixItEncloseTrailingClosure(getTypeChecker(), diag, callExpr,
664+
choicePair.first);
665+
}
666+
667+
return true;
668+
}

lib/Sema/CSDiagnostics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,21 @@ class RValueTreatedAsLValueFailure final : public FailureDiagnostic {
467467
bool diagnoseAsError() override;
468468
};
469469

470+
class TrailingClosureAmbiguityFailure final : public FailureDiagnostic {
471+
ArrayRef<OverloadChoice> Choices;
472+
473+
public:
474+
TrailingClosureAmbiguityFailure(Expr *root, ConstraintSystem &cs,
475+
Expr *anchor,
476+
ArrayRef<OverloadChoice> choices)
477+
: FailureDiagnostic(root, cs, cs.getConstraintLocator(anchor)),
478+
Choices(choices) {}
479+
480+
bool diagnoseAsError() override { return false; }
481+
482+
bool diagnoseAsNote() override;
483+
};
484+
470485
} // end namespace constraints
471486
} // end namespace swift
472487

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//===----------------------------------------------------------------------===//
1818
#include "ConstraintSystem.h"
1919
#include "ConstraintGraph.h"
20-
#include "MiscDiagnostics.h"
20+
#include "CSDiagnostics.h"
2121
#include "TypeCheckType.h"
2222
#include "swift/AST/GenericEnvironment.h"
2323
#include "swift/AST/ParameterList.h"
@@ -2283,61 +2283,6 @@ static DeclName getOverloadChoiceName(ArrayRef<OverloadChoice> choices) {
22832283
return name;
22842284
}
22852285

2286-
/// Returns true if any diagnostics were emitted.
2287-
static bool
2288-
tryDiagnoseTrailingClosureAmbiguity(TypeChecker &tc, const Expr *expr,
2289-
const Expr *anchor,
2290-
ArrayRef<OverloadChoice> choices) {
2291-
auto *callExpr = dyn_cast<CallExpr>(expr);
2292-
if (!callExpr)
2293-
return false;
2294-
if (!callExpr->hasTrailingClosure())
2295-
return false;
2296-
if (callExpr->getFn() != anchor)
2297-
return false;
2298-
2299-
llvm::SmallMapVector<Identifier, const ValueDecl *, 8> choicesByLabel;
2300-
for (const OverloadChoice &choice : choices) {
2301-
auto *callee = dyn_cast<AbstractFunctionDecl>(choice.getDecl());
2302-
if (!callee)
2303-
return false;
2304-
2305-
const ParameterList *paramList = callee->getParameters();
2306-
const ParamDecl *param = paramList->getArray().back();
2307-
2308-
// Sanity-check that the trailing closure corresponds to this parameter.
2309-
if (!param->hasValidSignature() ||
2310-
!param->getInterfaceType()->is<AnyFunctionType>())
2311-
return false;
2312-
2313-
Identifier trailingClosureLabel = param->getArgumentName();
2314-
auto &choiceForLabel = choicesByLabel[trailingClosureLabel];
2315-
2316-
// FIXME: Cargo-culted from diagnoseAmbiguity: apparently the same decl can
2317-
// appear more than once?
2318-
if (choiceForLabel == callee)
2319-
continue;
2320-
2321-
// If just providing the trailing closure label won't solve the ambiguity,
2322-
// don't bother offering the fix-it.
2323-
if (choiceForLabel != nullptr)
2324-
return false;
2325-
2326-
choiceForLabel = callee;
2327-
}
2328-
2329-
// If we got here, then all of the choices have unique labels. Offer them in
2330-
// order.
2331-
for (const auto &choicePair : choicesByLabel) {
2332-
auto diag =
2333-
tc.diagnose(expr->getLoc(), diag::ambiguous_because_of_trailing_closure,
2334-
choicePair.first.empty(), choicePair.second->getFullName());
2335-
swift::fixItEncloseTrailingClosure(tc, diag, callExpr, choicePair.first);
2336-
}
2337-
2338-
return true;
2339-
}
2340-
23412286
bool ConstraintSystem::diagnoseAmbiguity(Expr *expr,
23422287
ArrayRef<Solution> solutions) {
23432288
// Produce a diff of the solutions.
@@ -2415,7 +2360,9 @@ bool ConstraintSystem::diagnoseAmbiguity(Expr *expr,
24152360
: diag::ambiguous_decl_ref,
24162361
name);
24172362

2418-
if (tryDiagnoseTrailingClosureAmbiguity(tc, expr, anchor, overload.choices))
2363+
TrailingClosureAmbiguityFailure failure(expr, *this, anchor,
2364+
overload.choices);
2365+
if (failure.diagnoseAsNote())
24192366
return true;
24202367

24212368
// Emit candidates. Use a SmallPtrSet to make sure only emit a particular

0 commit comments

Comments
 (0)