Skip to content

Point at unmet explicit lifetime obligation bound #87628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,17 @@ pub(super) fn note_and_explain_region(
prefix: &str,
region: ty::Region<'tcx>,
suffix: &str,
alt_span: Option<Span>,
) {
let (description, span) = match *region {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
msg_span_from_free_region(tcx, region)
msg_span_from_free_region(tcx, region, alt_span)
}

ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), None),
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), alt_span),

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

ty::RePlaceholder(_) => return,

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

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

emit_msg_span(err, prefix, description, span, suffix);
}

fn msg_span_from_free_region(
tcx: TyCtxt<'tcx>,
region: ty::Region<'tcx>,
alt_span: Option<Span>,
) -> (String, Option<Span>) {
match *region {
ty::ReEarlyBound(_) | ty::ReFree(_) => {
msg_span_from_early_bound_and_free_regions(tcx, region)
}
ty::ReStatic => ("the static lifetime".to_owned(), None),
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), None),
ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), None),
ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), alt_span),
ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), alt_span),
_ => bug!("{:?}", region),
}
}
Expand Down Expand Up @@ -319,6 +321,7 @@ pub fn unexpected_hidden_region_diagnostic(
&format!("hidden type `{}` captures ", hidden_ty),
hidden_region,
"",
None,
);
}
}
Expand Down Expand Up @@ -2285,8 +2288,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&format!("{} must be valid for ", labeled_user_string),
sub,
"...",
None,
);
if let Some(infer::RelateParamBound(_, t)) = origin {
if let Some(infer::RelateParamBound(_, t, _)) = origin {
let return_impl_trait = self
.in_progress_typeck_results
.map(|typeck_results| typeck_results.borrow().hir_owner)
Expand Down Expand Up @@ -2332,6 +2336,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"first, the lifetime cannot outlive ",
sup_region,
"...",
None,
);

debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
Expand All @@ -2358,6 +2363,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"...but the lifetime must also be valid for ",
sub_region,
"...",
None,
);
err.span_note(
sup_trace.cause.span,
Expand All @@ -2379,6 +2385,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"but, the lifetime must be valid for ",
sub_region,
"...",
None,
);

