diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index f7c20542cbf2e..6c076265db639 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -708,7 +708,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> { let span = err.span.clone(); - let msg = match err.code { + match err.code { err_mutbl => { let descr = match err.cmt.note { mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => { @@ -732,10 +732,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { match err.cause { MutabilityViolation => { - format!("cannot assign to {}", descr) + struct_span_err!(self.tcx.sess, span, E0594, "cannot assign to {}", descr) } BorrowViolation(euv::ClosureCapture(_)) => { - format!("closure cannot assign to {}", descr) + struct_span_err!(self.tcx.sess, span, E0595, + "closure cannot assign to {}", descr) } BorrowViolation(euv::OverloadedOperator) | BorrowViolation(euv::AddrOf) | @@ -744,7 +745,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { BorrowViolation(euv::AutoUnsafe) | BorrowViolation(euv::ForLoop) | BorrowViolation(euv::MatchDiscriminant) => { - format!("cannot borrow {} as mutable", descr) + struct_span_err!(self.tcx.sess, span, E0596, + "cannot borrow {} as mutable", descr) } BorrowViolation(euv::ClosureInvocation) => { span_bug!(err.span, @@ -759,17 +761,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { format!("`{}`", self.loan_path_to_string(&lp)) } }; - format!("{} does not live long enough", msg) + struct_span_err!(self.tcx.sess, span, E0597, "{} does not live long enough", msg) } err_borrowed_pointer_too_short(..) => { let descr = self.cmt_to_path_or_string(&err.cmt); - format!("lifetime of {} is too short to guarantee \ - its contents can be safely reborrowed", - descr) + struct_span_err!(self.tcx.sess, span, E0598, + "lifetime of {} is too short to guarantee \ + its contents can be safely reborrowed", + descr) } - }; - - self.struct_span_err(span, &msg) + } } pub fn report_aliasability_violation(&self, @@ -1176,7 +1177,7 @@ before rustc 1.16, this temporary lived longer - see issue #39283 \ if kind == ty::ClosureKind::Fn { db.span_help(self.tcx.hir.span(upvar_id.closure_expr_id), "consider changing this closure to take \ - self by mutable reference"); + self by mutable reference"); } } _ => { diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index bfd342a9f2134..2a38dcfd26e1a 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -1114,9 +1114,63 @@ fn main() { ``` "##, +E0596: r##" +This error occurs because you tried to mutably borrow a non-mutable variable. + +Example of erroneous code: + +```compile_fail,E0596 +let x = 1; +let y = &mut x; // error: cannot borrow mutably +``` + +In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it +fails. To fix this error, you need to make `x` mutable: + +``` +let mut x = 1; +let y = &mut x; // ok! +``` +"##, + +E0597: r##" +This error occurs because a borrow was made inside a variable which has a +greater lifetime than the borrowed one. + +Example of erroneous code: + +```compile_fail,E0597 +struct Foo<'a> { + x: Option<&'a u32>, +} + +let mut x = Foo { x: None }; +let y = 0; +x.x = Some(&y); // error: `y` does not live long enough +``` + +In here, `x` is created before `y` and therefore has a greater lifetime. Always +keep in mind that values in a scope are dropped in the opposite order they are +created. So to fix the previous example, just make the `y` lifetime greater than +the `x`'s one: + +``` +struct Foo<'a> { + x: Option<&'a u32>, +} + +let y = 0; +let mut x = Foo { x: None }; +x.x = Some(&y); +``` +"##, + } register_diagnostics! { // E0385, // {} in an aliasable location E0524, // two closures require unique access to `..` at the same time + E0594, // cannot assign to {} + E0595, // closure cannot assign to {} + E0598, // lifetime of {} is too short to guarantee its contents can be... } diff --git a/src/test/compile-fail/E0596.rs b/src/test/compile-fail/E0596.rs new file mode 100644 index 0000000000000..1f1af69d97768 --- /dev/null +++ b/src/test/compile-fail/E0596.rs @@ -0,0 +1,14 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let x = 1; + let y = &mut x; //~ ERROR E0596 +} diff --git a/src/test/compile-fail/E0597.rs b/src/test/compile-fail/E0597.rs new file mode 100644 index 0000000000000..00ef14a8e2af0 --- /dev/null +++ b/src/test/compile-fail/E0597.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo<'a> { + x: Option<&'a u32>, +} + +fn main() { + let mut x = Foo { x: None }; + let y = 0; + x.x = Some(&y); +} //~ `y` does not live long enough [E0597]