about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-01-15 22:49:26 +0530
committerGitHub <noreply@github.com>2020-01-15 22:49:26 +0530
commitae1e75bf4e6a2e8f112627b840f1a70e43cb2152 (patch)
treef628389f1c1a85033807391045327c97f910603a
parent1b7b8cbed32987eda783dae0739b9e52edc8db5e (diff)
parent4eb47ded54610300c54291aee74d5585a711e75b (diff)
downloadrust-ae1e75bf4e6a2e8f112627b840f1a70e43cb2152.tar.gz
rust-ae1e75bf4e6a2e8f112627b840f1a70e43cb2152.zip
Rollup merge of #68212 - csmoe:temp, r=estebank
Suggest to shorten temporary lifetime during method call inside generator

Closes https://github.com/rust-lang/rust/issues/67376
![image](https://user-images.githubusercontent.com/35686186/72364752-f6b1e400-3731-11ea-8ec9-8297ba4c6c77.png)

r? @estebank
cc @tmandry @nikomatsakis
-rw-r--r--src/librustc/traits/error_reporting.rs32
-rw-r--r--src/librustc/ty/adjustment.rs9
-rw-r--r--src/librustc/ty/context.rs7
-rw-r--r--src/librustc_typeck/check/generator_interior.rs17
-rw-r--r--src/test/ui/async-await/issue-64130-4-async-move.stderr5
-rw-r--r--src/test/ui/generator/not-send-sync.stderr2
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr4
7 files changed, 60 insertions, 16 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 0c9a73d78a5..c1df1149bbd 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -2479,19 +2479,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 +2516,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 +2552,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 +2568,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 {
@@ -2581,7 +2585,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         };
 
         // Look at the last interior type to get a span for the `.await`.
-        let await_span = tables.generator_interior_types.iter().map(|i| i.span).last().unwrap();
+        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
         let mut span = MultiSpan::from_span(await_span);
         span.push_span_label(
             await_span,
@@ -2606,6 +2610,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             ),
         );
 
+        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",
+                    );
+                }
+            }
+        }
+
         // Add a note for the item obligation that remains - normally a note pointing to the
         // bound that introduced the obligation (e.g. `T: Send`).
         debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index ebefb03b813..db034d1618c 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..ef776c88a8f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -315,8 +315,7 @@ pub struct ResolvedOpaqueTy<'tcx> {
 ///
 /// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for
 /// the scope that contains `x`.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
 pub struct GeneratorInteriorTypeCause<'tcx> {
     /// Type of the captured binding.
     pub ty: Ty<'tcx>,
@@ -324,6 +323,8 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
     pub span: Span,
     /// Span of the scope of the captured binding.
     pub scope_span: Option<Span>,
+    /// Expr which the type evaluated from.
+    pub expr: Option<hir::HirId>,
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug)]
@@ -436,7 +437,7 @@ pub struct TypeckTables<'tcx> {
     /// entire variable.
     pub upvar_list: ty::UpvarListMap,
 
-    /// Stores the type, span and optional scope span of all types
+    /// Stores the type, expression, 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>>,
 }
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index 9d8805f225d..fc02d17a50f 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -97,6 +97,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                         span: source_span,
                         ty: &ty,
                         scope_span,
+                        expr: expr.map(|e| e.hir_id),
                     })
                     .or_insert(entries);
             }
@@ -164,17 +165,25 @@ pub fn resolve_interior<'a, 'tcx>(
     // which means that none of the regions inside relate to any other, even if
     // typeck had previously found constraints that would cause them to be related.
     let mut counter = 0;
-    let types = fcx.tcx.fold_regions(&types, &mut false, |_, current_depth| {
+    let fold_types: Vec<_> = types.iter().map(|(t, _)| t.ty).collect();
+    let folded_types = fcx.tcx.fold_regions(&fold_types, &mut false, |_, current_depth| {
         counter += 1;
         fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)))
     });
 
     // Store the generator types and spans into the tables for this generator.
-    let interior_types = types.iter().map(|t| t.0.clone()).collect::<Vec<_>>();
-    visitor.fcx.inh.tables.borrow_mut().generator_interior_types = interior_types;
+    let types = types
+        .into_iter()
+        .zip(&folded_types)
+        .map(|((mut interior_cause, _), ty)| {
+            interior_cause.ty = ty;
+            interior_cause
+        })
+        .collect();
+    visitor.fcx.inh.tables.borrow_mut().generator_interior_types = types;
 
     // Extract type components
-    let type_list = fcx.tcx.mk_type_list(types.into_iter().map(|t| (t.0).ty));
+    let type_list = fcx.tcx.mk_type_list(folded_types.iter());
 
     let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
 
diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr
index ddbb469b99c..77d0885c38d 100644
--- a/src/test/ui/async-await/issue-64130-4-async-move.stderr
+++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr
@@ -16,6 +16,11 @@ LL |                 let _x = get().await;
 ...
 LL |     }
    |     - `client` is later dropped here
+help: consider moving this method call into a `let` binding to create a shorter lived borrow
+  --> $DIR/issue-64130-4-async-move.rs:19:15
+   |
+LL |         match client.status() {
+   |               ^^^^^^^^^^^^^^^
    = note: the return type of a function must have a statically known size
 
 error: aborting due to previous error
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index 0ac1d189b79..18d9012b3ac 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -20,7 +20,7 @@ LL |     fn assert_sync<T: Sync>(_: T) {}
 LL |     assert_sync(|| {
    |     ^^^^^^^^^^^ future returned by `main` is not `Sync`
    |
-   = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
+   = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell<i32>, (), ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
 note: future is not `Sync` as this value is used across an yield
   --> $DIR/not-send-sync.rs:12:9
    |
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index b7ba0d6ab17..15a028f60ae 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -76,7 +76,7 @@ error[E0720]: opaque type expands to a recursive type
 LL | fn generator_capture() -> impl Sized {
    |                           ^^^^^^^^^^ expands to a recursive type
    |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]`
+   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {(), ()}]`
 
 error[E0720]: opaque type expands to a recursive type
   --> $DIR/recursive-impl-trait-type-indirect.rs:53:26
@@ -92,7 +92,7 @@ error[E0720]: opaque type expands to a recursive type
 LL | fn generator_hold() -> impl Sized {
    |                        ^^^^^^^^^^ expands to a recursive type
    |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]`
+   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, (), ()}]`
 
 error[E0720]: opaque type expands to a recursive type
   --> $DIR/recursive-impl-trait-type-indirect.rs:69:26