Fix incorrect use mut diagnostics
This commit is contained in:
parent
604cbdcfdd
commit
c748f32ee4
14 changed files with 129 additions and 72 deletions
|
@ -345,7 +345,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
let upvar = &self.upvars[upvar_field.unwrap().index()];
|
||||
let upvar_hir_id = upvar.var_hir_id;
|
||||
// FIXME(project-rfc-2229#8): Improve borrow-check diagnostics in case of precise
|
||||
// capture.
|
||||
let upvar_hir_id = upvar.place.get_root_variable();
|
||||
let upvar_name = upvar.name;
|
||||
let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
|
||||
|
||||
|
|
|
@ -64,12 +64,29 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
|
||||
reason = ", as it is not declared as mutable".to_string();
|
||||
let imm_borrow_derefed = self.upvars[upvar_index.index()]
|
||||
.place
|
||||
.place
|
||||
.deref_tys()
|
||||
.any(|ty| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)));
|
||||
|
||||
// If the place is immutable then:
|
||||
//
|
||||
// - Either we deref a immutable ref to get to our final place.
|
||||
// - We don't capture derefs of raw ptrs
|
||||
// - Or the final place is immut because the root variable of the capture
|
||||
// isn't marked mut and we should suggest that to the user.
|
||||
if imm_borrow_derefed {
|
||||
// If we deref an immutable ref then the suggestion here doesn't help.
|
||||
return;
|
||||
} else {
|
||||
let name = self.upvars[upvar_index.index()].name;
|
||||
reason = format!(", as `{}` is not declared as mutable", name);
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
|
||||
reason = ", as it is not declared as mutable".to_string();
|
||||
} else {
|
||||
let name = self.upvars[upvar_index.index()].name;
|
||||
reason = format!(", as `{}` is not declared as mutable", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,9 +276,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
let captured_place = &self.upvars[upvar_index.index()].place;
|
||||
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
|
||||
let upvar_hir_id = self.upvars[upvar_index.index()].var_hir_id;
|
||||
let upvar_hir_id = captured_place.get_root_variable();
|
||||
|
||||
if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) {
|
||||
if let hir::PatKind::Binding(
|
||||
hir::BindingAnnotation::Unannotated,
|
||||
|
|
|
@ -12,7 +12,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
local_names: &IndexVec<Local, Option<Symbol>>,
|
||||
upvars: &[Upvar],
|
||||
upvars: &[Upvar<'tcx>],
|
||||
fr: RegionVid,
|
||||
) -> Option<(Option<Symbol>, Span)> {
|
||||
debug!("get_var_name_and_span_for_region(fr={:?})", fr);
|
||||
|
@ -21,6 +21,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
debug!("get_var_name_and_span_for_region: attempting upvar");
|
||||
self.get_upvar_index_for_region(tcx, fr)
|
||||
.map(|index| {
|
||||
// FIXME(project-rfc-2229#8): Use place span for diagnostics
|
||||
let (name, span) = self.get_upvar_name_and_span_for_region(tcx, upvars, index);
|
||||
(Some(name), span)
|
||||
})
|
||||
|
@ -59,10 +60,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
crate fn get_upvar_name_and_span_for_region(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
upvars: &[Upvar<'tcx>],
|
||||
upvar_index: usize,
|
||||
) -> (Symbol, Span) {
|
||||
let upvar_hir_id = upvars[upvar_index].var_hir_id;
|
||||
let upvar_hir_id = upvars[upvar_index].place.get_root_variable();
|
||||
debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id);
|
||||
|
||||
let upvar_name = tcx.hir().name(upvar_hir_id);
|
||||
|
|
|
@ -5,11 +5,10 @@ use rustc_data_structures::graph::dominators::Dominators;
|
|||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{HirId, Node};
|
||||
use rustc_hir::Node;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
|
||||
use rustc_middle::mir::{
|
||||
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
|
||||
PlaceRef, VarDebugInfoContents,
|
||||
|
@ -18,7 +17,7 @@ use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind
|
|||
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
|
||||
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
|
||||
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
|
||||
use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
|
||||
|
@ -73,16 +72,15 @@ crate use region_infer::RegionInferenceContext;
|
|||
|
||||
// FIXME(eddyb) perhaps move this somewhere more centrally.
|
||||
#[derive(Debug)]
|
||||
crate struct Upvar {
|
||||
crate struct Upvar<'tcx> {
|
||||
// FIXME(project-rfc-2229#8): ty::CapturePlace should have a to_string(), or similar
|
||||
// then this should not be needed.
|
||||
name: Symbol,
|
||||
|
||||
// FIXME(project-rfc-2229#8): This should use Place or something similar
|
||||
var_hir_id: HirId,
|
||||
place: CapturedPlace<'tcx>,
|
||||
|
||||
/// If true, the capture is behind a reference.
|
||||
by_ref: bool,
|
||||
|
||||
mutability: Mutability,
|
||||
}
|
||||
|
||||
const DEREF_PROJECTION: &[PlaceElem<'_>; 1] = &[ProjectionElem::Deref];
|
||||
|
@ -161,21 +159,13 @@ fn do_mir_borrowck<'a, 'tcx>(
|
|||
let upvars: Vec<_> = tables
|
||||
.closure_min_captures_flattened(def.did.to_def_id())
|
||||
.map(|captured_place| {
|
||||
let var_hir_id = match captured_place.place.base {
|
||||
HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
|
||||
_ => bug!("Expected upvar"),
|
||||
};
|
||||
let var_hir_id = captured_place.get_root_variable();
|
||||
let capture = captured_place.info.capture_kind;
|
||||
let by_ref = match capture {
|
||||
ty::UpvarCapture::ByValue(_) => false,
|
||||
ty::UpvarCapture::ByRef(..) => true,
|
||||
};
|
||||
Upvar {
|
||||
name: tcx.hir().name(var_hir_id),
|
||||
var_hir_id,
|
||||
by_ref,
|
||||
mutability: captured_place.mutability,
|
||||
}
|
||||
Upvar { name: tcx.hir().name(var_hir_id), place: captured_place.clone(), by_ref }
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -544,7 +534,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
|
|||
dominators: Dominators<BasicBlock>,
|
||||
|
||||
/// Information about upvars not necessarily preserved in types or MIR
|
||||
upvars: Vec<Upvar>,
|
||||
upvars: Vec<Upvar<'tcx>>,
|
||||
|
||||
/// Names of local (user) variables (extracted from `var_debug_info`).
|
||||
local_names: IndexVec<Local, Option<Symbol>>,
|
||||
|
@ -2251,7 +2241,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
place={:?}",
|
||||
upvar, is_local_mutation_allowed, place
|
||||
);
|
||||
match (upvar.mutability, is_local_mutation_allowed) {
|
||||
match (upvar.place.mutability, is_local_mutation_allowed) {
|
||||
(
|
||||
Mutability::Not,
|
||||
LocalMutationIsAllowed::No
|
||||
|
|
|
@ -165,7 +165,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
|
|||
flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
upvars: &[Upvar<'tcx>],
|
||||
) -> NllOutput<'tcx> {
|
||||
let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool {
|
|||
/// of a closure type.
|
||||
pub(crate) fn is_upvar_field_projection(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
upvars: &[Upvar],
|
||||
upvars: &[Upvar<'tcx>],
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
) -> Option<Field> {
|
||||
|
|
|
@ -132,7 +132,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
elements: &Rc<RegionValueElements>,
|
||||
upvars: &[Upvar],
|
||||
upvars: &[Upvar<'tcx>],
|
||||
) -> MirTypeckResults<'tcx> {
|
||||
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
|
||||
let mut constraints = MirTypeckRegionConstraints {
|
||||
|
@ -821,7 +821,7 @@ struct BorrowCheckContext<'a, 'tcx> {
|
|||
all_facts: &'a mut Option<AllFacts>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||
upvars: &'a [Upvar],
|
||||
upvars: &'a [Upvar<'tcx>],
|
||||
}
|
||||
|
||||
crate struct MirTypeckResults<'tcx> {
|
||||
|
@ -2490,7 +2490,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
body,
|
||||
);
|
||||
let category = if let Some(field) = field {
|
||||
ConstraintCategory::ClosureUpvar(self.borrowck_context.upvars[field.index()].var_hir_id)
|
||||
let var_hir_id = self.borrowck_context.upvars[field.index()].place.get_root_variable();
|
||||
// FIXME(project-rfc-2229#8): Use Place for better diagnostics
|
||||
ConstraintCategory::ClosureUpvar(var_hir_id)
|
||||
} else {
|
||||
ConstraintCategory::Boring
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue