@@ -4860,66 +4860,68 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
4860
4860
// Aggregate all requirement fixes that belong to the same callee
4861
4861
// and attempt to diagnose possible ambiguities.
4862
4862
{
4863
- auto isResultBuilderRef = [&](ASTNode node) {
4863
+ auto isResultBuilderMethodRef = [&](ASTNode node) {
4864
4864
auto *UDE = getAsExpr<UnresolvedDotExpr>(node);
4865
- if (!UDE)
4865
+ if (!( UDE && UDE-> isImplicit ()) )
4866
4866
return false ;
4867
4867
4868
4868
auto &ctx = getASTContext ();
4869
- return UDE->isImplicit () &&
4870
- UDE->getName ().compare (DeclNameRef (ctx.Id_buildBlock )) == 0 ;
4869
+ SmallVector<Identifier, 4 > builderMethods (
4870
+ {ctx.Id_buildBlock , ctx.Id_buildExpression , ctx.Id_buildPartialBlock ,
4871
+ ctx.Id_buildFinalResult });
4872
+
4873
+ return llvm::any_of (builderMethods, [&](const Identifier &methodId) {
4874
+ return UDE->getName ().compare (DeclNameRef (methodId)) == 0 ;
4875
+ });
4871
4876
};
4872
4877
4873
- llvm::MapVector<SourceLoc,
4874
- SmallVector<FixInContext, 4 >>
4875
- builderFixes;
4878
+ // Aggregates fixes fixes attached to `buildExpression` and `buildBlock`
4879
+ // methods at the particular source location.
4880
+ llvm::MapVector<SourceLoc, SmallVector<FixInContext, 4 >>
4881
+ builderMethodRequirementFixes;
4876
4882
4877
4883
llvm::MapVector<ConstraintLocator *, SmallVector<FixInContext, 4 >>
4878
- requirementFixes ;
4884
+ perCalleeRequirementFixes ;
4879
4885
4880
- // TODO(diagnostics): This approach doesn't work for synthesized code
4881
- // because i.e. result builders would inject a new `buildBlock` or
4882
- // `buildExpression` for every kind of builder. We need to come up
4883
- // with the strategy to unify locators in such cases.
4884
4886
for (const auto &entry : fixes) {
4885
4887
auto *fix = entry.second ;
4886
4888
if (!fix->getLocator ()->isLastElement <LocatorPathElt::AnyRequirement>())
4887
4889
continue ;
4888
4890
4889
4891
auto *calleeLoc = entry.first ->getCalleeLocator (fix->getLocator ());
4890
4892
4891
- if (isResultBuilderRef (calleeLoc->getAnchor ())) {
4893
+ if (isResultBuilderMethodRef (calleeLoc->getAnchor ())) {
4892
4894
auto *anchor = castToExpr<Expr>(calleeLoc->getAnchor ());
4893
- builderFixes [anchor->getLoc ()].push_back (entry);
4895
+ builderMethodRequirementFixes [anchor->getLoc ()].push_back (entry);
4894
4896
} else {
4895
- requirementFixes [calleeLoc].push_back (entry);
4897
+ perCalleeRequirementFixes [calleeLoc].push_back (entry);
4896
4898
}
4897
4899
}
4898
4900
4899
- SmallVector<FixInContext, 4 > diagnosedFixes;
4901
+ SmallVector<SmallVector<FixInContext, 4 >, 4 > viableGroups;
4902
+ {
4903
+ auto takeAggregateIfViable =
4904
+ [&](SmallVector<FixInContext, 4 > &aggregate) {
4905
+ // Ambiguity only if all of the solutions have a requirement
4906
+ // fix at the given location.
4907
+ if (aggregate.size () == solutions.size ())
4908
+ viableGroups.push_back (std::move (aggregate));
4909
+ };
4900
4910
4901
- for (auto &entry : builderFixes) {
4902
- auto &aggregate = entry.second ;
4911
+ for (auto &entry : builderMethodRequirementFixes)
4912
+ takeAggregateIfViable ( entry.second ) ;
4903
4913
4904
- if ( diagnoseAmbiguityWithGenericRequirements (* this , aggregate) )
4905
- diagnosedFixes. append (aggregate. begin (), aggregate. end () );
4914
+ for ( auto &entry : perCalleeRequirementFixes )
4915
+ takeAggregateIfViable (entry. second );
4906
4916
}
4907
4917
4908
- for (auto &entry : requirementFixes) {
4909
- auto &aggregate = entry.second ;
4910
-
4911
- // Ambiguity only if all of the solutions have a requirement
4912
- // fix at the given location.
4913
- if (aggregate.size () != solutions.size ())
4914
- continue ;
4915
-
4916
- if (diagnoseAmbiguityWithGenericRequirements (*this , aggregate))
4917
- diagnosedFixes.append (aggregate.begin (), aggregate.end ());
4918
+ for (auto &aggregate : viableGroups) {
4919
+ if (diagnoseAmbiguityWithGenericRequirements (*this , aggregate)) {
4920
+ // Remove diagnosed fixes.
4921
+ fixes.set_subtract (aggregate);
4922
+ diagnosed = true ;
4923
+ }
4918
4924
}
4919
-
4920
- diagnosed |= !diagnosedFixes.empty ();
4921
- // Remove any diagnosed fixes.
4922
- fixes.set_subtract (diagnosedFixes);
4923
4925
}
4924
4926
4925
4927
llvm::MapVector<std::pair<FixKind, ConstraintLocator *>,
0 commit comments