Skip to content

Commit 166b13b

Browse files
authored
Rollup merge of rust-lang#65730 - csmoe:return-lifetime, r=nikomatsakis
Suggest to add lifetime constraint at explicit ouput of functions Closes rust-lang#62097
2 parents f1b882b + 9124f7a commit 166b13b

File tree

12 files changed

+103
-29
lines changed

12 files changed

+103
-29
lines changed

src/librustc/hir/lowering.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,16 @@ impl<'a> LoweringContext<'a> {
21702170
impl_trait_return_allow: bool,
21712171
make_ret_async: Option<NodeId>,
21722172
) -> P<hir::FnDecl> {
2173+
debug!("lower_fn_decl(\
2174+
fn_decl: {:?}, \
2175+
in_band_ty_params: {:?}, \
2176+
impl_trait_return_allow: {}, \
2177+
make_ret_async: {:?})",
2178+
decl,
2179+
in_band_ty_params,
2180+
impl_trait_return_allow,
2181+
make_ret_async,
2182+
);
21732183
let lt_mode = if make_ret_async.is_some() {
21742184
// In `async fn`, argument-position elided lifetimes
21752185
// must be transformed into fresh generic parameters so that
@@ -2462,7 +2472,7 @@ impl<'a> LoweringContext<'a> {
24622472

24632473
hir::FunctionRetTy::Return(P(hir::Ty {
24642474
kind: opaque_ty_ref,
2465-
span,
2475+
span: opaque_ty_span,
24662476
hir_id: self.next_id(),
24672477
}))
24682478
}
@@ -2572,7 +2582,7 @@ impl<'a> LoweringContext<'a> {
25722582
hir::Lifetime {
25732583
hir_id: self.lower_node_id(id),
25742584
span,
2575-
name: name,
2585+
name,
25762586
}
25772587
}
25782588

src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4545
///
4646
/// It will later be extended to trait objects.
4747
pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
48-
let (span, sub, sup) = self.get_regions();
48+
let (span, sub, sup) = self.regions();
4949

5050
// Determine whether the sub and sup consist of both anonymous (elided) regions.
5151
let anon_reg_sup = self.tcx().is_suitable_region(sup)?;

src/librustc/infer/error_reporting/nice_region_error/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
7777
.or_else(|| self.try_report_impl_not_conforming_to_trait())
7878
}
7979

