@@ -217,6 +217,32 @@ inferNameAndRootHelper(SILValue value) {
217217 return VariableNameInferrer::inferNameAndRoot (value);
218218}
219219
220+ // / Sometimes we use a store_borrow + temporary to materialize a borrowed value
221+ // / to be passed to another function. We want to emit the error on the function
222+ // / itself, not the store_borrow so we get the best location. We only do this if
223+ // / we can prove that we have a store_borrow to an alloc_stack, the store_borrow
224+ // / is the only thing stored into the alloc_stack, and except for the
225+ // / store_borrow, the alloc_stack has a single non_destroy user, a function we
226+ // / are calling.
227+ static Operand *
228+ findClosureUseThroughStoreBorrowTemporary (StoreBorrowInst *sbi) {
229+ auto *asi = dyn_cast<AllocStackInst>(sbi->getDest ());
230+ if (!asi)
231+ return {};
232+ Operand *resultUse = nullptr ;
233+ for (auto *use : asi->getUses ()) {
234+ if (use == &sbi->getAllOperands ()[StoreBorrowInst::Dest])
235+ continue ;
236+ if (isa<EndBorrowInst>(use->getUser ()))
237+ continue ;
238+ auto fas = FullApplySite::isa (use->getUser ());
239+ if (!fas)
240+ return {};
241+ resultUse = use;
242+ }
243+ return resultUse;
244+ }
245+
220246// / Find a use corresponding to the potentially recursive capture of \p
221247// / initialOperand that would be appropriate for diagnostics.
222248// /
@@ -261,9 +287,15 @@ findClosureUse(Operand *initialOperand) {
261287 if (isIncidentalUse (user) && !isa<IgnoredUseInst>(user))
262288 continue ;
263289
290+ // Ignore some instructions we do not care about.
291+ if (isa<DestroyValueInst, EndBorrowInst, EndAccessInst, DeallocStackInst>(
292+ user))
293+ continue ;
294+
264295 // Look through some insts we do not care about.
265296 if (isa<CopyValueInst, BeginBorrowInst, ProjectBoxInst, BeginAccessInst>(
266297 user) ||
298+ isa<MarkUnresolvedNonCopyableValueInst>(user) ||
267299 isMoveOnlyWrapperUse (user) ||
268300 // We want to treat move_value [var_decl] as a real use since we are
269301 // assigning to a var.
@@ -308,6 +340,17 @@ findClosureUse(Operand *initialOperand) {
308340 }
309341 }
310342
343+ // If we have a store_borrow, see if we are using it to just marshal a use
344+ // to a full apply site.
345+ if (auto *sbi = dyn_cast<StoreBorrowInst>(op->getUser ());
346+ sbi && op == &sbi->getAllOperands ()[StoreBorrowInst::Src]) {
347+ if (auto *use = findClosureUseThroughStoreBorrowTemporary (sbi)) {
348+ if (visitedOperand.insert (use).second )
349+ worklist.emplace_back (use, fArg );
350+ continue ;
351+ }
352+ }
353+
311354 // Otherwise, we have a real use. Return it and the function argument that
312355 // it was derived from.
313356 return pair;
0 commit comments