1
Fork 0

Move E0507 diagnostic into mod borrowck_errors shared between ast- and mir-borrowck.

(Had to modify signature of `report_cannot_move_out_of` slightly to
satisfy requirements of newly added `fn cannot_move_out_of` method.)
This commit is contained in:
Felix S. Klock II 2017-10-03 15:34:52 +02:00
parent eabef0608b
commit a12cefb497
4 changed files with 143 additions and 136 deletions

View file

@ -14,6 +14,7 @@ use rustc::middle::mem_categorization::Categorization;
use rustc::middle::mem_categorization::NoteClosureEnv;
use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
use rustc::ty;
use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
use syntax::ast;
use syntax_pos;
use errors::DiagnosticBuilder;
@ -134,7 +135,7 @@ fn group_errors_with_same_origin<'tcx>(errors: &Vec<MoveError<'tcx>>)
}
// (keep in sync with gather_moves::check_and_get_illegal_move_origin )
fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
move_from: mc::cmt<'tcx>)
-> DiagnosticBuilder<'a> {
match move_from.cat {
@ -142,16 +143,9 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
Categorization::Deref(_, mc::Implicit(..)) |
Categorization::Deref(_, mc::UnsafePtr(..)) |
Categorization::StaticItem => {
let mut err = struct_span_err!(bccx, move_from.span, E0507,
"cannot move out of {}",
move_from.descriptive_string(bccx.tcx));
err.span_label(
move_from.span,
format!("cannot move out of {}", move_from.descriptive_string(bccx.tcx))
);
err
bccx.cannot_move_out_of(
move_from.span, &move_from.descriptive_string(bccx.tcx), Origin::Ast)
}
Categorization::Interior(ref b, mc::InteriorElement(ik)) => {
let type_name = match (&b.ty.sty, ik) {
(&ty::TyArray(_, _), Kind::Index) => "array",

View file

@ -317,132 +317,6 @@ fn main() {
```
"##,
E0507: r##"
You tried to move out of a value which was borrowed. Erroneous code example:
```compile_fail,E0507
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
}
```
Here, the `nothing_is_true` method takes the ownership of `self`. However,
`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
which is a borrow of the content owned by the `RefCell`. To fix this error,
you have three choices:
* Try to avoid moving the variable.
* Somehow reclaim the ownership.
* Implement the `Copy` trait on the type.
Examples:
```
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(&self) {} // First case, we don't take ownership
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // ok!
}
```
Or:
```
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
let x = x.into_inner(); // we get back ownership
x.nothing_is_true(); // ok!
}
```
Or:
```
use std::cell::RefCell;
#[derive(Clone, Copy)] // we implement the Copy trait
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // ok!
}
```
Moving a member out of a mutably borrowed struct will also cause E0507 error:
```compile_fail,E0507
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
struct Batcave {
knight: TheDarkKnight
}
fn main() {
let mut cave = Batcave {
knight: TheDarkKnight
};
let borrowed = &mut cave;
borrowed.knight.nothing_is_true(); // E0507
}
```
It is fine only if you put something back. `mem::replace` can be used for that:
```
# struct TheDarkKnight;
# impl TheDarkKnight { fn nothing_is_true(self) {} }
# struct Batcave { knight: TheDarkKnight }
use std::mem;
let mut cave = Batcave {
knight: TheDarkKnight
};
let borrowed = &mut cave;
mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
```
You can find more information about borrowing in the rust-book:
http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
"##,
E0508: r##"
A value was moved out of a non-copy fixed-size array.

View file

@ -999,6 +999,133 @@ fn print_fancy_ref(fancy_ref: &FancyNum){
```
"##,
E0507: r##"
You tried to move out of a value which was borrowed. Erroneous code example:
```compile_fail,E0507
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
}
```
Here, the `nothing_is_true` method takes the ownership of `self`. However,
`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
which is a borrow of the content owned by the `RefCell`. To fix this error,
you have three choices:
* Try to avoid moving the variable.
* Somehow reclaim the ownership.
* Implement the `Copy` trait on the type.
Examples:
```
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(&self) {} // First case, we don't take ownership
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // ok!
}
```
Or:
```
use std::cell::RefCell;
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
let x = x.into_inner(); // we get back ownership
x.nothing_is_true(); // ok!
}
```
Or:
```
use std::cell::RefCell;
#[derive(Clone, Copy)] // we implement the Copy trait
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
fn main() {
let x = RefCell::new(TheDarkKnight);
x.borrow().nothing_is_true(); // ok!
}
```
Moving a member out of a mutably borrowed struct will also cause E0507 error:
```compile_fail,E0507
struct TheDarkKnight;
impl TheDarkKnight {
fn nothing_is_true(self) {}
}
struct Batcave {
knight: TheDarkKnight
}
fn main() {
let mut cave = Batcave {
knight: TheDarkKnight
};
let borrowed = &mut cave;
borrowed.knight.nothing_is_true(); // E0507
}
```
It is fine only if you put something back. `mem::replace` can be used for that:
```
# struct TheDarkKnight;
# impl TheDarkKnight { fn nothing_is_true(self) {} }
# struct Batcave { knight: TheDarkKnight }
use std::mem;
let mut cave = Batcave {
knight: TheDarkKnight
};
let borrowed = &mut cave;
mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
```
You can find more information about borrowing in the rust-book:
http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
"##,
}
register_diagnostics! {

View file

@ -191,6 +191,18 @@ pub trait BorrowckErrors {
{
self.cannot_assign(span, &format!("immutable static item `{}`", desc), o)
}
fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin)
-> DiagnosticBuilder
{
let mut err = struct_span_err!(self, move_from_span, E0507,
"cannot move out of {}{OGN}",
move_from_desc, OGN=o);
err.span_label(
move_from_span,
format!("cannot move out of {}", move_from_desc));
err
}
}
impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> {