]> git.lizzy.rs Git - rust.git/commitdiff
Suggest move for closures and async blocks in more cases.
authorAlex Aktsipetrov <alex.akts@gmail.com>
Tue, 7 Apr 2020 21:57:26 +0000 (23:57 +0200)
committerAlex Aktsipetrov <alex.akts@gmail.com>
Wed, 8 Apr 2020 11:01:53 +0000 (13:01 +0200)
src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
src/librustc_mir/lib.rs
src/librustc_mir/util/borrowck_errors.rs
src/test/ui/async-await/async-borrowck-escaping-block-error.fixed
src/test/ui/async-await/async-borrowck-escaping-block-error.rs
src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
src/test/ui/async-await/async-borrowck-escaping-closure-error.rs
src/test/ui/impl-trait/does-not-live-long-enough.rs
src/test/ui/impl-trait/does-not-live-long-enough.stderr

index 9df5760563129802b790870965b86e89c353529a..65561e224dbfdead3f285f67ff1e21e05e7cbb92 100644 (file)
@@ -760,47 +760,26 @@ pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough(
             (
                 Some(ref name),
                 BorrowExplanation::MustBeValidFor {
-                    category: category @ ConstraintCategory::Return,
+                    category:
+                        category
+                        @
+                        (ConstraintCategory::Return
+                        | ConstraintCategory::CallArgument
+                        | ConstraintCategory::OpaqueType),
                     from_closure: false,
                     ref region_name,
                     span,
                     ..
                 },
-            )
-            | (
-                Some(ref name),
-                BorrowExplanation::MustBeValidFor {
-                    category: category @ ConstraintCategory::CallArgument,
-                    from_closure: false,
-                    ref region_name,
-                    span,
-                    ..
-                },
-            ) if borrow_spans.for_closure() => self.report_escaping_closure_capture(
-                borrow_spans,
-                borrow_span,
-                region_name,
-                category,
-                span,
-                &format!("`{}`", name),
-            ),
-            (
-                Some(ref name),
-                BorrowExplanation::MustBeValidFor {
-                    category: category @ ConstraintCategory::OpaqueType,
-                    from_closure: false,
-                    ref region_name,
+            ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
+                .report_escaping_closure_capture(
+                    borrow_spans,
+                    borrow_span,
+                    region_name,
+                    category,
                     span,
-                    ..
-                },
-            ) if borrow_spans.for_generator() => self.report_escaping_closure_capture(
-                borrow_spans,
-                borrow_span,
-                region_name,
-                category,
-                span,
-                &format!("`{}`", name),
-            ),
+                    &format!("`{}`", name),
+                ),
             (
                 ref name,
                 BorrowExplanation::MustBeValidFor {
@@ -1187,7 +1166,6 @@ fn report_escaping_closure_capture(
     ) -> DiagnosticBuilder<'cx> {
         let tcx = self.infcx.tcx;
         let args_span = use_span.args_or_use();
-        let mut err = self.cannot_capture_in_long_lived_closure(args_span, captured_var, var_span);
 
         let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) {
             Ok(mut string) => {
@@ -1213,6 +1191,9 @@ fn report_escaping_closure_capture(
             },
             None => "closure",
         };
+
+        let mut err =
+            self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span);
         err.span_suggestion(
             args_span,
             &format!(
@@ -1225,8 +1206,9 @@ fn report_escaping_closure_capture(
         );
 
         let msg = match category {
-            ConstraintCategory::Return => "closure is returned here".to_string(),
-            ConstraintCategory::OpaqueType => "generator is returned here".to_string(),
+            ConstraintCategory::Return | ConstraintCategory::OpaqueType => {
+                format!("{} is returned here", kind)
+            }
             ConstraintCategory::CallArgument => {
                 fr_name.highlight_region_name(&mut err);
                 format!("function requires argument type to outlive `{}`", fr_name)
index e07b8535b9009e0fd153c1a1334d1c52f5bb3376..07822f865d2bd545370d245ec2dc7e41366571e0 100644 (file)
@@ -25,6 +25,7 @@
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
 #![feature(option_expect_none)]
+#![feature(or_patterns)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 808dd833774e42567fd0b7cf078ac96c0221f612..f8bb7e7a85d1117356715ccd170ea256609c6cc0 100644 (file)
@@ -431,6 +431,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
     crate fn cannot_capture_in_long_lived_closure(
         &self,
         closure_span: Span,
+        closure_kind: &str,
         borrowed_path: &str,
         capture_span: Span,
     ) -> DiagnosticBuilder<'cx> {
@@ -438,9 +439,10 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
             self,
             closure_span,
             E0373,
-            "closure may outlive the current function, \
+            "{} may outlive the current function, \
              but it borrows {}, \
              which is owned by the current function",
+            closure_kind,
             borrowed_path,
         );
         err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
index f004b4180ddc9c30fd424f4bfe8b21f66cb76434..605cfdfe747a34412e3635975268d1c66a5b9b43 100644 (file)
@@ -1,12 +1,18 @@
 // edition:2018
 // run-rustfix
 
-fn foo() -> Box<impl std::future::Future<Output = u32>> {
+fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
     let x = 0u32;
     Box::new(async move { x } )
     //~^ ERROR E0373
 }
 
+fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+    async move { *x }
+    //~^ ERROR E0373
+}
+
 fn main() {
-    let _foo = foo();
+    let _ = test_boxed();
+    let _ = test_ref(&0u32);
 }
index 4f35fd52ca39beed26bfb01c5becd7ef41c7e593..ec752c15fa28456aac4bace049dcf18bcee9d1f5 100644 (file)
@@ -1,12 +1,18 @@
 // edition:2018
 // run-rustfix
 
-fn foo() -> Box<impl std::future::Future<Output = u32>> {
+fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
     let x = 0u32;
     Box::new(async { x } )
     //~^ ERROR E0373
 }
 
+fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
+    async { *x }
+    //~^ ERROR E0373
+}
+
 fn main() {
-    let _foo = foo();
+    let _ = test_boxed();
+    let _ = test_ref(&0u32);
 }
index 0eb3971d14a38e8fdd53324a99dc7f7e15d7f16b..193026541d073433629c5f00547375cff6cc1110 100644 (file)
@@ -1,4 +1,4 @@
-error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
+error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
   --> $DIR/async-borrowck-escaping-block-error.rs:6:20
    |
 LL |     Box::new(async { x } )
@@ -7,16 +7,35 @@ LL |     Box::new(async { x } )
    |                    | `x` is borrowed here
    |                    may outlive borrowed value `x`
    |
-note: generator is returned here
-  --> $DIR/async-borrowck-escaping-block-error.rs:4:13
+note: async block is returned here
+  --> $DIR/async-borrowck-escaping-block-error.rs:4:20
    |
-LL | fn foo() -> Box<impl std::future::Future<Output = u32>> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn test_boxed() -> Box<impl std::future::Future<Output = u32>> {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
    |
 LL |     Box::new(async move { x } )
    |                    ^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/async-borrowck-escaping-block-error.rs:11:11
+   |
+LL |     async { *x }
+   |           ^^^-^^
+   |           |  |
+   |           |  `x` is borrowed here
+   |           may outlive borrowed value `x`
+   |
+note: async block is returned here
+  --> $DIR/async-borrowck-escaping-block-error.rs:11:5
+   |
+LL |     async { *x }
+   |     ^^^^^^^^^^^^
+help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |     async move { *x }
+   |           ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0373`.
index d2fa5d0a3d0f189b5507dd4c6c1566f866fbba5c..e667b72aee530616b705ed4354b14c1cacba0a93 100644 (file)
@@ -1,5 +1,5 @@
 // edition:2018
-#![feature(async_closure,async_await)]
+#![feature(async_closure)]
 fn foo() -> Box<dyn std::future::Future<Output = u32>> {
     let x = 0u32;
     Box::new((async || x)())
index 6179132b3f6080e0decb74aebfe80b4a49eb702e..d2a345231eb438687fe02d40b38bc2c9edfca400 100644 (file)
@@ -4,7 +4,7 @@ struct List {
 impl List {
     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
-        //~^ ERROR does not live long enough
+        //~^ ERROR E0373
     }
 }
 
index 9cff4bcd8b579df62d664c6f3b3f9cdc17d0833c..468c2f366299c854df01813094270feba4fa7f1a 100644 (file)
@@ -1,21 +1,21 @@
-error[E0597]: `prefix` does not live long enough
-  --> $DIR/does-not-live-long-enough.rs:6:51
+error[E0373]: closure may outlive the current function, but it borrows `prefix`, which is owned by the current function
+  --> $DIR/does-not-live-long-enough.rs:6:33
    |
-LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
-   |                     -- lifetime `'a` defined here     --------------------------- opaque type requires that `prefix` is borrowed for `'a`
 LL |         self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref())
-   |                                 ---               ^^^^^^ borrowed value does not live long enough
+   |                                 ^^^               ------ `prefix` is borrowed here
    |                                 |
-   |                                 value captured here
-LL |
-LL |     }
-   |     - `prefix` dropped here while still borrowed
+   |                                 may outlive borrowed value `prefix`
+   |
+note: closure is returned here
+  --> $DIR/does-not-live-long-enough.rs:5:55
    |
-help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
+LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> {
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `prefix` (and any other referenced variables), use the `move` keyword
    |
-LL |     fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator<Item=&'a str> + 'a {
-   |                                                                                   ^^^^
+LL |         self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref())
+   |                                 ^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0373`.