diff --git a/COMPILER_TESTS.md b/COMPILER_TESTS.md index e4acf230e721..546164c1492a 100644 --- a/COMPILER_TESTS.md +++ b/COMPILER_TESTS.md @@ -1,6 +1,6 @@ # Compiler Test Documentation -In the Rust project, we use a special set of comands imbedded in +In the Rust project, we use a special set of comands embedded in comments to test the Rust compiler. There are two groups of commands: 1. Header commands @@ -29,11 +29,11 @@ The error levels that you can have are: 3. `NOTE` 4. `HELP` and `SUGGESTION`* -\* **Note**: `SUGGESTION` must follow emediatly after `HELP`. +\* **Note**: `SUGGESTION` must follow immediately after `HELP`. ## Summary of Header Commands -Header commands specify something about the entire test file, as a +Header commands specify something about the entire test file as a whole, instead of just a few lines inside the test. * `ignore-X` where `X` is an architecture, OS or stage will ignore the test accordingly diff --git a/Makefile.in b/Makefile.in index 8968fabf1b4b..baa7e77394a0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -26,7 +26,7 @@ # # * check - Run the complete test suite # -# * clean - Clean the build repertory. It is advised to run this +# * clean - Clean the build repository. It is advised to run this # command if you want to build Rust again, after an update # of the git repository. # diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index edb794a54aea..18ce93ea06a6 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -28,7 +28,7 @@ systems may want to jump around. * [The `Result` type](#the-result-type) * [Parsing integers](#parsing-integers) * [The `Result` type alias idiom](#the-result-type-alias-idiom) - * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil) + * [A brief interlude: unwrapping isn't evil](#a-brief-interlude:-unwrapping-isn't-evil) * [Working with multiple error types](#working-with-multiple-error-types) * [Composing `Option` and `Result`](#composing-option-and-result) * [The limits of combinators](#the-limits-of-combinators) @@ -41,11 +41,11 @@ systems may want to jump around. * [The real `try!` macro](#the-real-try!-macro) * [Composing custom error types](#composing-custom-error-types) * [Advice for library writers](#advice-for-library-writers) -* [Case study: A program to read population data](#case-study-a-program-to-read-population-data) +* [Case study: A program to read population data](#case-study:-a-program-to-read-population-data) * [Initial setup](#initial-setup) * [Argument parsing](#argument-parsing) * [Writing the logic](#writing-the-logic) - * [Error handling with `Box`](#error-handling-with-box) + * [Error handling with `Box`](#error-handling-with-box%3Cerror%3E) * [Reading from stdin](#reading-from-stdin) * [Error handling with a custom type](#error-handling-with-a-custom-type) * [Adding functionality](#adding-functionality) @@ -87,9 +87,9 @@ thread '
' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5 Here's another example that is slightly less contrived. A program that accepts an integer as an argument, doubles it and prints it. -
-```rust,should_panic + +```rust,should_panic use std::env; fn main() { @@ -99,7 +99,6 @@ fn main() { println!("{}", 2 * n); } ``` -
If you give this program zero arguments (error 1) or if the first argument isn't an integer (error 2), the program will panic just like in the first @@ -140,7 +139,8 @@ system is an important concept because it will cause the compiler to force the programmer to handle that absence. Let's take a look at an example that tries to find a character in a string: -
+ + ```rust // Searches `haystack` for the Unicode character `needle`. If one is found, the // byte offset of the character is returned. Otherwise, `None` is returned. @@ -153,7 +153,6 @@ fn find(haystack: &str, needle: char) -> Option { None } ``` -
Notice that when this function finds a matching character, it doen't just return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or @@ -187,6 +186,8 @@ But wait, what about `unwrap` used in [`unwrap-double`](#code-unwrap-double)? There was no case analysis there! Instead, the case analysis was put inside the `unwrap` method for you. You could define it yourself if you want: + + ```rust enum Option { None, @@ -210,7 +211,7 @@ that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that ### Composing `Option` values -In [`option-ex-string-find`](#code-option-ex-string-find-2) +In [`option-ex-string-find`](#code-option-ex-string-find) we saw how to use `find` to discover the extension in a file name. Of course, not all file names have a `.` in them, so it's possible that the file name has no extension. This *possibility of absence* is encoded into the types using @@ -252,6 +253,8 @@ option is `None`, in which case, just return `None`. Rust has parametric polymorphism, so it is very easy to define a combinator that abstracts this pattern: + + ```rust fn map(option: Option, f: F) -> Option where F: FnOnce(T) -> A { match option { @@ -391,6 +394,8 @@ remove choices because they will panic if `Option` is `None`. The `Result` type is also [defined in the standard library][6]: + + ```rust enum Result { Ok(T), @@ -667,6 +672,8 @@ with both an `Option` and a `Result`, the solution is *usually* to convert the (from `env::args()`) means the user didn't invoke the program correctly. We could just use a `String` to describe the error. Let's try: + + ```rust use std::env; @@ -899,6 +906,8 @@ seen above. Here is a simplified definition of a `try!` macro: + + ```rust macro_rules! try { ($e:expr) => (match $e { @@ -1159,6 +1168,8 @@ The `std::convert::From` trait is [defined in the standard library](../std/convert/trait.From.html): + + ```rust trait From { fn from(T) -> Self; @@ -1236,9 +1247,11 @@ macro_rules! try { } ``` -This is not it's real definition. It's real definition is +This is not its real definition. Its real definition is [in the standard library](../std/macro.try!.html): + + ```rust macro_rules! try { ($e:expr) => (match $e { @@ -1457,7 +1470,7 @@ representation. But certainly, this will vary depending on use cases. At a minimum, you should probably implement the [`Error`](../std/error/trait.Error.html) trait. This will give users of your library some minimum flexibility for -[composing errors](#the-real-try-macro). Implementing the `Error` trait also +[composing errors](#the-real-try!-macro). Implementing the `Error` trait also means that users are guaranteed the ability to obtain a string representation of an error (because it requires impls for both `fmt::Debug` and `fmt::Display`). diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 3a4328562f87..94280aa4a331 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -147,7 +147,7 @@ a few tricks up their sleeves. For example, they’re [immutable][immutable] by default. That’s why our example uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t -take a name on the left hand side, it actually accepts a +take a name on the left hand side of the assignment, it actually accepts a ‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough to use for now: diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index eed8f82b5d85..43e9cdd73c43 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 c39b1a9da07e..bbcf51933422 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 57e578d10c66..4db7974f0944 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 e94a214309d1..a5b313e2dd67 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/back/link.rs b/src/librustc_trans/back/link.rs index 83e33ede6f23..f1997054fa39 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -542,7 +542,11 @@ fn link_binary_output(sess: &Session, } } - let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir"); + let tmpdir = match TempDir::new("rustc") { + Ok(tmpdir) => tmpdir, + Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)), + }; + match crate_type { config::CrateTypeRlib => { link_rlib(sess, Some(trans), &objects, &out_filename, diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs new file mode 100644 index 000000000000..dd7c3834e564 --- /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 a7fb3af13845..049d8fbe390a 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 bcfd44d8835d..b43a4b3fc889 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 { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 9d84d4ea3c1a..5b0b19b95af1 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -54,7 +54,8 @@ } function browserSupportsHistoryApi() { - return window.history && typeof window.history.pushState === "function"; + return document.location.protocol != "file:" && + window.history && typeof window.history.pushState === "function"; } function highlightSourceLines(ev) { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a0c3f013f2b4..a07d21add8db 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -68,6 +68,10 @@ macro_rules! panic { /// necessary to use `io::stdout().flush()` to ensure the output is emitted /// immediately. /// +/// # Panics +/// +/// Panics if writing to `io::stdout()` fails. +/// /// # Examples /// /// ``` @@ -99,6 +103,10 @@ macro_rules! print { /// Use the `format!` syntax to write data to the standard output. /// See `std::fmt` for more information. /// +/// # Panics +/// +/// Panics if writing to `io::stdout()` fails. +/// /// # Examples /// /// ``` diff --git a/src/test/run-make/issue-14698/Makefile b/src/test/run-make/issue-14698/Makefile new file mode 100644 index 000000000000..28502f67e074 --- /dev/null +++ b/src/test/run-make/issue-14698/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + TMP=fake TMPDIR=fake $(RUSTC) foo.rs 2>&1 | grep "couldn't create a temp dir:" diff --git a/src/test/run-make/issue-14698/foo.rs b/src/test/run-make/issue-14698/foo.rs new file mode 100644 index 000000000000..7dc79f2043ba --- /dev/null +++ b/src/test/run-make/issue-14698/foo.rs @@ -0,0 +1,11 @@ +// 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. + +fn main() {}