@@ -177,6 +177,21 @@ FailureDiagnostic::getArgumentListFor(ConstraintLocator *locator) const {
177177 return S.getArgumentList (locator);
178178}
179179
180+ StringRef FailureDiagnostic::getEditorPlaceholder (
181+ StringRef description, Type ty,
182+ llvm::SmallVectorImpl<char > &scratch) const {
183+ llvm::raw_svector_ostream OS (scratch);
184+ OS << " <#" ;
185+ if (!ty || ty->is <UnresolvedType>()) {
186+ OS << description;
187+ } else {
188+ OS << " T##" ;
189+ ty.print (OS);
190+ }
191+ OS << " #>" ;
192+ return StringRef (scratch.data (), scratch.size ());
193+ }
194+
180195Expr *FailureDiagnostic::getBaseExprFor (const Expr *anchor) const {
181196 if (!anchor)
182197 return nullptr ;
@@ -5177,6 +5192,9 @@ bool MissingArgumentsFailure::diagnoseAsError() {
51775192 return true ;
51785193 }
51795194
5195+ if (diagnoseMissingResultBuilderElement ())
5196+ return true ;
5197+
51805198 if (diagnoseInvalidTupleDestructuring ())
51815199 return true ;
51825200
@@ -5514,6 +5532,55 @@ bool MissingArgumentsFailure::diagnoseClosure(const ClosureExpr *closure) {
55145532 return true ;
55155533}
55165534
5535+ bool MissingArgumentsFailure::diagnoseMissingResultBuilderElement () const {
5536+ auto &ctx = getASTContext ();
5537+
5538+ // Only handle a single missing argument in an empty builder for now. This
5539+ // should be the most common case though since most builders support N >= 1
5540+ // elements.
5541+ if (SynthesizedArgs.size () != 1 )
5542+ return false ;
5543+
5544+ auto *call = getAsExpr<CallExpr>(getRawAnchor ());
5545+ if (!call || !call->isImplicit () || !call->getArgs ()->empty ())
5546+ return false ;
5547+
5548+ auto *UDE = dyn_cast<UnresolvedDotExpr>(call->getFn ());
5549+ if (!UDE || !isResultBuilderMethodReference (ctx, UDE))
5550+ return false ;
5551+
5552+ auto overload = getCalleeOverloadChoiceIfAvailable (getLocator ());
5553+ if (!overload)
5554+ return false ;
5555+
5556+ auto *decl = overload->choice .getDeclOrNull ();
5557+ if (!decl || decl->getBaseName () != ctx.Id_buildBlock )
5558+ return false ;
5559+
5560+ auto resultBuilder =
5561+ getType (UDE->getBase ())->getMetatypeInstanceType ()->getAnyNominal ();
5562+ if (!resultBuilder)
5563+ return false ;
5564+
5565+ auto paramType = resolveType (SynthesizedArgs.front ().param .getPlainType ());
5566+
5567+ SmallString<64 > scratch;
5568+ auto fixIt = getEditorPlaceholder (" result" , paramType, scratch);
5569+ auto fixItLoc = call->getStartLoc ();
5570+
5571+ if (paramType->is <UnresolvedType>()) {
5572+ emitDiagnostic (diag::result_builder_missing_element,
5573+ resultBuilder->getName ())
5574+ .fixItInsertAfter (fixItLoc, fixIt);
5575+ } else {
5576+ emitDiagnostic (diag::result_builder_missing_element_of_type, paramType,
5577+ resultBuilder->getName ())
5578+ .fixItInsertAfter (fixItLoc, fixIt);
5579+ }
5580+ emitDiagnosticAt (decl, diag::decl_declared_here, decl);
5581+ return true ;
5582+ }
5583+
55175584bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring () const {
55185585 auto *locator = getLocator ();
55195586 if (!locator->isLastElement <LocatorPathElt::ApplyArgument>())
0 commit comments