Skip to content

Commit c511055

Browse files
committed
Further tweak wording of E0759 and introduce E0767
1 parent 2c9c80e commit c511055

File tree

43 files changed

+280
-167
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+280
-167
lines changed

src/librustc_error_codes/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -628,4 +628,5 @@ E0766: include_str!("./error_codes/E0766.md"),
628628
E0755, // `#[ffi_pure]` is only allowed on foreign functions
629629
E0756, // `#[ffi_const]` is only allowed on foreign functions
630630
E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
631+
E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
631632
}

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

+78-29
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,31 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4545
let mut err = struct_span_err!(
4646
tcx.sess,
4747
cause.span,
48-
E0759,
49-
"cannot infer an appropriate lifetime"
48+
E0767,
49+
"{} has {} but calling `{}` introduces an implicit `'static` lifetime \
50+
requirement",
51+
param
52+
.param
53+
.pat
54+
.simple_ident()
55+
.map(|s| format!("`{}`", s))
56+
.unwrap_or_else(|| "`fn` parameter".to_string()),
57+
lifetime,
58+
assoc.ident,
5059
);
5160
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
5261
err.span_label(
5362
cause.span,
54-
"...is captured and required to live as long as `'static` here",
63+
&format!(
64+
"...is captured and required to live as long as `'static` here \
65+
because of an implicit lifetime bound on the {}",
66+
match assoc.container {
67+
AssocItemContainer::TraitContainer(id) =>
68+
format!("`impl` of `{}`", tcx.def_path_str(id)),
69+
AssocItemContainer::ImplContainer(_) =>
70+
"inherent `impl`".to_string(),
71+
},
72+
),
5573
);
5674
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc) {
5775
err.emit();
@@ -78,10 +96,49 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
7896
} else {
7997
("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
8098
};
81-
let mut err = struct_span_err!(tcx.sess, sp, E0759, "cannot infer an appropriate lifetime");
99+
let param_name = param
100+
.param
101+
.pat
102+
.simple_ident()
103+
.map(|s| format!("`{}`", s))
104+
.unwrap_or_else(|| "`fn` parameter".to_string());
105+
let mut err = struct_span_err!(
106+
tcx.sess,
107+
sp,
108+
E0759,
109+
"{} has {} but it needs to satisfy a `'static` lifetime requirement",
110+
param_name,
111+
lifetime,
112+
);
82113
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
83114
debug!("try_report_static_impl_trait: param_info={:?}", param);
84115

116+
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
117+
118+
let mut postfix = String::new();
119+
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
120+
if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
121+
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc)
122+
&& fn_returns.is_empty()
123+
{
124+
err.code(rustc_errors::error_code!(E0767));
125+
err.set_primary_message(&format!(
126+
"{} has {} but calling `{}` introduces an implicit `'static` lifetime \
127+
requirement",
128+
param_name, lifetime, assoc.ident,
129+
));
130+
postfix = format!(
131+
" because of an implicit lifetime on the {}",
132+
match assoc.container {
133+
AssocItemContainer::TraitContainer(id) =>
134+
format!("`impl` of `{}`", tcx.def_path_str(id)),
135+
AssocItemContainer::ImplContainer(_) => "inherent `impl`".to_string(),
136+
},
137+
);
138+
}
139+
}
140+
}
141+
85142
// We try to make the output have fewer overlapping spans if possible.
86143
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
87144
&& sup_origin.span() != return_sp
@@ -108,36 +165,35 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
108165
// | ---- ^
109166
err.span_label(
110167
sup_origin.span(),
111-
"...is captured here, requiring it to live as long as `'static`",
168+
&format!(
169+
"...is captured here, requiring it to live as long as `'static`{}",
170+
postfix
171+
),
112172
);
113173
} else {
114174
err.span_label(sup_origin.span(), "...is captured here...");
115175
if return_sp < sup_origin.span() {
116176
err.span_note(
117177
return_sp,
118-
"...and is required to live as long as `'static` here",
178+
&format!("...and is required to live as long as `'static` here{}", postfix),
119179
);
120180
} else {
121181
err.span_label(
122182
return_sp,
123-
"...and is required to live as long as `'static` here",
183+
&format!("...and is required to live as long as `'static` here{}", postfix),
124184
);
125185
}
126186
}
127187
} else {
128188
err.span_label(
129189
return_sp,
130-
"...is captured and required to live as long as `'static` here",
190+
&format!(
191+
"...is captured and required to live as long as `'static` here{}",
192+
postfix
193+
),
131194
);
132195
}
133196

