Skip to content

Commit f63ab6c

Browse files
committed
Auto merge of #87628 - estebank:unmet-explicit-lifetime-bound, r=oli-obk
Point at unmet explicit lifetime obligation bound r? `@oli-obk` Split off of #85799.
2 parents e3b1c12 + e5d42af commit f63ab6c

24 files changed

+238
-55
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,17 @@ pub(super) fn note_and_explain_region(
8989
prefix: &str,
9090
region: ty::Region<'tcx>,
9191
suffix: &str,
92+
alt_span: Option<Span>,
9293
) {
9394
let (description, span) = match *region {
9495
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
95-
msg_span_from_free_region(tcx, region)
96+
msg_span_from_free_region(tcx, region, alt_span)
9697
}
9798

98-
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), None),
99+
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), alt_span),
99100

100101
// uh oh, hope no user ever sees THIS
101-
ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
102+
ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), alt_span),
102103

103104
ty::RePlaceholder(_) => return,
104105

@@ -108,7 +109,7 @@ pub(super) fn note_and_explain_region(
108109
// We shouldn't really be having unification failures with ReVar
109110
// and ReLateBound though.
110111
ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
111-
(format!("lifetime {:?}", region), None)
112+
(format!("lifetime {:?}", region), alt_span)
112113
}
113114
};
114115

@@ -122,22 +123,23 @@ pub(super) fn note_and_explain_free_region(
122123
region: ty::Region<'tcx>,
123124
suffix: &str,
124125
) {
125-
let (description, span) = msg_span_from_free_region(tcx, region);
126+
let (description, span) = msg_span_from_free_region(tcx, region, None);
126127

127128
emit_msg_span(err, prefix, description, span, suffix);
128129
}
129130

130131
fn msg_span_from_free_region(
131132
tcx: TyCtxt<'tcx>,
132133
region: ty::Region<'tcx>,
134+
alt_span: Option<Span>,
133135
) -> (String, Option<Span>) {
134136
match *region {
135137
ty::ReEarlyBound(_) | ty::ReFree(_) => {
136138
msg_span_from_early_bound_and_free_regions(tcx, region)
137139
}
138-
ty::ReStatic => ("the static lifetime".to_owned(), None),
139-
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), None),
140-
ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), None),
140+
ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
141+
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), alt_span),
142+
ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), alt_span),
141143
_ => bug!("{:?}", region),
142144
}
143145
}
@@ -319,6 +321,7 @@ pub fn unexpected_hidden_region_diagnostic(
319321
&format!("hidden type `{}` captures ", hidden_ty),
320322
hidden_region,
321323
"",
324+
None,
322325
);
323326
}
324327
}
@@ -2303,8 +2306,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
23032306
&format!("{} must be valid for ", labeled_user_string),
23042307
sub,
23052308
"...",
2309+
None,
23062310
);
2307-
if let Some(infer::RelateParamBound(_, t)) = origin {
2311+
if let Some(infer::RelateParamBound(_, t, _)) = origin {
23082312
let return_impl_trait = self
23092313
.in_progress_typeck_results
23102314
.map(|typeck_results| typeck_results.borrow().hir_owner)
@@ -2350,6 +2354,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
23502354
"first, the lifetime cannot outlive ",
23512355
sup_region,
23522356
"...",
2357+
None,
23532358
);
23542359

23552360
debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
@@ -2376,6 +2381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
23762381
"...but the lifetime must also be valid for ",
23772382
sub_region,
23782383
"...",
2384+
None,
23792385
);
23802386
err.span_note(
23812387
sup_trace.cause.span,
@@ -2397,6 +2403,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
23972403
"but, the lifetime must be valid for ",
23982404
sub_region,
23992405
"...",
2406+
None,
24002407
);
24012408

24022409
self.note_region_origin(&mut err, &sub_origin);

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4343
multi_span
4444
.push_span_label(binding_span, "introduces a `'static` lifetime requirement".into());
4545
err.span_note(multi_span, "because this has an unmet lifetime requirement");
46-
note_and_explain_region(self.tcx(), &mut err, "", sup, "...");
46+
note_and_explain_region(self.tcx(), &mut err, "", sup, "...", Some(binding_span));
4747
if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
4848
// If an impl is local, then maybe this isn't what they want. Try to
4949
// be as helpful as possible with implicit lifetimes.

