implement tainted_by_errors in mir borrowck
This commit is contained in:
parent
6499c5e7fc
commit
4ad272b282
9 changed files with 68 additions and 52 deletions
|
@ -55,7 +55,7 @@ impl<'tcx> UniverseInfo<'tcx> {
|
|||
found,
|
||||
TypeError::RegionsPlaceholderMismatch,
|
||||
);
|
||||
err.buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(err);
|
||||
}
|
||||
UniverseInfoInner::TypeOp(ref type_op_info) => {
|
||||
type_op_info.report_error(mbcx, placeholder, error_element, cause);
|
||||
|
@ -64,11 +64,9 @@ impl<'tcx> UniverseInfo<'tcx> {
|
|||
// FIXME: This error message isn't great, but it doesn't show
|
||||
// up in the existing UI tests. Consider investigating this
|
||||
// some more.
|
||||
mbcx.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.struct_span_err(cause.span, "higher-ranked subtype error")
|
||||
.buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(
|
||||
mbcx.infcx.tcx.sess.struct_span_err(cause.span, "higher-ranked subtype error"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +147,7 @@ trait TypeOpInfo<'tcx> {
|
|||
{
|
||||
adjusted
|
||||
} else {
|
||||
self.fallback_error(tcx, cause.span).buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(self.fallback_error(tcx, cause.span));
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -178,9 +176,9 @@ trait TypeOpInfo<'tcx> {
|
|||
let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region);
|
||||
|
||||
if let Some(nice_error) = nice_error {
|
||||
nice_error.buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(nice_error);
|
||||
} else {
|
||||
self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(self.fallback_error(tcx, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if move_out_indices.is_empty() {
|
||||
let root_place = PlaceRef { projection: &[], ..used_place };
|
||||
|
||||
self.set_tainted_by_errors();
|
||||
if !self.uninitialized_error_reported.insert(root_place) {
|
||||
debug!(
|
||||
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
|
||||
|
@ -104,7 +105,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
|
||||
);
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
} else {
|
||||
if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) {
|
||||
if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) {
|
||||
|
@ -216,6 +217,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
place_name, partially_str, loop_message
|
||||
),
|
||||
);
|
||||
self.set_tainted_by_errors();
|
||||
if self.fn_self_span_reported.insert(fn_span) {
|
||||
err.span_note(
|
||||
// Check whether the source is accessible
|
||||
|
@ -297,6 +299,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
// Avoid pointing to the same function in multiple different
|
||||
// error messages.
|
||||
self.set_tainted_by_errors();
|
||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span)
|
||||
{
|
||||
err.span_note(
|
||||
|
@ -449,6 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.set_tainted_by_errors();
|
||||
if let Some((_, mut old_err)) =
|
||||
self.move_error_reported.insert(move_out_indices, (used_place, err))
|
||||
{
|
||||
|
@ -503,7 +507,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
Some(borrow_span),
|
||||
None,
|
||||
);
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
pub(crate) fn report_use_while_mutably_borrowed(
|
||||
|
@ -1012,6 +1016,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
self.set_tainted_by_errors();
|
||||
self.access_place_error_reported.insert((
|
||||
Place { local: root_place.local, projection: root_place_projection },
|
||||
borrow_span,
|
||||
|
@ -1021,7 +1026,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
|
||||
let err =
|
||||
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1113,7 +1118,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
),
|
||||
};
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn report_local_value_does_not_live_long_enough(
|
||||
|
@ -1295,7 +1300,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
None,
|
||||
);
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn report_thread_local_value_does_not_live_long_enough(
|
||||
|
@ -1810,7 +1815,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
loan.kind.describe_mutability(),
|
||||
);
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1836,7 +1841,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
self.explain_deref_coercion(loan, &mut err);
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>) {
|
||||
|
@ -1938,7 +1943,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
err.span_label(span, msg);
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
|
||||
|
|
|
@ -264,7 +264,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
self.add_move_hints(error, &mut err, err_span);
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
fn report_cannot_move_from_static(
|
||||
|
|
|
@ -626,7 +626,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
|
||||
/// User cannot make signature of a trait mutable without changing the
|
||||
|
|
|
@ -256,6 +256,6 @@ impl OutlivesSuggestionBuilder {
|
|||
diag.sort_span = mir_span.shrink_to_hi();
|
||||
|
||||
// Buffer the diagnostic
|
||||
diag.buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(diag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,14 +168,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let type_test_span = type_test.locations.span(&self.body);
|
||||
|
||||
if let Some(lower_bound_region) = lower_bound_region {
|
||||
self.infcx
|
||||
.construct_generic_bound_failure(
|
||||
self.buffer_error(self.infcx.construct_generic_bound_failure(
|
||||
type_test_span,
|
||||
None,
|
||||
type_test.generic_kind,
|
||||
lower_bound_region,
|
||||
)
|
||||
.buffer(&mut self.errors_buffer);
|
||||
));
|
||||
} else {
|
||||
// FIXME. We should handle this case better. It
|
||||
// indicates that we have e.g., some region variable
|
||||
|
@ -186,27 +184,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
// to report it; we could probably handle it by
|
||||
// iterating over the universal regions and reporting
|
||||
// an error that multiple bounds are required.
|
||||
self.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
self.buffer_error(self.infcx.tcx.sess.struct_span_err(
|
||||
type_test_span,
|
||||
&format!("`{}` does not live long enough", type_test.generic_kind),
|
||||
)
|
||||
.buffer(&mut self.errors_buffer);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
|
||||
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
|
||||
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
|
||||
unexpected_hidden_region_diagnostic(
|
||||
self.buffer_error(unexpected_hidden_region_diagnostic(
|
||||
self.infcx.tcx,
|
||||
span,
|
||||
named_ty,
|
||||
named_region,
|
||||
)
|
||||
.buffer(&mut self.errors_buffer);
|
||||
));
|
||||
}
|
||||
|
||||
RegionErrorKind::BoundUniversalRegionError {
|
||||
|
@ -285,7 +278,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
|
||||
let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
|
||||
if let Some(diag) = nice.try_report_from_nll() {
|
||||
diag.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(diag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +368,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
diag.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(diag);
|
||||
}
|
||||
|
||||
/// Report a specialized error when `FnMut` closures return a reference to a captured variable.
|
||||
|
|
|
@ -313,6 +313,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
move_error_reported: BTreeMap::new(),
|
||||
uninitialized_error_reported: Default::default(),
|
||||
errors_buffer,
|
||||
tainted_by_errors: false,
|
||||
regioncx: regioncx.clone(),
|
||||
used_mut: Default::default(),
|
||||
used_mut_upvars: SmallVec::new(),
|
||||
|
@ -346,6 +347,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
move_error_reported: BTreeMap::new(),
|
||||
uninitialized_error_reported: Default::default(),
|
||||
errors_buffer,
|
||||
tainted_by_errors: false,
|
||||
regioncx: Rc::clone(®ioncx),
|
||||
used_mut: Default::default(),
|
||||
used_mut_upvars: SmallVec::new(),
|
||||
|
@ -398,7 +400,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
diag.message = initial_diag.styled_message().clone();
|
||||
diag.span = initial_diag.span.clone();
|
||||
|
||||
diag.buffer(&mut mbcx.errors_buffer);
|
||||
mbcx.buffer_error(diag);
|
||||
},
|
||||
);
|
||||
initial_diag.cancel();
|
||||
|
@ -423,7 +425,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals);
|
||||
|
||||
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
|
||||
let used_mut = mbcx.used_mut;
|
||||
let used_mut = std::mem::take(&mut mbcx.used_mut);
|
||||
for local in mbcx.body.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) {
|
||||
let local_decl = &mbcx.body.local_decls[local];
|
||||
let lint_root = match &mbcx.body.source_scopes[local_decl.source_info.scope].local_data {
|
||||
|
@ -461,8 +463,8 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
}
|
||||
|
||||
// Buffer any move errors that we collected and de-duplicated.
|
||||
for (_, (_, diag)) in mbcx.move_error_reported {
|
||||
diag.buffer(&mut mbcx.errors_buffer);
|
||||
for (_, (_, diag)) in std::mem::take(&mut mbcx.move_error_reported) {
|
||||
mbcx.buffer_error(diag);
|
||||
}
|
||||
|
||||
if !mbcx.errors_buffer.is_empty() {
|
||||
|
@ -477,6 +479,7 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
concrete_opaque_types: opaque_type_values,
|
||||
closure_requirements: opt_closure_req,
|
||||
used_mut_upvars: mbcx.used_mut_upvars,
|
||||
tainted_by_errors: mbcx.tainted_by_errors,
|
||||
};
|
||||
|
||||
let body_with_facts = if return_body_with_facts {
|
||||
|
@ -573,6 +576,8 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
|
|||
uninitialized_error_reported: FxHashSet<PlaceRef<'tcx>>,
|
||||
/// Errors to be reported buffer
|
||||
errors_buffer: Vec<Diagnostic>,
|
||||
/// Set to true if we emit an error during borrowck
|
||||
tainted_by_errors: bool,
|
||||
/// This field keeps track of all the local variables that are declared mut and are mutated.
|
||||
/// Used for the warning issued by an unused mutable local variable.
|
||||
used_mut: FxHashSet<Local>,
|
||||
|
@ -1028,6 +1033,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
if conflict_error || mutability_error {
|
||||
debug!("access_place: logging error place_span=`{:?}` kind=`{:?}`", place_span, kind);
|
||||
|
||||
self.set_tainted_by_errors();
|
||||
self.access_place_error_reported.insert((place_span.0, place_span.1));
|
||||
}
|
||||
}
|
||||
|
@ -1107,12 +1113,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
error_reported = true;
|
||||
match kind {
|
||||
ReadKind::Copy => {
|
||||
this.report_use_while_mutably_borrowed(location, place_span, borrow)
|
||||
.buffer(&mut this.errors_buffer);
|
||||
let err = this
|
||||
.report_use_while_mutably_borrowed(location, place_span, borrow);
|
||||
this.buffer_error(err);
|
||||
}
|
||||
ReadKind::Borrow(bk) => {
|
||||
this.report_conflicting_borrow(location, place_span, bk, borrow)
|
||||
.buffer(&mut this.errors_buffer);
|
||||
let err =
|
||||
this.report_conflicting_borrow(location, place_span, bk, borrow);
|
||||
this.buffer_error(err);
|
||||
}
|
||||
}
|
||||
Control::Break
|
||||
|
@ -1162,8 +1170,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
error_reported = true;
|
||||
match kind {
|
||||
WriteKind::MutableBorrow(bk) => {
|
||||
this.report_conflicting_borrow(location, place_span, bk, borrow)
|
||||
.buffer(&mut this.errors_buffer);
|
||||
let err =
|
||||
this.report_conflicting_borrow(location, place_span, bk, borrow);
|
||||
this.buffer_error(err);
|
||||
}
|
||||
WriteKind::StorageDeadOrDrop => this
|
||||
.report_borrowed_value_does_not_live_long_enough(
|
||||
|
@ -1570,7 +1579,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
yield_span,
|
||||
);
|
||||
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
self.buffer_error(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2299,6 +2308,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
|
||||
path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body())
|
||||
}
|
||||
|
||||
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
|
||||
self.tainted_by_errors = true;
|
||||
t.buffer(&mut self.errors_buffer);
|
||||
}
|
||||
|
||||
pub fn set_tainted_by_errors(&mut self) {
|
||||
self.tainted_by_errors = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// The degree of overlap between 2 places for borrow-checking.
|
||||
|
|
|
@ -418,6 +418,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
|
|||
err.note(&format!("Inferred opaque type values:\n{:#?}", opaque_type_values));
|
||||
}
|
||||
|
||||
// FIXME(compiler-errors): Maybe we need to set tainted here
|
||||
err.buffer(errors_buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ pub struct BorrowCheckResult<'tcx> {
|
|||
pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
|
||||
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
|
||||
pub used_mut_upvars: SmallVec<[Field; 8]>,
|
||||
pub tainted_by_errors: bool,
|
||||
}
|
||||
|
||||
/// The result of the `mir_const_qualif` query.
|
||||
|
|
Loading…
Add table
Reference in a new issue