Skip to content

Commit 4e90f17

Browse files
committed
When 'static is explicit, suggest constraining argument with it
1 parent 81c9094 commit 4e90f17

16 files changed

+237
-158
lines changed

src/librustc_infer/infer/error_reporting/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,8 +2035,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20352035
self.tcx.sess,
20362036
var_origin.span(),
20372037
E0495,
2038-
"cannot infer an appropriate lifetime{} \
2039-
due to conflicting requirements",
2038+
"cannot infer an appropriate lifetime{} due to conflicting requirements",
20402039
var_description
20412040
)
20422041
}

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

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_middle::ty::RegionKind;
1010
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
1111
/// Print the error message for lifetime errors when the return type is a static impl Trait.
1212
pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
13+
debug!("try_report_static_impl_trait(error={:?})", self.error);
1314
if let Some(ref error) = self.error {
1415
if let RegionResolutionError::SubSupConflict(
1516
_,
@@ -18,19 +19,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
1819
sub_r,
1920
sup_origin,
2021
sup_r,
21-
) = error.clone()
22+
) = error
2223
{
24+
debug!(
25+
"try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
26+
var_origin, sub_origin, sub_r, sup_origin, sup_r
27+
);
2328
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
29+
debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
2430
let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
25-
let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..));
26-
let fn_return_span = fn_return.span;
27-
if sub_r == &RegionKind::ReStatic {
31+
debug!("try_report_static_impl_trait: fn_return={:?}", fn_return);
32+
if **sub_r == RegionKind::ReStatic {
2833
let sp = var_origin.span();
2934
let return_sp = sub_origin.span();
35+
let param_info = self.find_param_with_region(sup_r, sub_r)?;
3036
let mut err =
3137
self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime");
32-
let param_info = self.find_param_with_region(sup_r, sub_r)?;
3338
err.span_label(param_info.param_ty_span, "data with this lifetime...");
39+
debug!("try_report_static_impl_trait: param_info={:?}", param_info);
3440

3541
// We try to make the output have fewer overlapping spans if possible.
3642
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
@@ -60,14 +66,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
6066
if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
6167
// only apply this suggestion onto functions with
6268
// explicit non-desugar'able return.
63-
if fn_return_span.desugaring_kind().is_none() {
64-
let msg = format!(
65-
"to permit non-static references in {} `{} Trait` value, you can add \
66-
an explicit bound for {}",
67-
if is_dyn { "a" } else { "an" },
68-
if is_dyn { "dyn" } else { "impl" },
69-
lifetime,
70-
);
69+
if fn_return.span.desugaring_kind().is_none() {
7170
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
7271
match fn_return.kind {
7372
TyKind::Def(item_id, _) => {
@@ -78,46 +77,80 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
7877
err.emit();
7978
return Some(ErrorReported);
8079
};
81-
let (span, sugg) = opaque
80+
81+
if let Some(span) = opaque
8282
.bounds
8383
.iter()
8484
.filter_map(|arg| match arg {
8585
GenericBound::Outlives(Lifetime {
8686
name: LifetimeName::Static,
8787
span,
8888
..
89-
}) => Some((*span, lifetime_name.clone())),
89+
}) => Some(*span),
9090
_ => None,
9191
})
9292
.next()
93-
.unwrap_or_else(|| {
94-
(
95-
fn_return_span.shrink_to_hi(),
96-
format!(" + {}", lifetime_name),
97-
)
98-
});
99-
100-
err.span_suggestion_verbose(
101-
span,
102-
&msg,
103-
sugg,
104-
Applicability::MaybeIncorrect,
105-
);
106-
}
107-
TyKind::TraitObject(_, lt) => {
108-
let (span, sugg) = match lt.name {
109-
LifetimeName::ImplicitObjectLifetimeDefault => (
110-
fn_return_span.shrink_to_hi(),
93+
{
94+
err.span_suggestion_verbose(
95+
span,
96+
"consider changing the `impl Trait`'s explicit \
97+
`'static` bound",
98+
lifetime_name,
99+
Applicability::MaybeIncorrect,
100+
);
101+
err.span_suggestion_verbose(
102+
param_info.param_ty_span,
103+
"alternatively, set an explicit `'static` lifetime to \
104+
this parameter",
105+
param_info.param_ty.to_string(),
106+
Applicability::MaybeIncorrect,
107+
);
108+
} else {
109+
err.span_suggestion_verbose(
110+
fn_return.span.shrink_to_hi(),
111+
&format!(
112+
"to permit non-static references in an `impl Trait` \
113+
value, you can add an explicit bound for {}",
114+
lifetime,
115+
),
111116
format!(" + {}", lifetime_name),
112-
),
113-
_ => (lt.span, lifetime_name),
117+
Applicability::MaybeIncorrect,
118+
);
114119
};
115-
err.span_suggestion_verbose(
116-
span,
117-
&msg,
118-
sugg,
119-
Applicability::MaybeIncorrect,
120-
);
120+
}
121+
TyKind::TraitObject(_, lt) => {
122+
match lt.name {
123+
LifetimeName::ImplicitObjectLifetimeDefault => {
124+
err.span_suggestion_verbose(
125+
fn_return.span.shrink_to_hi(),
126+
&format!(
127+
"to permit non-static references in a trait object \
128+
value, you can add an explicit bound for {}",
129+
lifetime,
130+
),
131+
format!(" + {}", lifetime_name),
132+
Applicability::MaybeIncorrect,
133+
);
134+
}
135+
_ => {
136+
err.span_suggestion_verbose(
137+
lt.span,
138+
"consider changing the trait object's explicit \
139+
`'static` bound",
140+
lifetime_name,
141+
Applicability::MaybeIncorrect,
142+
);
143+
err.span_suggestion_verbose(
144+
param_info.param_ty_span,
145+
&format!(
146+
"alternatively, set an explicit `'static` lifetime \
147+
in this parameter",
148+
),
149+
param_info.param_ty.to_string(),
150+
Applicability::MaybeIncorrect,
151+
);
152+
}
153+
}
121154
}
122155
_ => {}
123156
}

src/librustc_middle/ty/diagnostics.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,10 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
247247
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
248248
if let hir::TyKind::TraitObject(
249249
_,
250-
hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
250+
hir::Lifetime {
251+
name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
252+
..
253+
},
251254
) = ty.kind
252255
{
253256
self.0.push(ty);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
2222
//~^ ERROR cannot infer an appropriate lifetime
2323

2424
fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
25-
//~^ ERROR explicit lifetime required in the type of `x`
25+
//~^ ERROR cannot infer an appropriate lifetime
2626

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

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

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
3535
| | ...is required to be `'static` by this...
3636
| data with this lifetime...
3737
|
38-
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1
38+
help: consider changing the `impl Trait`'s explicit `'static` bound
3939
|
4040
LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
4141
| ^^
42+
help: alternatively, set an explicit `'static` lifetime to this parameter
43+
|
44+
LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
45+
| ^^^^^^^^^^^^
4246

4347
error: cannot infer an appropriate lifetime
4448
--> $DIR/must_outlive_least_region_or_bound.rs:12:55
@@ -49,10 +53,14 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
4953
| | ...is required to be `'static` by this...
5054
| data with this lifetime...
5155
|
52-
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14
56+
help: consider changing the `impl Trait`'s explicit `'static` bound
5357
|
5458
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
5559
| ^^
60+
help: alternatively, set an explicit `'static` lifetime to this parameter
61+
|
62+
LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
63+
| ^^^^^^^^^^^^
5664

5765
error[E0621]: explicit lifetime required in the type of `x`
5866
--> $DIR/must_outlive_least_region_or_bound.rs:15:24
@@ -71,10 +79,14 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
7179
| | ...is required to be `'static` by this...
7280
| data with this lifetime...
7381
|
74-
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15
82+
help: consider changing the `impl Trait`'s explicit `'static` bound
7583
|
7684
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
7785
| ^^
86+
help: alternatively, set an explicit `'static` lifetime to this parameter
87+
|
88+
LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
89+
| ^^^^^^^^^^^^
7890

7991
error[E0623]: lifetime mismatch
8092
--> $DIR/must_outlive_least_region_or_bound.rs:38:61
@@ -103,7 +115,7 @@ LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
103115
| | ...is required to be `'static` by this...
104116
| data with this lifetime...
105117
|
106-
help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
118+
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
107119
|
108120
LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
109121
| ^^^^
@@ -118,47 +130,48 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
118130
| | ...is required to be `'static` by this...
119131
| data with this lifetime...
120132
|
121-
help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
133+
help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
122134
|
123135
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
124136
| ^^^^
125137

126-
error[E0621]: explicit lifetime required in the type of `x`
127-
--> $DIR/must_outlive_least_region_or_bound.rs:24:51
138+
error: cannot infer an appropriate lifetime
139+
--> $DIR/must_outlive_least_region_or_bound.rs:24:60
128140
|
129141
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
130-
| ---- ^^^^^^^^^^^ lifetime `'static` required
131-
| |
132-
| help: add explicit lifetime `'static` to the type of `x`: `&'static i32`
133-
134-
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
135-
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
142+
| ---- ---------^-
143+
| | | |
144+
| | | ...and is captured here
145+
| data with this lifetime... ...is required to be `'static` by this...
136146
|
137-
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
138-
| ^
147+
help: consider changing the trait object's explicit `'static` bound
139148
|
140-
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14...
141-
--> $DIR/must_outlive_least_region_or_bound.rs:27:14
149+
LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
150+
| ^^
151+
help: alternatively, set an explicit `'static` lifetime in this parameter
142152
|
143-
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
144-
| ^^
145-
note: ...so that the expression is assignable
153+
LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
154+
| ^^^^^^^^^^^^
155+
156+
error: cannot infer an appropriate lifetime
146157
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
147158
|
148159
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
149-
| ^
150-
= note: expected `&i32`
151-
found `&'a i32`
152-
= note: but, the lifetime must be valid for the static lifetime...
153-
note: ...so that the expression is assignable
154-
--> $DIR/must_outlive_least_region_or_bound.rs:27:60
160+
| ------- ---------^-
161+
| | | |
162+
| | | ...and is captured here
163+
| data with this lifetime... ...is required to be `'static` by this...
155164
|
156-
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
157-
| ^^^^^^^^^^^
158-
= note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>`
159-
found `std::boxed::Box<dyn std::fmt::Debug>`
165+
help: consider changing the trait object's explicit `'static` bound
166+
|
167+
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
168+
| ^^
169+
help: alternatively, set an explicit `'static` lifetime in this parameter
170+
|
171+
LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
172+
| ^^^^^^^^^^^^
160173

161174
error: aborting due to 12 previous errors
162175

163-
Some errors have detailed explanations: E0310, E0495, E0621, E0623.
176+
Some errors have detailed explanations: E0310, E0621, E0623.
164177
For more information about an error, try `rustc --explain E0310`.

src/test/ui/issues/issue-16922.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | Box::new(value) as Box<dyn Any>
99
| | ...and is captured here
1010
| ...is required to be `'static` by this...
1111
|
12-
help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
12+
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
1313
|
1414
LL | fn foo<T: Any>(value: &T) -> Box<dyn Any + '_> {
1515
| ^^^^

src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
77
LL | ss.r
88
| ^^^^ ...is captured and required to be `'static` here
99
|
10-
help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
10+
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
1111
|
1212
LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> {
1313
| ^^^^

0 commit comments

Comments
 (0)