about summary refs log tree commit diff
diff options
context:
space:
mode:
authorcsmoe <csmoe@msn.com>2020-01-14 21:21:14 +0800
committercsmoe <csmoe@msn.com>2020-01-14 21:21:14 +0800
commit148c1bca0f0eb8da23a50cd876cb86cb060a8375 (patch)
tree171f1143993739d504759fba6736b92bc29a412c
parent0b6c116a84fb1dbb60b5870291f5d7df808c280d (diff)
downloadrust-148c1bca0f0eb8da23a50cd876cb86cb060a8375.tar.gz
rust-148c1bca0f0eb8da23a50cd876cb86cb060a8375.zip
record generoator interior exprs in typecktable
-rw-r--r--src/librustc/traits/error_reporting.rs33
-rw-r--r--src/librustc/ty/adjustment.rs9
-rw-r--r--src/librustc/ty/context.rs5
3 files changed, 41 insertions, 6 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 0c9a73d78a5..66737372bda 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -2456,7 +2456,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         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,
@@ -2479,19 +2480,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 );
                 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,
@@ -2514,6 +2517,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         err: &mut DiagnosticBuilder<'_>,
         target_span: Span,
         scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
         snippet: String,
         first_generator: DefId,
         last_generator: Option<DefId>,
@@ -2549,6 +2553,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         // 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") };
@@ -2564,8 +2569,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
             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 {
@@ -2588,6 +2593,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             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.
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index ebefb03b813..6531289bd70 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -81,6 +81,15 @@ pub struct Adjustment<'tcx> {
     pub target: Ty<'tcx>,
 }
 
+impl Adjustment<'tcx> {
+    pub fn is_region_borrow(&self) -> bool {
+        match self.kind {
+            Adjust::Borrow(AutoBorrow::Ref(..)) => true,
+            _ => false
+        }
+    }
+}
+
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum Adjust<'tcx> {
     /// Go from ! to any type.
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6b98fddb22e..4a5fced7a89 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -439,6 +439,8 @@ pub struct TypeckTables<'tcx> {
     /// Stores the type, span and optional scope span of all types
     /// that are live across the yield of this generator (if a generator).
     pub generator_interior_types: Vec<GeneratorInteriorTypeCause<'tcx>>,
+
+    pub generator_interior_exprs: Vec<Option<hir::HirId>>,
 }
 
 impl<'tcx> TypeckTables<'tcx> {
@@ -465,6 +467,7 @@ impl<'tcx> TypeckTables<'tcx> {
             concrete_opaque_types: Default::default(),
             upvar_list: Default::default(),
             generator_interior_types: Default::default(),
+            generator_interior_exprs: Default::default(),
         }
     }
 
@@ -728,6 +731,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             ref concrete_opaque_types,
             ref upvar_list,
             ref generator_interior_types,
+            ref generator_interior_exprs,
         } = *self;
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
@@ -766,6 +770,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             concrete_opaque_types.hash_stable(hcx, hasher);
             upvar_list.hash_stable(hcx, hasher);
             generator_interior_types.hash_stable(hcx, hasher);
+            generator_interior_exprs.hash_stable(hcx, hasher);
         })
     }
 }