Tweak wording and spans

This commit is contained in:
Esteban Küber 2022-06-21 15:54:17 -07:00
parent 29e2aa12ff
commit 9cb1874cd6
60 changed files with 368 additions and 326 deletions

View file

@ -21,6 +21,7 @@ use rustc_middle::ty::{
self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty,
};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, Span};
use rustc_trait_selection::infer::InferCtxtExt;
@ -331,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
spans.push(span);
}
let (item_msg, name, desc) =
let (binding, name, desc) =
match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
Some(name) => (format!("`{name}`"), format!("`{name}`"), format!("`{name}` ")),
None => ("value".to_string(), "the variable".to_string(), String::new()),
@ -351,7 +352,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
"initialized in all conditions"
};
let mut err = struct_span_err!(self, span, E0381, "binding {desc}isn't {initialized}");
let used = desired_action.as_general_verb_in_past_tense();
let mut err =
struct_span_err!(self, span, E0381, "{used} binding {desc}isn't {initialized}");
use_spans.var_span_label_path_only(
&mut err,
format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
@ -359,12 +362,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let InitializationRequiringAction::PartialAssignment = desired_action {
err.help(
"partial initialization isn't supported, fully initialize the binding with \
a default value and mutate, or use `std::mem::MaybeUninit`",
"partial initialization isn't supported, fully initialize the binding with a \
default value and mutate it, or use `std::mem::MaybeUninit`",
);
}
let verb = desired_action.as_verb_in_past_tense();
err.span_label(span, format!("{item_msg} {verb} here but it isn't {initialized}",));
err.span_label(span, format!("{binding} {used} here but it isn't {initialized}"));
// We use the statements were the binding was initialized, and inspect the HIR to look
// for the branching codepaths that aren't covered, to point at them.
@ -400,7 +402,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(sp, &label);
}
}
err.span_label(decl_span, "variable declared here");
err.span_label(decl_span, "binding declared here but left uninitialized");
err
}
@ -2559,10 +2561,10 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
v.visit_expr(body);
if v.1 {
self.errors.push((
cond.span,
ex.span.to(cond.span),
format!(
"this `if` expression might be missing an `else` arm where {} is \
initialized",
"this `if` expression might be missing an `else` arm that initializes \
{}",
self.name,
),
));
@ -2578,10 +2580,24 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
match (a.1, b.1) {
(true, true) | (false, false) => {}
(true, false) => {
self.errors.push((
cond.span,
format!("{} is uninitialized if this condition isn't met", self.name,),
));
if other.span.is_desugaring(DesugaringKind::WhileLoop) {
self.errors.push((
cond.span,
format!(
"{} is uninitialized if this condition isn't met and the \
`while` loop runs 0 times",
self.name
),
));
} else {
self.errors.push((
body.span.shrink_to_hi().until(other.span),
format!(
"{} is uninitialized if this `else` arm is executed",
self.name
),
));
}
}
(false, true) => {
self.errors.push((
@ -2591,7 +2607,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
}
}
}
hir::ExprKind::Match(_, arms, _) => {
hir::ExprKind::Match(e, arms, loop_desugar) => {
// If the binding is initialized in one of the match arms, then the other match
// arms might be missing an initialization.
let results: Vec<bool> = arms
@ -2605,13 +2621,32 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
for (arm, seen) in arms.iter().zip(results) {
if !seen {
self.errors.push((
arm.pat.span,
format!(
"{} is uninitialized if this pattern is matched",
self.name
),
));
if loop_desugar == hir::MatchSource::ForLoopDesugar {
self.errors.push((
e.span,
format!(
"{} is uninitialized if the `for` loop runs 0 times",
self.name
),
));
} else if let Some(guard) = &arm.guard {
self.errors.push((
arm.pat.span.to(guard.body().span),
format!(
"{} is uninitialized if this pattern and condition are \
matched",
self.name
),
));
} else {
self.errors.push((
arm.pat.span,
format!(
"{} is uninitialized if this pattern is matched",
self.name
),
));
}
}
}
}
@ -2619,8 +2654,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
// FIXME: should we also account for binops, particularly `&&` and `||`? `try` should
// also be accounted for. For now it is fine, as if we don't find *any* relevant
// branching code paths, we point at the places where the binding *is* initialized for
// *some* context. We should also specialize the output for `while` and `for` loops,
// but for now we can rely on their desugaring to provide appropriate output.
// *some* context.
_ => {}
}
walk_expr(self, ex);