Rollup merge of #40445 - estebank:issue-18150, r=jonathandturner
Point to let when modifying field of immutable variable Point at the immutable local variable when trying to modify one of its fields. Given a file: ```rust struct Foo { pub v: Vec<String> } fn main() { let f = Foo { v: Vec::new() }; f.v.push("cat".to_string()); } ``` present the following output: ``` error: cannot borrow immutable field `f.v` as mutable --> file.rs:7:13 | 6 | let f = Foo { v: Vec::new() }; | - this should be `mut` 7 | f.v.push("cat".to_string()); | ^^^ error: aborting due to previous error ``` Fix #27593.
This commit is contained in:
commit
9032ceae97
|
@ -195,6 +195,21 @@ pub struct cmt_<'tcx> {
|
|||
pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
|
||||
|
||||
impl<'tcx> cmt_<'tcx> {
|
||||
pub fn get_def(&self) -> Option<ast::NodeId> {
|
||||
match self.cat {
|
||||
Categorization::Deref(ref cmt, ..) |
|
||||
Categorization::Interior(ref cmt, _) |
|
||||
Categorization::Downcast(ref cmt, _) => {
|
||||
if let Categorization::Local(nid) = cmt.cat {
|
||||
Some(nid)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
|
||||
match self.cat {
|
||||
Categorization::Deref(ref cmt, ..) |
|
||||
|
|
|
@ -662,6 +662,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||
pub fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
|
||||
let span = err.span.clone();
|
||||
let mut immutable_field = None;
|
||||
let mut local_def = None;
|
||||
|
||||
let msg = &match err.code {
|
||||
err_mutbl => {
|
||||
|
@ -711,6 +712,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||
}
|
||||
None
|
||||
});
|
||||
local_def = err.cmt.get_def()
|
||||
.and_then(|nid| {
|
||||
if !self.tcx.hir.is_argument(nid) {
|
||||
Some(self.tcx.hir.span(nid))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
format!("cannot borrow {} as mutable", descr)
|
||||
}
|
||||
|
@ -741,6 +750,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
|||
if let Some((span, msg)) = immutable_field {
|
||||
db.span_label(span, &msg);
|
||||
}
|
||||
if let Some(let_span) = local_def {
|
||||
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
|
||||
db.span_label(let_span, &format!("consider changing this to `mut {}`", snippet));
|
||||
}
|
||||
}
|
||||
db
|
||||
}
|
||||
|
||||
|
@ -1109,6 +1123,11 @@ before rustc 1.16, this temporary lived longer - see issue #39283 \
|
|||
} else {
|
||||
db.span_label(*error_span, &format!("cannot borrow mutably"));
|
||||
}
|
||||
} else if let Categorization::Interior(ref cmt, _) = err.cmt.cat {
|
||||
if let mc::MutabilityCategory::McImmutable = cmt.mutbl {
|
||||
db.span_label(*error_span,
|
||||
&"cannot mutably borrow immutable field");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
error: cannot borrow immutable field `z.x` as mutable
|
||||
--> $DIR/issue-39544.rs:21:18
|
||||
|
|
||||
20 | let z = Z { x: X::Y };
|
||||
| - consider changing this to `mut z`
|
||||
21 | let _ = &mut z.x;
|
||||
| ^^^
|
||||
| ^^^ cannot mutably borrow immutable field
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Reference in New Issue