error_reporting/mod.rs: rustfmt

This commit is contained in:
Niko Matsakis 2018-10-24 08:51:39 -04:00
parent b24b88734d
commit a1be20c9ce

View file

@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use borrow_check::nll::ConstraintDescription;
use borrow_check::nll::constraints::{OutlivesConstraint};
use borrow_check::nll::constraints::OutlivesConstraint;
use borrow_check::nll::region_infer::RegionInferenceContext;
use borrow_check::nll::type_check::Locations;
use borrow_check::nll::universal_regions::DefiningTy;
use util::borrowck_errors::{BorrowckErrors, Origin};
use borrow_check::nll::ConstraintDescription;
use rustc::hir::def_id::DefId;
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
@ -22,9 +21,10 @@ use rustc::ty::{self, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use std::collections::VecDeque;
use syntax::errors::Applicability;
use syntax::symbol::keywords;
use syntax_pos::Span;
use syntax::errors::Applicability;
use util::borrowck_errors::{BorrowckErrors, Origin};
mod region_name;
mod var_name;
@ -76,9 +76,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
debug!("best_blame_constraint(from_region={:?})", from_region);
// Find all paths
let (path, target_region) = self
.find_constraint_paths_between_regions(from_region, target_test)
.unwrap();
let (path, target_region) =
self.find_constraint_paths_between_regions(from_region, target_test)
.unwrap();
debug!(
"best_blame_constraint: path={:#?}",
path.iter()
@ -92,8 +92,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
);
// Classify each of the constraints along the path.
let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
.iter()
let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path.iter()
.map(|constraint| {
if constraint.category == ConstraintCategory::ClosureBounds {
self.retrieve_closure_constraint_info(mir, &constraint)
@ -137,13 +136,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
| ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal => false,
ConstraintCategory::TypeAnnotation
| ConstraintCategory::Return => true,
ConstraintCategory::TypeAnnotation | ConstraintCategory::Return => true,
_ => constraint_sup_scc != target_scc,
}
});
if let Some(i) = best_choice {
return categorized_path[i]
return categorized_path[i];
}
// If that search fails, that is.. unusual. Maybe everything
@ -206,9 +204,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// enqueue any regions we find, keeping track of how we
// reached them.
let fr_static = self.universal_regions.fr_static;
for constraint in self.constraint_graph.outgoing_edges(r,
&self.constraints,
fr_static) {
for constraint in self.constraint_graph
.outgoing_edges(r, &self.constraints, fr_static)
{
assert_eq!(constraint.sup, r);
let sub_region = constraint.sub;
if let Trace::NotVisited = context[sub_region] {
@ -240,11 +238,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) {
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
let (category, _, span) = self.best_blame_constraint(
mir,
fr,
|r| r == outlived_fr
);
let (category, _, span) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr);
// Check if we can use one of the "nice region errors".
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
@ -260,20 +254,45 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.universal_regions.is_local_free_region(outlived_fr),
);
debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
fr_is_local, outlived_fr_is_local, category);
debug!(
"report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
fr_is_local, outlived_fr_is_local, category
);
match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) =>
self.report_fnmut_error(mir, infcx, mir_def_id, fr, outlived_fr, span,
errors_buffer),
(ConstraintCategory::Assignment, true, false) |
(ConstraintCategory::CallArgument, true, false) =>
self.report_escaping_data_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),
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
self.report_fnmut_error(
mir,
infcx,
mir_def_id,
fr,
outlived_fr,
span,
errors_buffer,
)
}
(ConstraintCategory::Assignment, true, false)
| (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_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,
),
};
}
@ -303,10 +322,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
span: Span,
errors_buffer: &mut Vec<Diagnostic>,
) {
let mut diag = infcx.tcx.sess.struct_span_err(
span,
"captured variable cannot escape `FnMut` closure body",
);
let mut diag = infcx
.tcx
.sess
.struct_span_err(span, "captured variable cannot escape `FnMut` closure body");
// We should check if the return type of this closure is in fact a closure - in that
// case, we can special case the error further.
@ -318,27 +337,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
"returns a reference to a captured variable which escapes the closure body"
};
diag.span_label(
span,
message,
);
diag.span_label(span, message);
match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).source {
RegionNameSource::NamedEarlyBoundRegion(fr_span) |
RegionNameSource::NamedFreeRegion(fr_span) |
RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _) |
RegionNameSource::CannotMatchHirTy(fr_span, _) |
RegionNameSource::MatchedHirTy(fr_span) |
RegionNameSource::MatchedAdtAndSegment(fr_span) |
RegionNameSource::AnonRegionFromUpvar(fr_span, _) |
RegionNameSource::AnonRegionFromOutput(fr_span, _, _) => {
match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1)
.source
{
RegionNameSource::NamedEarlyBoundRegion(fr_span)
| RegionNameSource::NamedFreeRegion(fr_span)
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
| RegionNameSource::CannotMatchHirTy(fr_span, _)
| RegionNameSource::MatchedHirTy(fr_span)
| RegionNameSource::MatchedAdtAndSegment(fr_span)
| RegionNameSource::AnonRegionFromUpvar(fr_span, _)
| RegionNameSource::AnonRegionFromOutput(fr_span, _, _) => {
diag.span_label(fr_span, "inferred to be a `FnMut` closure");
},
_ => {},
}
_ => {}
}
diag.note("`FnMut` closures only have access to their captured variables while they are \
executing...");
diag.note(
"`FnMut` closures only have access to their captured variables while they are \
executing...",
);
diag.note("...therefore, they cannot allow references to captured variables to escape");
diag.buffer(errors_buffer);
@ -375,7 +395,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
DefiningTy::Closure(..) => "closure",
DefiningTy::Generator(..) => "generator",
DefiningTy::FnDef(..) => "function",
DefiningTy::Const(..) => "const"
DefiningTy::Const(..) => "const",
};
// Revert to the normal error in these cases.
@ -384,12 +404,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|| (category == ConstraintCategory::Assignment && escapes_from == "function")
|| escapes_from == "const"
{
return self.report_general_error(mir, infcx, mir_def_id,
fr, true, outlived_fr, false,
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.tcx.borrowed_data_escapes_closure(span, escapes_from, Origin::Mir);
let mut diag = infcx
.tcx
.borrowed_data_escapes_closure(span, escapes_from, Origin::Mir);
if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
diag.span_label(
@ -410,7 +441,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
),
);
diag.span_label(span, format!("`{}` escapes the {} body here", fr_name, escapes_from));
diag.span_label(
span,
format!("`{}` escapes the {} body here", fr_name, escapes_from),
);
}
diag.buffer(errors_buffer);
@ -452,31 +486,41 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let counter = &mut 1;
let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter);
fr_name.highlight_region_name(&mut diag);
let outlived_fr_name = self.give_region_a_name(
infcx, mir, mir_def_id, outlived_fr, counter);
let outlived_fr_name =
self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter);
outlived_fr_name.highlight_region_name(&mut diag);
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) { "closure" } else { "function" };
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
"closure"
} else {
"function"
};
match (category, outlived_fr_is_local, fr_is_local) {
(ConstraintCategory::Return, true, _) => {
diag.span_label(span, format!(
"{} was supposed to return data with lifetime `{}` but it is returning \
data with lifetime `{}`",
mir_def_name, outlived_fr_name, fr_name
));
},
diag.span_label(
span,
format!(
"{} was supposed to return data with lifetime `{}` but it is returning \
data with lifetime `{}`",
mir_def_name, outlived_fr_name, fr_name
),
);
}
_ => {
diag.span_label(span, format!(
"{}requires that `{}` must outlive `{}`",
category.description(), fr_name, outlived_fr_name,
));
},
diag.span_label(
span,
format!(
"{}requires that `{}` must outlive `{}`",
category.description(),
fr_name,
outlived_fr_name,
),
);
}
}
self.add_static_impl_trait_suggestion(
infcx, &mut diag, fr, fr_name, outlived_fr,
);
self.add_static_impl_trait_suggestion(infcx, &mut diag, fr, fr_name, outlived_fr);
diag.buffer(errors_buffer);
}
@ -499,17 +543,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fr_name: RegionName,
outlived_fr: RegionVid,
) {
if let (
Some(f),
Some(ty::RegionKind::ReStatic)
) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
if let (Some(f), Some(ty::RegionKind::ReStatic)) =
(self.to_error_region(fr), self.to_error_region(outlived_fr))
{
if let Some(ty::TyS {
sty: ty::TyKind::Opaque(did, substs),
..
}) = infcx.tcx.is_suitable_region(f)
.map(|r| r.def_id)
.map(|id| infcx.tcx.return_type_impl_trait(id))
.unwrap_or(None)
}) = infcx
.tcx
.is_suitable_region(f)
.map(|r| r.def_id)
.map(|id| infcx.tcx.return_type_impl_trait(id))
.unwrap_or(None)
{
// Check whether or not the impl trait return type is intended to capture
// data with the static lifetime.
@ -522,10 +567,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let mut found = false;
for predicate in bounds.predicates {
if let ty::Predicate::TypeOutlives(binder) = predicate {
if let ty::OutlivesPredicate(
_,
ty::RegionKind::ReStatic
) = binder.skip_binder() {
if let ty::OutlivesPredicate(_, ty::RegionKind::ReStatic) =
binder.skip_binder()
{
found = true;
break;
}
@ -535,18 +579,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
found
};
debug!("add_static_impl_trait_suggestion: has_static_predicate={:?}",
has_static_predicate);
debug!(
"add_static_impl_trait_suggestion: has_static_predicate={:?}",
has_static_predicate
);
let static_str = keywords::StaticLifetime.name();
// If there is a static predicate, then the only sensible suggestion is to replace
// fr with `'static`.
if has_static_predicate {
diag.help(
&format!(
"consider replacing `{}` with `{}`",
fr_name, static_str,
),
);
diag.help(&format!(
"consider replacing `{}` with `{}`",
fr_name, static_str,
));
} else {
// Otherwise, we should suggest adding a constraint on the return type.
let span = infcx.tcx.def_span(*did);
@ -581,13 +625,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
borrow_region: RegionVid,
outlived_region: RegionVid,
) -> (ConstraintCategory, bool, Span, RegionName) {
let (category, from_closure, span) = self.best_blame_constraint(
mir,
borrow_region,
|r| r == outlived_region
);
let outlived_fr_name = self.give_region_a_name(
infcx, mir, mir_def_id, outlived_region, &mut 1);
let (category, from_closure, span) =
self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
let outlived_fr_name =
self.give_region_a_name(infcx, mir, mir_def_id, outlived_region, &mut 1);
(category, from_closure, span, outlived_fr_name)
}
@ -596,10 +637,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
// Find all paths
let (_path, r) =
self.find_constraint_paths_between_regions(fr1, |r| {
self.liveness_constraints.contains(r, elem)
}).unwrap();
let (_path, r) = self.find_constraint_paths_between_regions(fr1, |r| {
self.liveness_constraints.contains(r, elem)
}).unwrap();
r
}
@ -617,27 +657,22 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn retrieve_closure_constraint_info(
&self,
mir: &Mir<'tcx>,
constraint: &OutlivesConstraint
constraint: &OutlivesConstraint,
) -> (ConstraintCategory, bool, Span) {
let loc = match constraint.locations {
Locations::All(span) => return (constraint.category, false, span),
Locations::Single(loc) => loc,
};
let opt_span_category = self
.closure_bounds_mapping[&loc]
.get(&(constraint.sup, constraint.sub));
let opt_span_category =
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
opt_span_category
.map(|&(category, span)| (category, true, span))
.unwrap_or((constraint.category, false, mir.source_info(loc).span))
}
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
crate fn is_closure_fn_mut(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
fr: RegionVid,
) -> bool {
crate fn is_closure_fn_mut(&self, infcx: &InferCtxt<'_, '_, 'tcx>, fr: RegionVid) -> bool {
if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
if let ty::BoundRegion::BrEnv = free_region.bound_region {
if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty {