@@ -177,6 +177,21 @@ FailureDiagnostic::getArgumentListFor(ConstraintLocator *locator) const {
177
177
return S.getArgumentList (locator);
178
178
}
179
179
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
+
180
195
Expr *FailureDiagnostic::getBaseExprFor (const Expr *anchor) const {
181
196
if (!anchor)
182
197
return nullptr ;
@@ -5177,6 +5192,9 @@ bool MissingArgumentsFailure::diagnoseAsError() {
5177
5192
return true ;
5178
5193
}
5179
5194
5195
+ if (diagnoseMissingResultBuilderElement ())
5196
+ return true ;
5197
+
5180
5198
if (diagnoseInvalidTupleDestructuring ())
5181
5199
return true ;
5182
5200
@@ -5514,6 +5532,55 @@ bool MissingArgumentsFailure::diagnoseClosure(const ClosureExpr *closure) {
5514
5532
return true ;
5515
5533
}
5516
5534
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
+
5517
5584
bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring () const {
5518
5585
auto *locator = getLocator ();
5519
5586
if (!locator->isLastElement <LocatorPathElt::ApplyArgument>())
0 commit comments