134-
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
135-
if let ObligationCauseCode::UnifyReceiver(assoc) = &cause.code {
136-
self.find_impl_on_dyn_trait(&mut err, param.param_ty, assoc);
137-
}
138-
}
139-
140-
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
141197
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
142198
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
143199
let consider = "consider changing the";
@@ -295,20 +351,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
295351
let mut multi_span: MultiSpan = vec![*span].into();
296352
multi_span.push_span_label(
297353
*span,
298-
"this trait object has an implicit `'static` lifetime requirement"
299-
.to_string(),
354+
"this has an implicit `'static` lifetime requirement".to_string(),
300355
);
301356
multi_span.push_span_label(
302357
assoc.ident.span,
303-
"the `'static` requirement is introduced when calling this method"
358+
"`'static` requirement is introduced when calling this method"
304359
.to_string(),
305360
);
306361
err.span_note(
307362
multi_span,
308363
&format!(
309-
"when using method `{}` on `{}`, an implicit `'static` \
310-
requirement is introduced",
311-
assoc.ident,
364+
"`{}`'s inherent `impl` has a `'static` requirement",
312365
tcx.def_path_str(*found_did),
313366
),
314367
);
@@ -363,22 +416,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
363416
let mut multi_span: MultiSpan = vec![*span].into();
364417
multi_span.push_span_label(
365418
*span,
366-
"this trait object has an implicit `'static` lifetime requirement"
367-
.to_string(),
419+
"this has an implicit `'static` lifetime requirement".to_string(),
368420
);
369421
multi_span.push_span_label(
370422
method.span,
371-
"the `'static` requirement is introduced when calling this method"
372-
.to_string(),
423+
"`'static` requirement is introduced when calling this method".to_string(),
373424
);
374425
err.span_note(
375426
multi_span,
376427
&format!(
377-
"when using method `{}` of trait `{}` on `{}`, an implicit `'static` \
378-
requirement is introduced",
379-
method,
380-
tcx.def_path_str(container_id),
428+
"`{}`'s `impl` of `{}` has an implicit `'static` requirement",
381429
tcx.def_path_str(*found_did),
430+
tcx.def_path_str(container_id),
382431
),
383432
);
384433
err.span_suggestion_verbose(

src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0759]: cannot infer an appropriate lifetime
1+
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
22
--> $DIR/project-fn-ret-contravariant.rs:38:8
33
|
44
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {

src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0759]: cannot infer an appropriate lifetime
1+
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
22
--> $DIR/project-fn-ret-invariant.rs:49:9
33
|
44
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {

src/test/ui/async-await/issues/issue-62097.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ where
99
struct Struct;
1010

1111
impl Struct {
12-
pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer
12+
pub async fn run_dummy_fn(&self) { //~ ERROR E0759
1313
foo(|| self.bar()).await;
1414
}
1515

src/test/ui/async-await/issues/issue-62097.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0759]: cannot infer an appropriate lifetime
1+
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
22
--> $DIR/issue-62097.rs:12:31
33
|
44
LL | pub async fn run_dummy_fn(&self) {

src/test/ui/impl-header-lifetime-elision/dyn-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn static_val<T: StaticTrait>(_: T) {
1717
}
1818

1919
fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
20-
static_val(x); //~ ERROR cannot infer
20+
static_val(x); //~ ERROR E0759
2121
}
2222

2323
fn not_static_val<T: NotStaticTrait>(_: T) {

src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0759]: cannot infer an appropriate lifetime
1+
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
22
--> $DIR/dyn-trait.rs:20:16
33
|
44
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {

src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
1212
| ^^^^^^^^^^^^^^
1313

1414
error: lifetime may not live long enough
15-
--> $DIR/must_outlive_least_region_or_bound.rs:6:32
15+
--> $DIR/must_outlive_least_region_or_bound.rs:5:32
1616
|
1717
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
1818
| -- ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
@@ -26,7 +26,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
2626
| ^^^^^^^^^^^^^^
2727

2828
error: lifetime may not live long enough
29-
--> $DIR/must_outlive_least_region_or_bound.rs:9:46
29+
--> $DIR/must_outlive_least_region_or_bound.rs:7:46
3030
|
3131
LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
3232
| - ^ returning this value requires that `'1` must outlive `'static`
@@ -36,7 +36,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
3636
= help: consider replacing `'1` with `'static`
3737

3838
error: lifetime may not live long enough
39-
--> $DIR/must_outlive_least_region_or_bound.rs:12:55
39+
--> $DIR/must_outlive_least_region_or_bound.rs:9:55
4040
|
4141
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
4242
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
@@ -45,23 +45,23 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
4545
= help: consider replacing `'a` with `'static`
4646

4747
error[E0621]: explicit lifetime required in the type of `x`
48-
--> $DIR/must_outlive_least_region_or_bound.rs:15:41
48+
--> $DIR/must_outlive_least_region_or_bound.rs:11:41
4949
|
5050
LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
5151
| ---- ^ lifetime `'a` required
5252
| |
5353
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
5454

5555
error: lifetime may not live long enough
56-
--> $DIR/must_outlive_least_region_or_bound.rs:30:24
56+
--> $DIR/must_outlive_least_region_or_bound.rs:22:24
5757
|
5858
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
5959
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
6060
| |
6161
| let's call the lifetime of this reference `'1`
6262

6363
error: lifetime may not live long enough
64-
--> $DIR/must_outlive_least_region_or_bound.rs:37:69
64+
--> $DIR/must_outlive_least_region_or_bound.rs:28:69
6565
|
6666
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
6767
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
@@ -70,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
7070
= help: consider replacing `'a` with `'static`
7171

7272
error: lifetime may not live long enough
73-
--> $DIR/must_outlive_least_region_or_bound.rs:42:61
73+
--> $DIR/must_outlive_least_region_or_bound.rs:32:61
7474
|
7575
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
7676
| -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
@@ -80,7 +80,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
8080
= help: consider adding the following bound: `'b: 'a`
8181

8282
error[E0310]: the parameter type `T` may not live long enough
83-
--> $DIR/must_outlive_least_region_or_bound.rs:47:51
83+
--> $DIR/must_outlive_least_region_or_bound.rs:37:51
8484
|
8585
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
8686
| ^^^^^^^^^^^^^^^^^^^^

src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs

+11-21
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,31 @@
11
use std::fmt::Debug;
22

3-
fn elided(x: &i32) -> impl Copy { x }
4-
//~^ ERROR cannot infer an appropriate lifetime
3+
fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759
54

6-
fn explicit<'a>(x: &'a i32) -> impl Copy { x }
7-
//~^ ERROR cannot infer an appropriate lifetime
5+
fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759
86

9-
fn elided2(x: &i32) -> impl Copy + 'static { x }
10-
//~^ ERROR cannot infer an appropriate lifetime
7+
fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759
118

12-
fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
13-
//~^ ERROR cannot infer an appropriate lifetime
9+
fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } //~ ERROR E0759
1410

1511
fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
1612
//~^ ERROR explicit lifetime required in the type of `x`
1713

18-
fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
19-
//~^ ERROR cannot infer an appropriate lifetime
14+
fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } //~ ERROR E0759
2015

21-
fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
22-
//~^ ERROR cannot infer an appropriate lifetime
16+
fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } //~ ERROR E0759
2317

24-
fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
25-
//~^ ERROR cannot infer an appropriate lifetime
18+
fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
2619

27-
fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
28-
//~^ ERROR cannot infer an appropriate lifetime
20+
fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
2921

30-
fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
31-
//~^ ERROR cannot infer an appropriate lifetime
32-
//~| ERROR cannot infer an appropriate lifetime
22+
fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~ ERROR E0759
23+
//~^ ERROR E0759
3324

3425
trait LifetimeTrait<'a> {}
3526
impl<'a> LifetimeTrait<'a> for &'a i32 {}
3627

37-
fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
38-
//~^ ERROR cannot infer an appropriate lifetime
28+
fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERROR E0759
3929

4030
// Tests that a closure type containing 'b cannot be returned from a type where
4131
// only 'a was expected.

0 commit comments

Comments
 (0)