diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index eed8f82b5d853..43e9cdd73c433 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -464,40 +464,36 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { match (new_loan.kind, old_loan.kind) { (ty::MutBorrow, ty::MutBorrow) => { - self.bccx.span_err( - new_loan.span, - &format!("cannot borrow `{}`{} as mutable \ - more than once at a time", - nl, new_loan_msg)) + span_err!(self.bccx, new_loan.span, E0499, + "cannot borrow `{}`{} as mutable \ + more than once at a time", + nl, new_loan_msg); } (ty::UniqueImmBorrow, _) => { - self.bccx.span_err( - new_loan.span, - &format!("closure requires unique access to `{}` \ - but {} is already borrowed{}", - nl, ol_pronoun, old_loan_msg)); + span_err!(self.bccx, new_loan.span, E0500, + "closure requires unique access to `{}` \ + but {} is already borrowed{}", + nl, ol_pronoun, old_loan_msg); } (_, ty::UniqueImmBorrow) => { - self.bccx.span_err( - new_loan.span, - &format!("cannot borrow `{}`{} as {} because \ - previous closure requires unique access", - nl, new_loan_msg, new_loan.kind.to_user_str())); + span_err!(self.bccx, new_loan.span, E0501, + "cannot borrow `{}`{} as {} because \ + previous closure requires unique access", + nl, new_loan_msg, new_loan.kind.to_user_str()); } (_, _) => { - self.bccx.span_err( - new_loan.span, - &format!("cannot borrow `{}`{} as {} because \ - {} is also borrowed as {}{}", - nl, - new_loan_msg, - new_loan.kind.to_user_str(), - ol_pronoun, - old_loan.kind.to_user_str(), - old_loan_msg)); + span_err!(self.bccx, new_loan.span, E0502, + "cannot borrow `{}`{} as {} because \ + {} is also borrowed as {}{}", + nl, + new_loan_msg, + new_loan.kind.to_user_str(), + ol_pronoun, + old_loan.kind.to_user_str(), + old_loan_msg); } } @@ -617,11 +613,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) { UseOk => { } UseWhileBorrowed(loan_path, loan_span) => { - self.bccx.span_err( - span, - &format!("cannot use `{}` because it was mutably borrowed", - &self.bccx.loan_path_to_string(copy_path)) - ); + span_err!(self.bccx, span, E0503, + "cannot use `{}` because it was mutably borrowed", + &self.bccx.loan_path_to_string(copy_path)); self.bccx.span_note( loan_span, &format!("borrow of `{}` occurs here", @@ -642,18 +636,19 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { match self.analyze_restrictions_on_use(id, move_path, ty::MutBorrow) { UseOk => { } UseWhileBorrowed(loan_path, loan_span) => { - let err_message = match move_kind { + match move_kind { move_data::Captured => - format!("cannot move `{}` into closure because it is borrowed", - &self.bccx.loan_path_to_string(move_path)), + span_err!(self.bccx, span, E0504, + "cannot move `{}` into closure because it is borrowed", + &self.bccx.loan_path_to_string(move_path)), move_data::Declared | move_data::MoveExpr | move_data::MovePat => - format!("cannot move out of `{}` because it is borrowed", - &self.bccx.loan_path_to_string(move_path)) + span_err!(self.bccx, span, E0505, + "cannot move out of `{}` because it is borrowed", + &self.bccx.loan_path_to_string(move_path)) }; - self.bccx.span_err(span, &err_message[..]); self.bccx.span_note( loan_span, &format!("borrow of `{}` occurs here", @@ -820,10 +815,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { span: Span, loan_path: &LoanPath<'tcx>, loan: &Loan) { - self.bccx.span_err( - span, - &format!("cannot assign to `{}` because it is borrowed", - self.bccx.loan_path_to_string(loan_path))); + span_err!(self.bccx, span, E0506, + "cannot assign to `{}` because it is borrowed", + self.bccx.loan_path_to_string(loan_path)); self.bccx.span_note( loan.span, &format!("borrow of `{}` occurs here", diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index c39b1a9da07ea..bbcf51933422e 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -119,18 +119,18 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, mc::cat_deref(_, _, mc::Implicit(..)) | mc::cat_deref(_, _, mc::UnsafePtr(..)) | mc::cat_static_item => { - bccx.span_err(move_from.span, - &format!("cannot move out of {}", - move_from.descriptive_string(bccx.tcx))); + span_err!(bccx, move_from.span, E0507, + "cannot move out of {}", + move_from.descriptive_string(bccx.tcx)); } mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => { let expr = bccx.tcx.map.expect_expr(move_from.id); if let hir::ExprIndex(..) = expr.node { - bccx.span_err(move_from.span, - &format!("cannot move out of type `{}`, \ - a non-copy fixed-size array", - b.ty)); + span_err!(bccx, move_from.span, E0508, + "cannot move out of type `{}`, \ + a non-copy fixed-size array", + b.ty); } } @@ -139,11 +139,10 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, match b.ty.sty { ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => { - bccx.span_err( - move_from.span, - &format!("cannot move out of type `{}`, \ - which defines the `Drop` trait", - b.ty)); + span_err!(bccx, move_from.span, E0509, + "cannot move out of type `{}`, \ + which defines the `Drop` trait", + b.ty); }, _ => { bccx.span_bug(move_from.span, "this path should not cause illegal move") diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 57e578d10c668..4db7974f09444 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -803,6 +803,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err(s, m); } + pub fn span_err_with_code(&self, s: Span, msg: &str, code: &str) { + self.tcx.sess.span_err_with_code(s, msg, code); + } + pub fn span_bug(&self, s: Span, m: &str) { self.tcx.sess.span_bug(s, m); } diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index e94a214309d1e..a5b313e2dd67e 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -263,12 +263,50 @@ fn mutable() { You can read more about cell types in the API documentation: https://doc.rust-lang.org/std/cell/ -"## +"##, + +E0499: r##" +A variable was borrowed as mutable more than once. Erroneous code example: + +``` +let mut i = 0; +let mut x = &mut i; +let mut a = &mut i; +// error: cannot borrow `i` as mutable more than once at a time +``` + +Please note that in rust, you can either have many immutable references, or one +mutable reference. Take a look at +https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more +information. Example: + + +``` +let mut i = 0; +let mut x = &mut i; // ok! + +// or: +let mut i = 0; +let a = &i; // ok! +let b = &i; // still ok! +let c = &i; // still ok! +``` +"##, } register_diagnostics! { E0385, // {} in an aliasable location E0388, // {} in a static location - E0389 // {} in a `&` reference + E0389, // {} in a `&` reference + E0500, // closure requires unique access to `..` but .. is already borrowed + E0501, // cannot borrow `..`.. as .. because previous closure requires unique access + E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ... + E0503, // cannot use `..` because it was mutably borrowed + E0504, // cannot move `..` into closure because it is borrowed + E0505, // cannot move out of `..` because it is borrowed + E0506, // cannot assign to `..` because it is borrowed + E0507, // cannot move out of .. + E0508, // cannot move out of type `..`, a non-copy fixed-size array + E0509, // cannot move out of type `..`, which defines the `Drop` trait } diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs new file mode 100644 index 0000000000000..dd7c3834e564a --- /dev/null +++ b/src/librustc_trans/diagnostics.rs @@ -0,0 +1,21 @@ +// Copyright 2015 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. + +#![allow(non_snake_case)] + +register_long_diagnostics! { + +} + +register_diagnostics! { + E0510, // invalid use of `return_address` intrinsic: function does not use out pointer + E0511, // invalid monomorphization of `{}` intrinsic + E0512, // transmute called on types with potentially different sizes... +} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index a7fb3af138453..049d8fbe390a4 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -80,6 +80,8 @@ pub mod back { pub mod msvc; } +pub mod diagnostics; + pub mod trans; pub mod save; diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index bcfd44d8835d7..b43a4b3fc889d 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -44,6 +44,9 @@ use syntax::ast; use syntax::ptr::P; use syntax::parse::token; +use rustc::session::Session; +use syntax::codemap::Span; + use std::cmp::Ordering; pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Option { @@ -99,6 +102,10 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Opti Some(ccx.get_intrinsic(&name)) } +pub fn span_transmute_size_error(a: &Session, b: Span, msg: &str) { + span_err!(a, b, E0512, "{}", msg); +} + /// Performs late verification that intrinsics are used correctly. At present, /// the only intrinsic that needs such verification is `transmute`. pub fn check_intrinsics(ccx: &CrateContext) { @@ -127,8 +134,7 @@ pub fn check_intrinsics(ccx: &CrateContext) { last_failing_id = Some(transmute_restriction.id); if transmute_restriction.original_from != transmute_restriction.substituted_from { - ccx.sess().span_err( - transmute_restriction.span, + span_transmute_size_error(ccx.sess(), transmute_restriction.span, &format!("transmute called on types with potentially different sizes: \ {} (could be {} bit{}) to {} (could be {} bit{})", transmute_restriction.original_from, @@ -138,8 +144,7 @@ pub fn check_intrinsics(ccx: &CrateContext) { to_type_size as usize, if to_type_size == 1 {""} else {"s"})); } else { - ccx.sess().span_err( - transmute_restriction.span, + span_transmute_size_error(ccx.sess(), transmute_restriction.span, &format!("transmute called on types with different sizes: \ {} ({} bit{}) to {} ({} bit{})", transmute_restriction.original_from, @@ -798,9 +803,9 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "return_address") => { if !fcx.caller_expects_out_pointer { - tcx.sess.span_err(call_info.span, - "invalid use of `return_address` intrinsic: function \ - does not use out pointer"); + span_err!(tcx.sess, call_info.span, E0510, + "invalid use of `return_address` intrinsic: function \ + does not use out pointer"); C_null(Type::i8p(ccx)) } else { PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx)) @@ -1439,6 +1444,10 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, return rust_try } +fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { + span_err!(a, b, E0511, "{}", c); +} + fn generic_simd_intrinsic<'blk, 'tcx, 'a> (bcx: Block<'blk, 'tcx>, name: &str, @@ -1457,10 +1466,11 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a> emit_error!($msg, ) }; ($msg: tt, $($fmt: tt)*) => { - bcx.sess().span_err(call_info.span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", - $msg), - name, $($fmt)*)); + span_invalid_monomorphization_error( + bcx.sess(), call_info.span, + &format!(concat!("invalid monomorphization of `{}` intrinsic: ", + $msg), + name, $($fmt)*)); } } macro_rules! require {