Skip to content

Commit c47b2a9

Browse files
committed
guarantee working no projection place when reporting mutability error
1 parent 7da7205 commit c47b2a9

File tree

1 file changed

+85
-83
lines changed

1 file changed

+85
-83
lines changed

src/librustc_mir/borrow_check/mutability_errors.rs

Lines changed: 85 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -195,98 +195,100 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
195195
match projection {
196196
ProjectionElem::Deref => {
197197
if let PlaceBase::Local(local) = base_place.base {
198-
match self.mir.local_decls[local].is_user_variable {
199-
Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) => {
200-
err.span_label(span, format!("cannot {ACT}", ACT = act));
201-
err.note(
202-
"variables bound in patterns are \
203-
immutable until the end of the pattern guard",
204-
);
205-
}
206-
Some(_) => {
207-
// We want to point out when a `&` can be readily replaced
208-
// with an `&mut`.
209-
//
210-
// FIXME: can this case be generalized to work for an
211-
// arbitrary base for the projection?
212-
let local_decl = &self.mir.local_decls[local];
213-
let suggestion = match local_decl.is_user_variable.as_ref().unwrap()
214-
{
215-
ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
216-
Some(suggest_ampmut_self(self.tcx, local_decl))
217-
}
198+
if base_place.has_no_projection() {
199+
match self.mir.local_decls[local].is_user_variable {
200+
Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) => {
201+
err.span_label(span, format!("cannot {ACT}", ACT = act));
202+
err.note(
203+
"variables bound in patterns are \
204+
immutable until the end of the pattern guard",
205+
);
206+
}
207+
Some(_) => {
208+
// We want to point out when a `&` can be readily replaced
209+
// with an `&mut`.
210+
//
211+
// FIXME: can this case be generalized to work for an
212+
// arbitrary base for the projection?
213+
let local_decl = &self.mir.local_decls[local];
214+
let suggestion = match local_decl.is_user_variable.as_ref().unwrap()
215+
{
216+
ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
217+
Some(suggest_ampmut_self(self.tcx, local_decl))
218+
}
218219

219-
ClearCrossCrate::Set(mir::BindingForm::Var(
220-
mir::VarBindingForm {
221-
binding_mode: ty::BindingMode::BindByValue(_),
222-
opt_ty_info,
223-
..
224-
},
225-
)) => Some(suggest_ampmut(
226-
self.tcx,
227-
self.mir,
228-
local,
229-
local_decl,
230-
*opt_ty_info,
231-
)),
220+
ClearCrossCrate::Set(mir::BindingForm::Var(
221+
mir::VarBindingForm {
222+
binding_mode: ty::BindingMode::BindByValue(_),
223+
opt_ty_info,
224+
..
225+
},
226+
)) => Some(suggest_ampmut(
227+
self.tcx,
228+
self.mir,
229+
local,
230+
local_decl,
231+
*opt_ty_info,
232+
)),
232233

233-
ClearCrossCrate::Set(mir::BindingForm::Var(
234-
mir::VarBindingForm {
235-
binding_mode: ty::BindingMode::BindByReference(_),
236-
..
237-
},
238-
)) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
234+
ClearCrossCrate::Set(mir::BindingForm::Var(
235+
mir::VarBindingForm {
236+
binding_mode: ty::BindingMode::BindByReference(_),
237+
..
238+
},
239+
)) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
239240

240-
ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => {
241-
unreachable!()
242-
}
241+
ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => {
242+
unreachable!()
243+
}
243244

244-
ClearCrossCrate::Clear => bug!("saw cleared local state"),
245-
};
245+
ClearCrossCrate::Clear => bug!("saw cleared local state"),
246+
};
246247

247-
let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr()
248-
{
249-
("&", "reference")
250-
} else {
251-
("*const", "pointer")
252-
};
248+
let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr()
249+
{
250+
("&", "reference")
251+
} else {
252+
("*const", "pointer")
253+
};
253254

254-
if let Some((err_help_span, suggested_code)) = suggestion {
255-
err.span_suggestion(
256-
err_help_span,
257-
&format!(
258-
"consider changing this to be a mutable {}",
259-
pointer_desc
260-
),
261-
suggested_code,
262-
);
263-
}
255+
if let Some((err_help_span, suggested_code)) = suggestion {
256+
err.span_suggestion(
257+
err_help_span,
258+
&format!(
259+
"consider changing this to be a mutable {}",
260+
pointer_desc
261+
),
262+
suggested_code,
263+
);
264+
}
264265

265-
if let Some(name) = local_decl.name {
266-
err.span_label(
267-
span,
268-
format!(
269-
"`{NAME}` is a `{SIGIL}` {DESC}, \
270-
so the data it refers to cannot be {ACTED_ON}",
271-
NAME = name,
272-
SIGIL = pointer_sigil,
273-
DESC = pointer_desc,
274-
ACTED_ON = acted_on
275-
),
276-
);
277-
} else {
278-
err.span_label(
279-
span,
280-
format!(
281-
"cannot {ACT} through `{SIGIL}` {DESC}",
282-
ACT = act,
283-
SIGIL = pointer_sigil,
284-
DESC = pointer_desc
285-
),
286-
);
266+
if let Some(name) = local_decl.name {
267+
err.span_label(
268+
span,
269+
format!(
270+
"`{NAME}` is a `{SIGIL}` {DESC}, \
271+
so the data it refers to cannot be {ACTED_ON}",
272+
NAME = name,
273+
SIGIL = pointer_sigil,
274+
DESC = pointer_desc,
275+
ACTED_ON = acted_on
276+
),
277+
);
278+
} else {
279+
err.span_label(
280+
span,
281+
format!(
282+
"cannot {ACT} through `{SIGIL}` {DESC}",
283+
ACT = act,
284+
SIGIL = pointer_sigil,
285+
DESC = pointer_desc
286+
),
287+
);
288+
}
287289
}
290+
_ => {}
288291
}
289-
_ => {}
290292
}
291293
if local == Local::new(1) && !self.mir.upvar_decls.is_empty() {
292294
err.span_label(span, format!("cannot {ACT}", ACT = act));

0 commit comments

Comments
 (0)