1
Fork 0

Make rustc::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region} free functions.

This commit is contained in:
Camille GILLOT 2020-01-05 16:11:18 +01:00
parent 7118e33bfd
commit d53bf7a676
3 changed files with 164 additions and 125 deletions

View file

@ -79,98 +79,95 @@ pub use need_type_info::TypeAnnotationNeeded;
pub mod nice_region_error; pub mod nice_region_error;
impl<'tcx> TyCtxt<'tcx> { pub(super) fn note_and_explain_region(
pub fn note_and_explain_region( tcx: TyCtxt<'tcx>,
self, region_scope_tree: &region::ScopeTree,
region_scope_tree: &region::ScopeTree, err: &mut DiagnosticBuilder<'_>,
err: &mut DiagnosticBuilder<'_>, prefix: &str,
prefix: &str, region: ty::Region<'tcx>,
region: ty::Region<'tcx>, suffix: &str,
suffix: &str, ) {
) { let (description, span) = match *region {
let (description, span) = match *region { ty::ReScope(scope) => {
ty::ReScope(scope) => { let new_string;
let new_string; let unknown_scope =
let unknown_scope = || { || format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix);
format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix) let span = scope.span(tcx, region_scope_tree);
}; let tag = match tcx.hir().find(scope.hir_id(region_scope_tree)) {
let span = scope.span(self, region_scope_tree); Some(Node::Block(_)) => "block",
let tag = match self.hir().find(scope.hir_id(region_scope_tree)) { Some(Node::Expr(expr)) => match expr.kind {
Some(Node::Block(_)) => "block", hir::ExprKind::Call(..) => "call",
Some(Node::Expr(expr)) => match expr.kind { hir::ExprKind::MethodCall(..) => "method call",
hir::ExprKind::Call(..) => "call", hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
hir::ExprKind::MethodCall(..) => "method call", hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let",
hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let", hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for",
hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let", hir::ExprKind::Match(..) => "match",
hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for", _ => "expression",
hir::ExprKind::Match(..) => "match", },
_ => "expression", Some(Node::Stmt(_)) => "statement",
}, Some(Node::Item(it)) => item_scope_tag(&it),
Some(Node::Stmt(_)) => "statement", Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
Some(Node::Item(it)) => item_scope_tag(&it), Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
Some(Node::TraitItem(it)) => trait_item_scope_tag(&it), Some(_) | None => {
Some(Node::ImplItem(it)) => impl_item_scope_tag(&it), err.span_note(span, &unknown_scope());
Some(_) | None => { return;
err.span_note(span, &unknown_scope()); }
return; };
} let scope_decorated_tag = match scope.data {
}; region::ScopeData::Node => tag,
let scope_decorated_tag = match scope.data { region::ScopeData::CallSite => "scope of call-site for function",
region::ScopeData::Node => tag, region::ScopeData::Arguments => "scope of function body",
region::ScopeData::CallSite => "scope of call-site for function", region::ScopeData::Destruction => {
region::ScopeData::Arguments => "scope of function body", new_string = format!("destruction scope surrounding {}", tag);
region::ScopeData::Destruction => { &new_string[..]
new_string = format!("destruction scope surrounding {}", tag); }
&new_string[..] region::ScopeData::Remainder(first_statement_index) => {
} new_string = format!(
region::ScopeData::Remainder(first_statement_index) => { "block suffix following statement {}",
new_string = format!( first_statement_index.index()
"block suffix following statement {}", );
first_statement_index.index() &new_string[..]
); }
&new_string[..] };
} explain_span(tcx, scope_decorated_tag, span)
}; }
explain_span(self, scope_decorated_tag, span)
}
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => { ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
msg_span_from_free_region(self, region) msg_span_from_free_region(tcx, region)
} }
ty::ReEmpty => ("the empty lifetime".to_owned(), None), ty::ReEmpty => ("the empty lifetime".to_owned(), None),
ty::RePlaceholder(_) => (format!("any other region"), None), ty::RePlaceholder(_) => (format!("any other region"), None),
// FIXME(#13998) RePlaceholder should probably print like // FIXME(#13998) RePlaceholder should probably print like
// ReFree rather than dumping Debug output on the user. // ReFree rather than dumping Debug output on the user.
// //
// We shouldn't really be having unification failures with ReVar // We shouldn't really be having unification failures with ReVar
// and ReLateBound though. // and ReLateBound though.
ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
(format!("lifetime {:?}", region), None) (format!("lifetime {:?}", region), None)
} }
// We shouldn't encounter an error message with ReClosureBound. // We shouldn't encounter an error message with ReClosureBound.
ty::ReClosureBound(..) => { ty::ReClosureBound(..) => {
bug!("encountered unexpected ReClosureBound: {:?}", region,); bug!("encountered unexpected ReClosureBound: {:?}", region,);
} }
}; };
emit_msg_span(err, prefix, description, span, suffix); emit_msg_span(err, prefix, description, span, suffix);
} }
pub fn note_and_explain_free_region( pub(super) fn note_and_explain_free_region(
self, tcx: TyCtxt<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
prefix: &str, prefix: &str,
region: ty::Region<'tcx>, region: ty::Region<'tcx>,
suffix: &str, suffix: &str,
) { ) {
let (description, span) = msg_span_from_free_region(self, region); let (description, span) = msg_span_from_free_region(tcx, region);
emit_msg_span(err, prefix, description, span, suffix); emit_msg_span(err, prefix, description, span, suffix);
}
} }
fn msg_span_from_free_region( fn msg_span_from_free_region(
@ -1719,7 +1716,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"consider adding an explicit lifetime bound for `{}`", "consider adding an explicit lifetime bound for `{}`",
bound_kind bound_kind
)); ));
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
&format!("{} must be valid for ", labeled_user_string), &format!("{} must be valid for ", labeled_user_string),
@ -1747,7 +1745,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) { ) {
let mut err = self.report_inference_failure(var_origin); let mut err = self.report_inference_failure(var_origin);
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"first, the lifetime cannot outlive ", "first, the lifetime cannot outlive ",
@ -1771,7 +1770,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
(self.values_str(&sup_trace.values), self.values_str(&sub_trace.values)) (self.values_str(&sup_trace.values), self.values_str(&sub_trace.values))
{ {
if sub_expected == sup_expected && sub_found == sup_found { if sub_expected == sup_expected && sub_found == sup_found {
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...but the lifetime must also be valid for ", "...but the lifetime must also be valid for ",
@ -1794,7 +1794,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.note_region_origin(&mut err, &sup_origin); self.note_region_origin(&mut err, &sup_origin);
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"but, the lifetime must be valid for ", "but, the lifetime must be valid for ",

View file

@ -1,3 +1,4 @@
use crate::infer::error_reporting::note_and_explain_region;
use crate::infer::{self, InferCtxt, SubregionOrigin}; use crate::infer::{self, InferCtxt, SubregionOrigin};
use crate::middle::region; use crate::middle::region;
use crate::ty::error::TypeError; use crate::ty::error::TypeError;
@ -167,8 +168,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::Subtype(box trace) => { infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, &terr); let mut err = self.report_and_explain_type_error(trace, &terr);
self.tcx.note_and_explain_region(region_scope_tree, &mut err, "", sup, "..."); note_and_explain_region(self.tcx, region_scope_tree, &mut err, "", sup, "...");
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...does not necessarily outlive ", "...does not necessarily outlive ",
@ -185,14 +187,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of reference outlives lifetime of \ "lifetime of reference outlives lifetime of \
borrowed content..." borrowed content..."
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...the reference is valid for ", "...the reference is valid for ",
sub, sub,
"...", "...",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...but the borrowed content is only valid for ", "...but the borrowed content is only valid for ",
@ -211,14 +215,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
of captured variable `{}`...", of captured variable `{}`...",
var_name var_name
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...the borrowed pointer is valid for ", "...the borrowed pointer is valid for ",
sub, sub,
"...", "...",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
&format!("...but `{}` is only valid for ", var_name), &format!("...but `{}` is only valid for ", var_name),
@ -230,14 +236,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::InfStackClosure(span) => { infer::InfStackClosure(span) => {
let mut err = let mut err =
struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame"); struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame");
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...the closure must be valid for ", "...the closure must be valid for ",
sub, sub,
"...", "...",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"...but the closure's stack frame is only valid \ "...but the closure's stack frame is only valid \
@ -254,7 +262,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
E0315, E0315,
"cannot invoke closure outside of its lifetime" "cannot invoke closure outside of its lifetime"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the closure is only valid for ", "the closure is only valid for ",
@ -270,7 +279,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
E0473, E0473,
"dereference of reference outside its lifetime" "dereference of reference outside its lifetime"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the reference is only valid for ", "the reference is only valid for ",
@ -288,14 +298,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
enclosing closure", enclosing closure",
self.tcx.hir().name(id) self.tcx.hir().name(id)
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"captured variable is valid for ", "captured variable is valid for ",
sup, sup,
"", "",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"closure is valid for ", "closure is valid for ",
@ -311,7 +323,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
E0475, E0475,
"index of slice outside its lifetime" "index of slice outside its lifetime"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the slice is only valid for ", "the slice is only valid for ",
@ -328,14 +341,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of the source pointer does not outlive \ "lifetime of the source pointer does not outlive \
lifetime bound of the object type" lifetime bound of the object type"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"object type is valid for ", "object type is valid for ",
sub, sub,
"", "",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"source pointer is only valid for ", "source pointer is only valid for ",
@ -354,14 +369,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.ty_to_string(ty) self.ty_to_string(ty)
); );
match *sub { match *sub {
ty::ReStatic => self.tcx.note_and_explain_region( ty::ReStatic => note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"type must satisfy ", "type must satisfy ",
sub, sub,
"", "",
), ),
_ => self.tcx.note_and_explain_region( _ => note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"type must outlive ", "type must outlive ",
@ -374,14 +391,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::RelateRegionParamBound(span) => { infer::RelateRegionParamBound(span) => {
let mut err = let mut err =
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"lifetime parameter instantiated with ", "lifetime parameter instantiated with ",
sup, sup,
"", "",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"but lifetime parameter must outlive ", "but lifetime parameter must outlive ",
@ -399,7 +418,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
parameter) is not valid at this point", parameter) is not valid at this point",
self.ty_to_string(ty) self.ty_to_string(ty)
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"type must outlive ", "type must outlive ",
@ -416,7 +436,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of method receiver does not outlive the \ "lifetime of method receiver does not outlive the \
method call" method call"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the receiver is only valid for ", "the receiver is only valid for ",
@ -433,7 +454,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of function argument does not outlive \ "lifetime of function argument does not outlive \
the function call" the function call"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the function argument is only valid for ", "the function argument is only valid for ",
@ -450,7 +472,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of return value does not outlive the \ "lifetime of return value does not outlive the \
function call" function call"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the return value is only valid for ", "the return value is only valid for ",
@ -467,7 +490,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of operand does not outlive the \ "lifetime of operand does not outlive the \
operation" operation"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the operand is only valid for ", "the operand is only valid for ",
@ -483,7 +507,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
E0484, E0484,
"reference is not valid at the time of borrow" "reference is not valid at the time of borrow"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the borrow is only valid for ", "the borrow is only valid for ",
@ -500,7 +525,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"automatically reference is not valid at the time \ "automatically reference is not valid at the time \
of borrow" of borrow"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the automatic borrow is only valid for ", "the automatic borrow is only valid for ",
@ -518,7 +544,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
not valid during the expression: `{}`", not valid during the expression: `{}`",
self.ty_to_string(t) self.ty_to_string(t)
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"type is only valid for ", "type is only valid for ",
@ -536,14 +563,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
called while references are dead" called while references are dead"
); );
// FIXME (22171): terms "super/subregion" are suboptimal // FIXME (22171): terms "super/subregion" are suboptimal
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"superregion: ", "superregion: ",
sup, sup,
"", "",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"subregion: ", "subregion: ",
@ -560,7 +589,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of variable does not enclose its \ "lifetime of variable does not enclose its \
declaration" declaration"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the variable is only valid for ", "the variable is only valid for ",
@ -576,7 +606,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
E0489, E0489,
"type/lifetime parameter not in scope here" "type/lifetime parameter not in scope here"
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the parameter is only valid for ", "the parameter is only valid for ",
@ -593,14 +624,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"a value of type `{}` is borrowed for too long", "a value of type `{}` is borrowed for too long",
self.ty_to_string(ty) self.ty_to_string(ty)
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the type is valid for ", "the type is valid for ",
sub, sub,
"", "",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"but the borrow lasts for ", "but the borrow lasts for ",
@ -618,14 +651,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
than the data it references", than the data it references",
self.ty_to_string(ty) self.ty_to_string(ty)
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"the pointer is valid for ", "the pointer is valid for ",
sub, sub,
"", "",
); );
self.tcx.note_and_explain_region( note_and_explain_region(
self.tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
"but the referenced data is only valid for ", "but the referenced data is only valid for ",

View file

@ -1,3 +1,4 @@
use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region};
use crate::infer::outlives::free_region_map::FreeRegionRelations; use crate::infer::outlives::free_region_map::FreeRegionRelations;
use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
use crate::middle::region; use crate::middle::region;
@ -624,7 +625,8 @@ pub fn unexpected_hidden_region_diagnostic(
// //
// (*) if not, the `tainted_by_errors` flag would be set to // (*) if not, the `tainted_by_errors` flag would be set to
// true in any case, so we wouldn't be here at all. // true in any case, so we wouldn't be here at all.
tcx.note_and_explain_free_region( note_and_explain_free_region(
tcx,
&mut err, &mut err,
&format!("hidden type `{}` captures ", hidden_ty), &format!("hidden type `{}` captures ", hidden_ty),
hidden_region, hidden_region,
@ -649,7 +651,8 @@ pub fn unexpected_hidden_region_diagnostic(
// If the `region_scope_tree` is available, this is being // If the `region_scope_tree` is available, this is being
// invoked from the "region inferencer error". We can at // invoked from the "region inferencer error". We can at
// least report a really cryptic error for now. // least report a really cryptic error for now.
tcx.note_and_explain_region( note_and_explain_region(
tcx,
region_scope_tree, region_scope_tree,
&mut err, &mut err,
&format!("hidden type `{}` captures ", hidden_ty), &format!("hidden type `{}` captures ", hidden_ty),