compiler/rustc_infer/src/infer/error_reporting/note.rs

+69-13
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
7474
),
7575
);
7676
}
77-
infer::RelateParamBound(span, t) => {
77+
infer::RelateParamBound(span, t, opt_span) => {
7878
label_or_note(
7979
span,
8080
&format!(
81-
"...so that the type `{}` will meet its required lifetime bounds",
82-
self.ty_to_string(t)
81+
"...so that the type `{}` will meet its required lifetime bounds{}",
82+
self.ty_to_string(t),
83+
if opt_span.is_some() { "..." } else { "" },
8384
),
8485
);
86+
if let Some(span) = opt_span {
87+
err.span_note(span, "...that is required by this bound");
88+
}
8589
}
8690
infer::RelateRegionParamBound(span) => {
8791
label_or_note(
@@ -117,6 +121,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
117121
"",
118122
sup,
119123
" doesn't meet the lifetime requirements",
124+
None,
120125
);
121126
}
122127
(_, ty::RePlaceholder(_)) => {
@@ -126,16 +131,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
126131
"the required lifetime does not necessarily outlive ",
127132
sub,
128133
"",
134+
None,
129135
);
130136
}
131137
_ => {
132-
note_and_explain_region(self.tcx, &mut err, "", sup, "...");
138+
note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
133139
note_and_explain_region(
134140
self.tcx,
135141
&mut err,
136142
"...does not necessarily outlive ",
137143
sub,
138144
"",
145+
None,
139146
);
140147
}
141148
}
@@ -154,13 +161,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
154161
"...the reference is valid for ",
155162
sub,
156163
"...",
164+
None,
157165
);
158166
note_and_explain_region(
159167
self.tcx,
160168
&mut err,
161169
"...but the borrowed content is only valid for ",
162170
sup,
163171
"",
172+
None,
164173
);
165174
err
166175
}
@@ -179,13 +188,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
179188
"...the borrowed pointer is valid for ",
180189
sub,
181190
"...",
191+
None,
182192
);
183193
note_and_explain_region(
184194
self.tcx,
185195
&mut err,
186196
&format!("...but `{}` is only valid for ", var_name),
187197
sup,
188198
"",
199+
None,
189200
);
190201
err
191202
}
@@ -197,17 +208,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
197208
"lifetime of the source pointer does not outlive lifetime bound of the \
198209
object type"
199210
);
200-
note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
211+
note_and_explain_region(
212+
self.tcx,
213+
&mut err,
214+
"object type is valid for ",
215+
sub,
216+
"",
217+
None,
218+
);
201219
note_and_explain_region(
202220
self.tcx,
203221
&mut err,
204222
"source pointer is only valid for ",
205223
sup,
206224
"",
225+
None,
207226
);
208227
err
209228
}
210-
infer::RelateParamBound(span, ty) => {
229+
infer::RelateParamBound(span, ty, opt_span) => {
211230
let mut err = struct_span_err!(
212231
self.tcx.sess,
213232
span,
@@ -216,10 +235,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
216235
self.ty_to_string(ty)
217236
);
218237
match *sub {
219-
ty::ReStatic => {
220-
note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
221-
}
222-
_ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
238+
ty::ReStatic => note_and_explain_region(
239+
self.tcx,
240+
&mut err,
241+
"type must satisfy ",
242+
sub,
243+
if opt_span.is_some() { " as required by this binding" } else { "" },
244+
opt_span,
245+
),
246+
_ => note_and_explain_region(
247+
self.tcx,
248+
&mut err,
249+
"type must outlive ",
250+
sub,
251+
if opt_span.is_some() { " as required by this binding" } else { "" },
252+
opt_span,
253+
),
223254
}
224255
err
225256
}
@@ -232,13 +263,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
232263
"lifetime parameter instantiated with ",
233264
sup,
234265
"",
266+
None,
235267
);
236268
note_and_explain_region(
237269
self.tcx,
238270
&mut err,
239271
"but lifetime parameter must outlive ",
240272
sub,
241273
"",
274+
None,
242275
);
243276
err
244277
}
@@ -255,6 +288,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
255288
"the return value is only valid for ",
256289
sup,
257290
"",
291+
None,
258292
);
259293
err
260294
}
@@ -266,8 +300,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
266300
"a value of type `{}` is borrowed for too long",
267301
self.ty_to_string(ty)
268302
);
269-
note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
270-
note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
303+
note_and_explain_region(
304+
self.tcx,
305+
&mut err,
306+
"the type is valid for ",
307+
sub,
308+
"",
309+
None,
310+
);
311+
note_and_explain_region(
312+
self.tcx,
313+
&mut err,
314+
"but the borrow lasts for ",
315+
sup,
316+
"",
317+
None,
318+
);
271319
err
272320
}
273321
infer::ReferenceOutlivesReferent(ty, span) => {
@@ -278,13 +326,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
278326
"in type `{}`, reference has a longer lifetime than the data it references",
279327
self.ty_to_string(ty)
280328
);
281-
note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
329+
note_and_explain_region(
330+
self.tcx,
331+
&mut err,
332+
"the pointer is valid for ",
333+
sub,
334+
"",
335+
None,
336+
);
282337
note_and_explain_region(
283338
self.tcx,
284339
&mut err,
285340
"but the referenced data is only valid for ",
286341
sup,
287342
"",
343+
None,
288344
);
289345
err
290346
}

