enum ConstraintCategory {
Cast,
Assignment,
- AssignmentToUpvar,
Return,
- CallArgumentToUpvar,
CallArgument,
Other,
Boring,
impl fmt::Display for ConstraintCategory {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- ConstraintCategory::Assignment | ConstraintCategory::AssignmentToUpvar => {
- write!(f, "assignment")
- }
+ ConstraintCategory::Assignment => write!(f, "assignment"),
ConstraintCategory::Return => write!(f, "return"),
ConstraintCategory::Cast => write!(f, "cast"),
- ConstraintCategory::CallArgument | ConstraintCategory::CallArgumentToUpvar => {
- write!(f, "argument")
- }
+ ConstraintCategory::CallArgument => write!(f, "argument"),
_ => write!(f, "free region"),
}
}
"constraint_is_interesting: locations={:?} constraint={:?}",
constraint.locations, constraint
);
- if let Locations::Interesting(_) = constraint.locations {
- true
- } else {
- false
+
+ match constraint.locations {
+ Locations::Interesting(_) | Locations::All => true,
+ _ => false,
}
}
}
}
- let category = match (
- category,
+ let (fr_is_local, outlived_fr_is_local): (bool, bool) = (
self.universal_regions.is_local_free_region(fr),
self.universal_regions.is_local_free_region(outlived_fr),
- ) {
- (ConstraintCategory::Assignment, true, false) => ConstraintCategory::AssignmentToUpvar,
- (ConstraintCategory::CallArgument, true, false) => {
- ConstraintCategory::CallArgumentToUpvar
- }
- (category, _, _) => category,
+ );
+ debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
+ fr_is_local, outlived_fr_is_local, category);
+
+ match (fr_is_local, outlived_fr_is_local) {
+ (true, false) =>
+ self.report_escapes_closure_error(mir, infcx, mir_def_id, fr, outlived_fr,
+ category, span, errors_buffer),
+ _ =>
+ self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local,
+ outlived_fr, outlived_fr_is_local,
+ category, span, errors_buffer),
};
-
- debug!("report_error: category={:?}", category);
- match category {
- ConstraintCategory::AssignmentToUpvar | ConstraintCategory::CallArgumentToUpvar => self
- .report_closure_error(
- mir,
- infcx,
- mir_def_id,
- fr,
- outlived_fr,
- category,
- span,
- errors_buffer,
- ),
- _ => self.report_general_error(
- mir,
- infcx,
- mir_def_id,
- fr,
- outlived_fr,
- category,
- span,
- errors_buffer,
- ),
- }
}
- fn report_closure_error(
+ fn report_escapes_closure_error(
&self,
mir: &Mir<'tcx>,
infcx: &InferCtxt<'_, '_, 'tcx>,
self.get_var_name_and_span_for_region(infcx.tcx, mir, outlived_fr);
if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
- return self.report_general_error(
- mir,
- infcx,
- mir_def_id,
- fr,
- outlived_fr,
- category,
- span,
- errors_buffer,
- );
+ return self.report_general_error(mir, infcx, mir_def_id,
+ fr, true, outlived_fr, false,
+ category, span, errors_buffer);
}
let mut diag = infcx
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
fr: RegionVid,
+ fr_is_local: bool,
outlived_fr: RegionVid,
+ outlived_fr_is_local: bool,
category: ConstraintCategory,
span: Span,
errors_buffer: &mut Vec<Diagnostic>,
);
let counter = &mut 1;
- let fr_name = self.give_region_a_name(infcx.tcx, mir, mir_def_id, fr, counter, &mut diag);
- let outlived_fr_name =
- self.give_region_a_name(infcx.tcx, mir, mir_def_id, outlived_fr, counter, &mut diag);
-
- diag.span_label(
- span,
- format!(
- "{} requires that `{}` must outlive `{}`",
- category, fr_name, outlived_fr_name,
- ),
- );
+ let fr_name = self.give_region_a_name(
+ infcx.tcx, mir, mir_def_id, fr, counter, &mut diag);
+ let outlived_fr_name = self.give_region_a_name(
+ infcx.tcx, mir, mir_def_id, outlived_fr, counter, &mut diag);
+
+ match (category, outlived_fr_is_local, fr_is_local) {
+ (ConstraintCategory::Return, true, _) => {
+ diag.span_label(span, format!(
+ "closure was supposed to return data with lifetime `{}` but it is returning \
+ data with lifetime `{}`",
+ fr_name, outlived_fr_name,
+ ));
+ },
+ _ => {
+ diag.span_label(span, format!(
+ "{} requires that `{}` must outlive `{}`",
+ category, fr_name, outlived_fr_name,
+ ));
+ },
+ }
diag.buffer(errors_buffer);
}