-
- let mut err;
- let item_msg = match self.describe_place(place) {
- Some(name) => format!("immutable item `{}`", name),
- None => "immutable item".to_owned(),
- };
-
- // `act` and `acted_on` are strings that let us abstract over
- // the verbs used in some diagnostic messages.
- let act;
- let acted_on;
-
- match error_access {
- AccessKind::Mutate => {
- let item_msg = match the_place_err {
- Place::Projection(box Projection {
- base: _,
- elem: ProjectionElem::Deref,
- }) => match self.describe_place(place) {
- Some(description) => {
- format!("`{}` which is behind a `&` reference", description)
- }
- None => format!("data in a `&` reference"),
- },
- _ => item_msg,
- };
- err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
- act = "assign";
- acted_on = "written";
- }
- AccessKind::MutableBorrow => {
- err = self
- .tcx
- .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
- act = "borrow as mutable";
- acted_on = "borrowed as mutable";
- }
- }
-
- match the_place_err {
- // We want to suggest users use `let mut` for local (user
- // variable) mutations...
- Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
- // ... but it doesn't make sense to suggest it on
- // variables that are `ref x`, `ref mut x`, `&self`,
- // or `&mut self` (such variables are simply not
- // mutable)..
- let local_decl = &self.mir.local_decls[*local];
- assert_eq!(local_decl.mutability, Mutability::Not);
-
- err.span_label(span, format!("cannot {ACT}", ACT = act));
- err.span_suggestion(
- local_decl.source_info.span,
- "consider changing this to be mutable",
- format!("mut {}", local_decl.name.unwrap()),
- );
- }
-
- // complete hack to approximate old AST-borrowck
- // diagnostic: if the span starts with a mutable borrow of
- // a local variable, then just suggest the user remove it.
- Place::Local(_)
- if {
- if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
- snippet.starts_with("&mut ")
- } else {
- false
- }
- } =>
- {
- err.span_label(span, format!("cannot {ACT}", ACT = act));
- err.span_label(span, "try removing `&mut` here");
- }
-
- // We want to point out when a `&` can be readily replaced
- // with an `&mut`.
- //
- // FIXME: can this case be generalized to work for an
- // arbitrary base for the projection?
- Place::Projection(box Projection {
- base: Place::Local(local),
- elem: ProjectionElem::Deref,
- }) if self.mir.local_decls[*local].is_nonref_binding() =>
- {
- let (err_help_span, suggested_code) =
- find_place_to_suggest_ampmut(self.tcx, self.mir, *local);
- err.span_suggestion(
- err_help_span,
- "consider changing this to be a mutable reference",
- suggested_code,
- );
-
- let local_decl = &self.mir.local_decls[*local];
- if let Some(name) = local_decl.name {
- err.span_label(
- span,
- format!(
- "`{NAME}` is a `&` reference, \
- so the data it refers to cannot be {ACTED_ON}",
- NAME = name,
- ACTED_ON = acted_on
- ),
- );
- } else {
- err.span_label(
- span,
- format!("cannot {ACT} through `&`-reference", ACT = act),
- );
- }
- }
-
- _ => {
- err.span_label(span, format!("cannot {ACT}", ACT = act));
- }
- }
-
- err.emit();