about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-11-21 15:29:02 +0100
committerGitHub <noreply@github.com>2019-11-21 15:29:02 +0100
commite4a634189e3ef7461a40e357633bdbc98cedf5ad (patch)
tree3916d5aff87711cd1566c067d259190dbe70b1cb
parent0828d5327b9950ef4b1fedd058bbc8eaed00f8be (diff)
parent9124f7a096007b5f96300e61e8f5817df10b315a (diff)
downloadrust-e4a634189e3ef7461a40e357633bdbc98cedf5ad.tar.gz
rust-e4a634189e3ef7461a40e357633bdbc98cedf5ad.zip
Rollup merge of #65730 - csmoe:return-lifetime, r=nikomatsakis
Suggest to add lifetime constraint at explicit ouput of functions

Closes #62097
-rw-r--r--src/librustc/hir/lowering.rs14
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs29
-rw-r--r--src/librustc/ty/context.rs7
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs4
-rw-r--r--src/test/ui/async-await/issues/issue-62097.nll.stderr29
-rw-r--r--src/test/ui/async-await/issues/issue-62097.rs19
-rw-r--r--src/test/ui/async-await/issues/issue-62097.stderr16
-rw-r--r--src/test/ui/async-await/issues/issue-63388-2.stderr4
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr4
12 files changed, 103 insertions, 29 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 06a7a6bb301..ac8173f101a 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2170,6 +2170,16 @@ impl<'a> LoweringContext<'a> {
         impl_trait_return_allow: bool,
         make_ret_async: Option<NodeId>,
     ) -> P<hir::FnDecl> {
+        debug!("lower_fn_decl(\
+            fn_decl: {:?}, \
+            in_band_ty_params: {:?}, \
+            impl_trait_return_allow: {}, \
+            make_ret_async: {:?})",
+            decl,
+            in_band_ty_params,
+            impl_trait_return_allow,
+            make_ret_async,
+        );
         let lt_mode = if make_ret_async.is_some() {
             // In `async fn`, argument-position elided lifetimes
             // must be transformed into fresh generic parameters so that
@@ -2462,7 +2472,7 @@ impl<'a> LoweringContext<'a> {
 
         hir::FunctionRetTy::Return(P(hir::Ty {
             kind: opaque_ty_ref,
-            span,
+            span: opaque_ty_span,
             hir_id: self.next_id(),
         }))
     }
@@ -2572,7 +2582,7 @@ impl<'a> LoweringContext<'a> {
         hir::Lifetime {
             hir_id: self.lower_node_id(id),
             span,
-            name: name,
+            name,
         }
     }
 
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index d7cba87e6b1..a431b541fa4 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -45,7 +45,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     ///
     /// It will later be extended to trait objects.
     pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
-        let (span, sub, sup) = self.get_regions();
+        let (span, sub, sup) = self.regions();
 
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
         let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
index cd003aa8dab..09cfbf850a5 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs
@@ -77,7 +77,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
             .or_else(|| self.try_report_impl_not_conforming_to_trait())
     }
 
-    pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
+    pub fn regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
         match (&self.error, self.regions) {
             (Some(ConcreteFailure(origin, sub, sup)), None) => (origin.span(), sub, sup),
             (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => (origin.span(), sub, sup),
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 36131849191..0abdeb71993 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -11,7 +11,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// When given a `ConcreteFailure` for a function with parameters containing a named region and
     /// an anonymous region, emit an descriptive diagnostic error.
     pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
-        let (span, sub, sup) = self.get_regions();
+        let (span, sub, sup) = self.regions();
 
         debug!(
             "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 9d405d4ea40..01ba748c4e1 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -20,8 +20,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 ) = error.clone()
             {
                 let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
+                let return_ty = self.tcx().return_type_impl_trait(anon_reg_sup.def_id);
                 if sub_r == &RegionKind::ReStatic &&
-                    self.tcx().return_type_impl_trait(anon_reg_sup.def_id).is_some()
+                    return_ty.is_some()
                 {
                     let sp = var_origin.span();
                     let return_sp = sub_origin.span();
@@ -52,17 +53,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                         }) => name.to_string(),
                         _ => "'_".to_owned(),
                     };
-                    if let Ok(snippet) = self.tcx().sess.source_map().span_to_snippet(return_sp) {
-                        err.span_suggestion(
-                            return_sp,
-                            &format!(
-                                "you can add a constraint to the return type to make it last \
+                    let fn_return_span = return_ty.unwrap().1;
+                    if let Ok(snippet) =
+                        self.tcx().sess.source_map().span_to_snippet(fn_return_span) {
+                        // only apply this suggestion onto functions with
+                        // explicit non-desugar'able return.
+                        if fn_return_span.desugaring_kind().is_none() {
+                            err.span_suggestion(
+                                fn_return_span,
+                                &format!(
+                                    "you can add a constraint to the return type to make it last \
                                  less than `'static` and match {}",
-                                lifetime,
-                            ),
-                            format!("{} + {}", snippet, lifetime_name),
-                            Applicability::Unspecified,
-                        );
+                                 lifetime,
+                                ),
+                                format!("{} + {}", snippet, lifetime_name),
+                                Applicability::Unspecified,
+                            );
+                        }
                     }
                     err.emit();
                     return Some(ErrorReported);
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d0767a1fc4c..95456581169 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1529,14 +1529,14 @@ impl<'tcx> TyCtxt<'tcx> {
         return Some(FreeRegionInfo {
             def_id: suitable_region_binding_scope,
             boundregion: bound_region,
-            is_impl_item: is_impl_item,
+            is_impl_item,
         });
     }
 
     pub fn return_type_impl_trait(
         &self,
         scope_def_id: DefId,
-    ) -> Option<Ty<'tcx>> {
+    ) -> Option<(Ty<'tcx>, Span)> {
         // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
         let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap();
         match self.hir().get(hir_id) {
@@ -1557,7 +1557,8 @@ impl<'tcx> TyCtxt<'tcx> {
                 let sig = ret_ty.fn_sig(*self);
                 let output = self.erase_late_bound_regions(&sig.output());
                 if output.is_impl_trait() {
-                    Some(output)
+                    let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
+                    Some((output, fn_decl.output.span()))
                 } else {
                     None
                 }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 26b288cb4b2..e6795dbfd44 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -715,10 +715,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         if let (Some(f), Some(ty::RegionKind::ReStatic)) =
             (self.to_error_region(fr), self.to_error_region(outlived_fr))
         {
-            if let Some(ty::TyS {
+            if let Some((ty::TyS {
                 kind: ty::Opaque(did, substs),
                 ..
-            }) = infcx
+            }, _)) = infcx
                 .tcx
                 .is_suitable_region(f)
                 .map(|r| r.def_id)
diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr
new file mode 100644
index 00000000000..0c64f90cb9f
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-62097.nll.stderr
@@ -0,0 +1,29 @@
+error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
+  --> $DIR/issue-62097.rs:13:13
+   |
+LL |         foo(|| self.bar()).await;
+   |             ^^ ---- `self` is borrowed here
+   |             |
+   |             may outlive borrowed value `self`
+   |
+note: function requires argument type to outlive `'static`
+  --> $DIR/issue-62097.rs:13:9
+   |
+LL |         foo(|| self.bar()).await;
+   |         ^^^^^^^^^^^^^^^^^^
+help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
+   |
+LL |         foo(move || self.bar()).await;
+   |             ^^^^^^^
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/issue-62097.rs:13:9
+   |
+LL |     pub async fn run_dummy_fn(&self) {
+   |                               ----- `self` is a reference that is only valid in the function body
+LL |         foo(|| self.bar()).await;
+   |         ^^^^^^^^^^^^^^^^^^ `self` escapes the function body here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/src/test/ui/async-await/issues/issue-62097.rs b/src/test/ui/async-await/issues/issue-62097.rs
new file mode 100644
index 00000000000..ea482d3667e
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-62097.rs
@@ -0,0 +1,19 @@
+// edition:2018
+async fn foo<F>(fun: F)
+where
+    F: FnOnce() + 'static
+{
+    fun()
+}
+
+struct Struct;
+
+impl Struct {
+    pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer
+        foo(|| self.bar()).await;
+    }
+
+    pub fn bar(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
new file mode 100644
index 00000000000..94afccc06a9
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -0,0 +1,16 @@
+error: cannot infer an appropriate lifetime
+  --> $DIR/issue-62097.rs:12:31
+   |
+LL |     pub async fn run_dummy_fn(&self) {
+   |                               ^^^^^ ...but this borrow...
+LL |         foo(|| self.bar()).await;
+   |         --- this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31
+  --> $DIR/issue-62097.rs:12:31
+   |
+LL |     pub async fn run_dummy_fn(&self) {
+   |                               ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr
index efec160588f..7e45d588c6c 100644
--- a/src/test/ui/async-await/issues/issue-63388-2.stderr
+++ b/src/test/ui/async-await/issues/issue-63388-2.stderr
@@ -20,10 +20,6 @@ note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14
    |
 LL |         foo: &dyn Foo, bar: &'a dyn Foo
    |              ^
-help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 11:14
-   |
-LL |         foo + '_
-   |
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index bce1900ca60..91075ffbdb6 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -11,10 +11,6 @@ note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
    |                          ^
-help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 8:26
-   |
-LL |     async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
-   |                                     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error