Skip to content

Commit 6ba494b

Browse files
committed
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 ```
1 parent f573db4 commit 6ba494b

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

src/librustc/middle/mem_categorization.rs

+15
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,21 @@ pub struct cmt_<'tcx> {
195195
pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
196196

197197
impl<'tcx> cmt_<'tcx> {
198+
pub fn get_def(&self) -> Option<ast::NodeId> {
199+
match self.cat {
200+
Categorization::Deref(ref cmt, ..) |
201+
Categorization::Interior(ref cmt, _) |
202+
Categorization::Downcast(ref cmt, _) => {
203+
if let Categorization::Local(nid) = cmt.cat {
204+
Some(nid)
205+
} else {
206+
None
207+
}
208+
}
209+
_ => None
210+
}
211+
}
212+
198213
pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
199214
match self.cat {
200215
Categorization::Deref(ref cmt, ..) |

src/librustc_borrowck/borrowck/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
659659
pub fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
660660
let span = err.span.clone();
661661
let mut immutable_field = None;
662+
let mut local_def = None;
662663

663664
let msg = &match err.code {
664665
err_mutbl => {
@@ -708,6 +709,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
708709
}
709710
None
710711
});
712+
local_def = err.cmt.get_def()
713+
.and_then(|nid| {
714+
if !self.tcx.hir.is_argument(nid) {
715+
Some(self.tcx.hir.span(nid))
716+
} else {
717+
None
718+
}
719+
});
711720

712721
format!("cannot borrow {} as mutable", descr)
713722
}
@@ -738,6 +747,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
738747
if let Some((span, msg)) = immutable_field {
739748
db.span_label(span, &msg);
740749
}
750+
if let Some(span) = local_def {
751+
db.span_label(span, &"this should be `mut`");
752+
}
741753
db
742754
}
743755

src/test/ui/did_you_mean/issue-39544.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error: cannot borrow immutable field `z.x` as mutable
22
--> $DIR/issue-39544.rs:21:18
33
|
4+
20 | let z = Z { x: X::Y };
5+
| - this should be `mut`
46
21 | let _ = &mut z.x;
57
| ^^^
68

0 commit comments

Comments
 (0)