let target_span = tables
.generator_interior_types
.iter()
- .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
+ .zip(tables.generator_interior_exprs.iter())
+ .find(|(ty::GeneratorInteriorTypeCause { ty, .. }, _)| {
// Careful: the regions for types that appear in the
// generator interior are not generally known, so we
// want to erase them when comparing (and anyway,
);
eq
})
- .map(|ty::GeneratorInteriorTypeCause { span, scope_span, .. }| {
- (span, source_map.span_to_snippet(*span), scope_span)
+ .map(|(ty::GeneratorInteriorTypeCause { span, scope_span, .. }, expr)| {
+ (span, source_map.span_to_snippet(*span), scope_span, expr)
});
+
debug!(
"maybe_note_obligation_cause_for_async_await: target_ty={:?} \
generator_interior_types={:?} target_span={:?}",
target_ty, tables.generator_interior_types, target_span
);
- if let Some((target_span, Ok(snippet), scope_span)) = target_span {
+ if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
self.note_obligation_cause_for_async_await(
err,
*target_span,
scope_span,
+ *expr,
snippet,
generator_did,
last_generator,
err: &mut DiagnosticBuilder<'_>,
target_span: Span,
scope_span: &Option<Span>,
+ expr: Option<hir::HirId>,
snippet: String,
first_generator: DefId,
last_generator: Option<DefId>,
// not implemented.
let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
+ let hir = self.tcx.hir();
let trait_explanation = if is_send || is_sync {
let (trait_name, trait_verb) =
if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
let message = if let Some(name) = last_generator
.and_then(|generator_did| self.tcx.parent(generator_did))
- .and_then(|parent_did| self.tcx.hir().as_local_hir_id(parent_did))
- .and_then(|parent_hir_id| self.tcx.hir().opt_name(parent_hir_id))
+ .and_then(|parent_did| hir.as_local_hir_id(parent_did))
+ .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
{
format!("future returned by `{}` is not {}", name, trait_name)
} else {
};
span.push_span_label(original_span, message);
- err.set_span(span);
+ err.set_span(span.clone());
format!("is not {}", trait_name)
} else {
format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
);
+ if let Some(expr_id) = expr {
+ let expr = hir.expect_expr(expr_id);
+ let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+ let parent = hir.get_parent_node(expr_id);
+ if let Some(hir::Node::Expr(e)) = hir.find(parent) {
+ let method_span = hir.span(parent);
+ if tables.is_method_call(e) && is_ref {
+ err.span_help(
+ method_span,
+ "consider moving this method call into a `let` \
+ binding to create a shorter lived borrow"
+ );
+ }
+ }
+ }
+
span.push_span_label(target_span, format!("has type `{}`", target_ty));
// If available, use the scope span to annotate the drop location.