]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #68212 - csmoe:temp, r=estebank
authorDylan DPC <dylan.dpc@gmail.com>
Wed, 15 Jan 2020 17:19:26 +0000 (22:49 +0530)
committerGitHub <noreply@github.com>
Wed, 15 Jan 2020 17:19:26 +0000 (22:49 +0530)
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

src/librustc/traits/error_reporting.rs
src/librustc/ty/adjustment.rs
src/librustc/ty/context.rs
src/librustc_typeck/check/generator_interior.rs
src/test/ui/async-await/issue-64130-4-async-move.stderr
src/test/ui/generator/not-send-sync.stderr
src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr

index 0c9a73d78a5ebe184290243e052fa6acb2f87b95..c1df1149bbdfc234b9fda7db231d2e51b655b2d3 100644 (file)
@@ -2479,19 +2479,21 @@ fn maybe_note_obligation_cause_for_async_await(
                 );
                 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 @@ fn note_obligation_cause_for_async_await(
         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 @@ fn note_obligation_cause_for_async_await(
         // 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 @@ fn note_obligation_cause_for_async_await(
 
             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 @@ fn note_obligation_cause_for_async_await(
         };
 
         // 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 @@ fn note_obligation_cause_for_async_await(
             ),
         );
 
+        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);
index ebefb03b813f207e0593f2b69bf92c9d831b44b8..db034d1618cea6cb35659e1792760e3418c47e5a 100644 (file)
@@ -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.
index 6b98fddb22ef913b72ca56820d7fbada126c3f6f..ef776c88a8f7cd85859c809c59c46a90cb56a37d 100644 (file)
@@ -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>>,
 }
index 9d8805f225d7e1452816d10dddd764d83d7da4e5..fc02d17a50f373d9752e07d95014bfa6fcb7e954 100644 (file)
@@ -97,6 +97,7 @@ fn record(
                         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));
 
index ddbb469b99c2489a1f4e33907d586830ca54d59d..77d0885c38d58a75c4624102d11dd7d638573a35 100644 (file)
@@ -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
index 0ac1d189b79b06e255f40c4ac024386a25f04ead..18d9012b3acf69410ce744320a54424a2c066471 100644 (file)
@@ -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
    |
index b7ba0d6ab177cee0d46ca1ba9f8484b6e9d2822b..15a028f60ae1154208e9c9e7ded2a4d65be10130 100644 (file)
@@ -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