self.note_region_origin(&mut err, &sub_origin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
multi_span
.push_span_label(binding_span, "introduces a `'static` lifetime requirement".into());
err.span_note(multi_span, "because this has an unmet lifetime requirement");
note_and_explain_region(self.tcx(), &mut err, "", sup, "...");
note_and_explain_region(self.tcx(), &mut err, "", sup, "...", Some(binding_span));
if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
// If an impl is local, then maybe this isn't what they want. Try to
// be as helpful as possible with implicit lifetimes.
Expand Down
82 changes: 69 additions & 13 deletions compiler/rustc_infer/src/infer/error_reporting/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
),
);
}
infer::RelateParamBound(span, t) => {
infer::RelateParamBound(span, t, opt_span) => {
label_or_note(
span,
&format!(
"...so that the type `{}` will meet its required lifetime bounds",
self.ty_to_string(t)
"...so that the type `{}` will meet its required lifetime bounds{}",
self.ty_to_string(t),
if opt_span.is_some() { "..." } else { "" },
),
);
if let Some(span) = opt_span {
err.span_note(span, "...that is required by this bound");
}
}
infer::RelateRegionParamBound(span) => {
label_or_note(
Expand Down Expand Up @@ -117,6 +121,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"",
sup,
" doesn't meet the lifetime requirements",
None,
);
}
(_, ty::RePlaceholder(_)) => {
Expand All @@ -126,16 +131,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"the required lifetime does not necessarily outlive ",
sub,
"",
None,
);
}
_ => {
note_and_explain_region(self.tcx, &mut err, "", sup, "...");
note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
note_and_explain_region(
self.tcx,
&mut err,
"...does not necessarily outlive ",
sub,
"",
None,
);
}
}
Expand All @@ -154,13 +161,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"...the reference is valid for ",
sub,
"...",
None,
);
note_and_explain_region(
self.tcx,
&mut err,
"...but the borrowed content is only valid for ",
sup,
"",
None,
);
err
}
Expand All @@ -179,13 +188,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"...the borrowed pointer is valid for ",
sub,
"...",
None,
);
note_and_explain_region(
self.tcx,
&mut err,
&format!("...but `{}` is only valid for ", var_name),
sup,
"",
None,
);
err
}
Expand All @@ -197,17 +208,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of the source pointer does not outlive lifetime bound of the \
object type"
);
note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
note_and_explain_region(
self.tcx,
&mut err,
"object type is valid for ",
sub,
"",
None,
);
note_and_explain_region(
self.tcx,
&mut err,
"source pointer is only valid for ",
sup,
"",
None,
);
err
}
infer::RelateParamBound(span, ty) => {
infer::RelateParamBound(span, ty, opt_span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
Expand All @@ -216,10 +235,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.ty_to_string(ty)
);
match *sub {
ty::ReStatic => {
note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
}
_ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
ty::ReStatic => note_and_explain_region(
self.tcx,
&mut err,
"type must satisfy ",
sub,
if opt_span.is_some() { " as required by this binding" } else { "" },
opt_span,
),
_ => note_and_explain_region(
self.tcx,
&mut err,
"type must outlive ",
sub,
if opt_span.is_some() { " as required by this binding" } else { "" },
opt_span,
),
}
err
}
Expand All @@ -232,13 +263,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime parameter instantiated with ",
sup,
"",
None,
);
note_and_explain_region(
self.tcx,
&mut err,
"but lifetime parameter must outlive ",
sub,
"",
None,
);
err
}
Expand All @@ -255,6 +288,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"the return value is only valid for ",
sup,
"",
None,
);
err
}
Expand All @@ -266,8 +300,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"a value of type `{}` is borrowed for too long",
self.ty_to_string(ty)
);
note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
note_and_explain_region(
self.tcx,
&mut err,
"the type is valid for ",
sub,
"",
None,
);
note_and_explain_region(
self.tcx,
&mut err,
"but the borrow lasts for ",
sup,
"",
None,
);
err
}
infer::ReferenceOutlivesReferent(ty, span) => {
Expand All @@ -278,13 +326,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"in type `{}`, reference has a longer lifetime than the data it references",
self.ty_to_string(ty)
);
note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
note_and_explain_region(
self.tcx,
&mut err,
"the pointer is valid for ",
sub,
"",
None,
);
note_and_explain_region(
self.tcx,
&mut err,
"but the referenced data is only valid for ",
sup,
"",
None,
);
err
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ pub enum SubregionOrigin<'tcx> {

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

/// The given region parameter was instantiated with a region
/// that must outlive some other region.
Expand Down Expand Up @@ -1705,7 +1705,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
match *self {
Subtype(ref a) => a.span(),
RelateObjectBound(a) => a,
RelateParamBound(a, _) => a,
RelateParamBound(a, ..) => a,
RelateRegionParamBound(a) => a,
Reborrow(a) => a,
ReborrowUpvar(a, _) => a,
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use crate::infer::outlives::verify::VerifyBoundCx;
use crate::infer::{
self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
};
use crate::traits::ObligationCause;
use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
Expand Down Expand Up @@ -99,7 +99,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
cause: &ObligationCause<'tcx>,
) {
let origin = SubregionOrigin::from_obligation_cause(cause, || {
infer::RelateParamBound(cause.span, sup_type)
infer::RelateParamBound(
cause.span,
sup_type,
match cause.code.peel_derives() {
ObligationCauseCode::BindingObligation(_, span) => Some(*span),
_ => None,
},
)
});

self.register_region_obligation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
GenericArgKind::Type(t1) => {
// we don't actually use this for anything, but
// the `TypeOutlives` code needs an origin.
let origin = infer::RelateParamBound(DUMMY_SP, t1);
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);

TypeOutlives::new(
&mut *self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ error[E0310]: the parameter type `U` may not live long enough
LL | struct Foo<U> {
| - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | bar: Bar<U>
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
| ^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> $DIR/feature-gate-infer_static_outlives_requirements.rs:7:15
|
LL | struct Bar<T: 'static> {
| ^^^^^^^

error: aborting due to previous error

Expand Down
Loading