Skip to content

Commit

Permalink
Point to let when modifying field of immutable variable
Browse files Browse the repository at this point in the history
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
```
  • Loading branch information
estebank committed Mar 11, 2017
1 parent f573db4 commit 6ba494b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/librustc/middle/mem_categorization.rs
Expand Up @@ -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, ..) |
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_borrowck/borrowck/mod.rs
Expand Up @@ -659,6 +659,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 => {
Expand Down Expand Up @@ -708,6 +709,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)
}
Expand Down Expand Up @@ -738,6 +747,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
if let Some((span, msg)) = immutable_field {
db.span_label(span, &msg);
}
if let Some(span) = local_def {
db.span_label(span, &"this should be `mut`");
}
db
}

Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/did_you_mean/issue-39544.stderr
@@ -1,6 +1,8 @@
error: cannot borrow immutable field `z.x` as mutable
--> $DIR/issue-39544.rs:21:18
|
20 | let z = Z { x: X::Y };
| - this should be `mut`
21 | let _ = &mut z.x;
| ^^^

Expand Down

0 comments on commit 6ba494b

Please sign in to comment.