80-
pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
80+
pub fn regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
8181
match (&self.error, self.regions) {
8282
(Some(ConcreteFailure(origin, sub, sup)), None) => (origin.span(), sub, sup),
8383
(Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => (origin.span(), sub, sup),

src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
1111
/// When given a `ConcreteFailure` for a function with parameters containing a named region and
1212
/// an anonymous region, emit an descriptive diagnostic error.
1313
pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
14-
let (span, sub, sup) = self.get_regions();
14+
let (span, sub, sup) = self.regions();
1515

1616
debug!(
1717
"try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",

src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
2020
) = error.clone()
2121
{
2222
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
23+
let return_ty = self.tcx().return_type_impl_trait(anon_reg_sup.def_id);
2324
if sub_r == &RegionKind::ReStatic &&
24-
self.tcx().return_type_impl_trait(anon_reg_sup.def_id).is_some()
25+
return_ty.is_some()
2526
{
2627
let sp = var_origin.span();
2728
let return_sp = sub_origin.span();
@@ -52,17 +53,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
5253
}) => name.to_string(),
5354
_ => "'_".to_owned(),
5455
};
55-
if let Ok(snippet) = self.tcx().sess.source_map().span_to_snippet(return_sp) {
56-
err.span_suggestion(
57-
return_sp,
58-
&format!(
59-
"you can add a constraint to the return type to make it last \
56+
let fn_return_span = return_ty.unwrap().1;
57+
if let Ok(snippet) =
58+
self.tcx().sess.source_map().span_to_snippet(fn_return_span) {
59+
// only apply this suggestion onto functions with
60+
// explicit non-desugar'able return.
61+
if fn_return_span.desugaring_kind().is_none() {
62+
err.span_suggestion(
63+
fn_return_span,
64+
&format!(
65+
"you can add a constraint to the return type to make it last \
6066
less than `'static` and match {}",
61-
lifetime,
62-
),
63-
format!("{} + {}", snippet, lifetime_name),
64-
Applicability::Unspecified,
65-
);
67+
lifetime,
68+
),
69+
format!("{} + {}", snippet, lifetime_name),
70+
Applicability::Unspecified,
71+
);
72+
}
6673
}
6774
err.emit();
6875
return Some(ErrorReported);

src/librustc/ty/context.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1529,14 +1529,14 @@ impl<'tcx> TyCtxt<'tcx> {
15291529
return Some(FreeRegionInfo {
15301530
def_id: suitable_region_binding_scope,
15311531
boundregion: bound_region,
1532-
is_impl_item: is_impl_item,
1532+
is_impl_item,
15331533
});
15341534
}
15351535

15361536
pub fn return_type_impl_trait(
15371537
&self,
15381538
scope_def_id: DefId,
1539-
) -> Option<Ty<'tcx>> {
1539+
) -> Option<(Ty<'tcx>, Span)> {
15401540
// HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
15411541
let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap();
15421542
match self.hir().get(hir_id) {
@@ -1557,7 +1557,8 @@ impl<'tcx> TyCtxt<'tcx> {
15571557
let sig = ret_ty.fn_sig(*self);
15581558
let output = self.erase_late_bound_regions(&sig.output());
15591559
if output.is_impl_trait() {
1560-
Some(output)
1560+
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
1561+
Some((output, fn_decl.output.span()))
15611562
} else {
15621563
None
15631564
}

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -715,10 +715,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
715715
if let (Some(f), Some(ty::RegionKind::ReStatic)) =
716716
(self.to_error_region(fr), self.to_error_region(outlived_fr))
717717
{
718-
if let Some(ty::TyS {
718+
if let Some((ty::TyS {
719719
kind: ty::Opaque(did, substs),
720720
..
721-
}) = infcx
721+
}, _)) = infcx
722722
.tcx
723723
.is_suitable_region(f)
724724
.map(|r| r.def_id)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
2+
--> $DIR/issue-62097.rs:13:13
3+
|
4+
LL | foo(|| self.bar()).await;
5+
| ^^ ---- `self` is borrowed here
6+
| |
7+
| may outlive borrowed value `self`
8+
|
9+
note: function requires argument type to outlive `'static`
10+
--> $DIR/issue-62097.rs:13:9
11+
|
12+
LL | foo(|| self.bar()).await;
13+
| ^^^^^^^^^^^^^^^^^^
14+
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
15+
|
16+
LL | foo(move || self.bar()).await;
17+
| ^^^^^^^
18+
19+
error[E0521]: borrowed data escapes outside of function
20+
--> $DIR/issue-62097.rs:13:9
21+
|
22+
LL | pub async fn run_dummy_fn(&self) {
23+
| ----- `self` is a reference that is only valid in the function body
24+
LL | foo(|| self.bar()).await;
25+
| ^^^^^^^^^^^^^^^^^^ `self` escapes the function body here
26+
27+
error: aborting due to 2 previous errors
28+
29+
For more information about this error, try `rustc --explain E0373`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// edition:2018
2+
async fn foo<F>(fun: F)
3+
where
4+
F: FnOnce() + 'static
5+
{
6+
fun()
7+
}
8+
9+
struct Struct;
10+
11+
impl Struct {
12+
pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer
13+
foo(|| self.bar()).await;
14+
}
15+
16+
pub fn bar(&self) {}
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: cannot infer an appropriate lifetime
2+
--> $DIR/issue-62097.rs:12:31
3+
|
4+
LL | pub async fn run_dummy_fn(&self) {
5+
| ^^^^^ ...but this borrow...
6+
LL | foo(|| self.bar()).await;
7+
| --- this return type evaluates to the `'static` lifetime...
8+
|
9+
note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31
10+
--> $DIR/issue-62097.rs:12:31
11+
|
12+
LL | pub async fn run_dummy_fn(&self) {
13+
| ^
14+
15+
error: aborting due to previous error
16+

src/test/ui/async-await/issues/issue-63388-2.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14
2020
|
2121
LL | foo: &dyn Foo, bar: &'a dyn Foo
2222
| ^
23-
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
24-
|
25-
LL | foo + '_
26-
|
2723

2824
error: aborting due to 2 previous errors
2925

src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26
1111
|
1212
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
1313
| ^
14-
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
15-
|
16-
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
17-
| ^^^^^^^^^^^^^^^
1814

1915
error: aborting due to previous error
2016

0 commit comments

Comments
 (0)