@@ -4914,59 +4914,64 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
4914
4914
// Aggregate all requirement fixes that belong to the same callee
4915
4915
// and attempt to diagnose possible ambiguities.
4916
4916
{
4917
- auto isResultBuilderRef = [&](ASTNode node) {
4917
+ auto isResultBuilderMethodRef = [&](ASTNode node) {
4918
4918
auto *UDE = getAsExpr<UnresolvedDotExpr>(node);
4919
- if (!UDE)
4919
+ if (!( UDE && UDE-> isImplicit ()) )
4920
4920
return false ;
4921
4921
4922
4922
auto &ctx = getASTContext ();
4923
- return UDE->isImplicit () &&
4924
- UDE->getName ().compare (DeclNameRef (ctx.Id_buildBlock )) == 0 ;
4923
+ SmallVector<Identifier, 4 > builderMethods (
4924
+ {ctx.Id_buildBlock , ctx.Id_buildExpression , ctx.Id_buildPartialBlock ,
4925
+ ctx.Id_buildFinalResult });
4926
+
4927
+ return llvm::any_of (builderMethods, [&](const Identifier &methodId) {
4928
+ return UDE->getName ().compare (DeclNameRef (methodId)) == 0 ;
4929
+ });
4925
4930
};
4926
4931
4927
- llvm::MapVector<SourceLoc,
4928
- SmallVector<FixInContext, 4 >>
4929
- builderFixes;
4932
+ // Aggregates fixes fixes attached to `buildExpression` and `buildBlock`
4933
+ // methods at the particular source location.
4934
+ llvm::MapVector<SourceLoc, SmallVector<FixInContext, 4 >>
4935
+ builderMethodRequirementFixes;
4930
4936
4931
4937
llvm::MapVector<ConstraintLocator *, SmallVector<FixInContext, 4 >>
4932
- requirementFixes ;
4938
+ perCalleeRequirementFixes ;
4933
4939
4934
- // TODO(diagnostics): This approach doesn't work for synthesized code
4935
- // because i.e. result builders would inject a new `buildBlock` or
4936
- // `buildExpression` for every kind of builder. We need to come up
4937
- // with the strategy to unify locators in such cases.
4938
4940
for (const auto &entry : fixes) {
4939
4941
auto *fix = entry.second ;
4940
4942
if (!fix->getLocator ()->isLastElement <LocatorPathElt::AnyRequirement>())
4941
4943
continue ;
4942
4944
4943
4945
auto *calleeLoc = entry.first ->getCalleeLocator (fix->getLocator ());
4944
4946
4945
- if (isResultBuilderRef (calleeLoc->getAnchor ())) {
4947
+ if (isResultBuilderMethodRef (calleeLoc->getAnchor ())) {
4946
4948
auto *anchor = castToExpr<Expr>(calleeLoc->getAnchor ());
4947
- builderFixes [anchor->getLoc ()].push_back (entry);
4949
+ builderMethodRequirementFixes [anchor->getLoc ()].push_back (entry);
4948
4950
} else {
4949
- requirementFixes [calleeLoc].push_back (entry);
4951
+ perCalleeRequirementFixes [calleeLoc].push_back (entry);
4950
4952
}
4951
4953
}
4952
4954
4953
- SmallVector<FixInContext, 4 > diagnosedFixes;
4955
+ SmallVector<SmallVector<FixInContext, 4 >, 4 > viableGroups;
4956
+ {
4957
+ auto takeAggregateIfViable =
4958
+ [&](SmallVector<FixInContext, 4 > &aggregate) {
4959
+ // Ambiguity only if all of the solutions have a requirement
4960
+ // fix at the given location.
4961
+ if (aggregate.size () == solutions.size ())
4962
+ viableGroups.push_back (std::move (aggregate));
4963
+ };
4954
4964
4955
- for (auto &entry : builderFixes) {
4956
- auto &aggregate = entry.second ;
4965
+ for (auto &entry : builderMethodRequirementFixes)
4966
+ takeAggregateIfViable ( entry.second ) ;
4957
4967
4958
- if ( diagnoseAmbiguityWithGenericRequirements (* this , aggregate) )
4959
- diagnosedFixes. append (aggregate. begin (), aggregate. end () );
4968
+ for ( auto &entry : perCalleeRequirementFixes )
4969
+ takeAggregateIfViable (entry. second );
4960
4970
}
4961
4971
4962
- for (auto &entry : requirementFixes) {
4963
- auto &aggregate = entry.second ;
4964
-
4965
- // Ambiguity only if all of the solutions have a requirement
4966
- // fix at the given location.
4967
- if (aggregate.size () != solutions.size ())
4968
- continue ;
4972
+ SmallVector<FixInContext, 4 > diagnosedFixes;
4969
4973
4974
+ for (auto &aggregate : viableGroups) {
4970
4975
if (diagnoseAmbiguityWithGenericRequirements (*this , aggregate))
4971
4976
diagnosedFixes.append (aggregate.begin (), aggregate.end ());
4972
4977
}
0 commit comments