compiler/rustc_infer/src/infer/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ pub enum SubregionOrigin<'tcx> {
375375

376376
/// Some type parameter was instantiated with the given type,
377377
/// and that type must outlive some region.
378-
RelateParamBound(Span, Ty<'tcx>),
378+
RelateParamBound(Span, Ty<'tcx>, Option<Span>),
379379

380380
/// The given region parameter was instantiated with a region
381381
/// that must outlive some other region.
@@ -1705,7 +1705,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
17051705
match *self {
17061706
Subtype(ref a) => a.span(),
17071707
RelateObjectBound(a) => a,
1708-
RelateParamBound(a, _) => a,
1708+
RelateParamBound(a, ..) => a,
17091709
RelateRegionParamBound(a) => a,
17101710
Reborrow(a) => a,
17111711
ReborrowUpvar(a, _) => a,

compiler/rustc_infer/src/infer/outlives/obligations.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use crate::infer::outlives::verify::VerifyBoundCx;
6464
use crate::infer::{
6565
self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
6666
};
67-
use crate::traits::ObligationCause;
67+
use crate::traits::{ObligationCause, ObligationCauseCode};
6868
use rustc_middle::ty::outlives::Component;
6969
use rustc_middle::ty::subst::GenericArgKind;
7070
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
@@ -99,7 +99,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
9999
cause: &ObligationCause<'tcx>,
100100
) {
101101
let origin = SubregionOrigin::from_obligation_cause(cause, || {
102-
infer::RelateParamBound(cause.span, sup_type)
102+
infer::RelateParamBound(
103+
cause.span,
104+
sup_type,
105+
match cause.code.peel_derives() {
106+
ObligationCauseCode::BindingObligation(_, span) => Some(*span),
107+
_ => None,
108+
},
109+
)
103110
});
104111

105112
self.register_region_obligation(

compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
9999
GenericArgKind::Type(t1) => {
100100
// we don't actually use this for anything, but
101101
// the `TypeOutlives` code needs an origin.
102-
let origin = infer::RelateParamBound(DUMMY_SP, t1);
102+
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
103103

104104
TypeOutlives::new(
105105
&mut *self,

src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ error[E0310]: the parameter type `U` may not live long enough
44
LL | struct Foo<U> {
55
| - help: consider adding an explicit lifetime bound...: `U: 'static`
66
LL | bar: Bar<U>
7-
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
7+
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
8+
|
9+
note: ...that is required by this bound
10+
--> $DIR/feature-gate-infer_static_outlives_requirements.rs:7:15
11+
|
12+
LL | struct Bar<T: 'static> {
13+
| ^^^^^^^
814

915
error: aborting due to previous error
1016

0 commit comments

Comments
 (0)