diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index d2d1d3d83685..eedff1d11760 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -32,8 +32,8 @@ extern crate getopts; extern crate log; use std::os; -use std::io; -use std::io::fs; +use std::old_io; +use std::old_io::fs; use std::str::FromStr; use std::thunk::Thunk; use getopts::{optopt, optflag, reqopt}; @@ -245,7 +245,7 @@ pub fn run_tests(config: &Config) { // sadly osx needs some file descriptor limits raised for running tests in // parallel (especially when we have lots and lots of child processes). // For context, see #8904 - io::test::raise_fd_limit(); + old_io::test::raise_fd_limit(); // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary os::setenv("__COMPAT_LAYER", "RunAsInvoker"); diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index fc815d66a4d4..868512c7943f 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -9,7 +9,7 @@ // except according to those terms. use self::WhichLine::*; -use std::io::{BufferedReader, File}; +use std::old_io::{BufferedReader, File}; pub struct ExpectedError { pub line: uint, diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index d7af767688e8..8458d880d05a 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -223,7 +223,7 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { fn iter_header(testfile: &Path, mut it: F) -> bool where F: FnMut(&str) -> bool, { - use std::io::{BufferedReader, File}; + use std::old_io::{BufferedReader, File}; let mut rdr = BufferedReader::new(File::open(testfile).unwrap()); for ln in rdr.lines() { diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index f3f860d470d9..7f3865308da1 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::io::process::{ProcessExit, Command, Process, ProcessOutput}; +use std::old_io::process::{ProcessExit, Command, Process, ProcessOutput}; use std::dynamic_lib::DynamicLibrary; fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { @@ -47,7 +47,7 @@ pub fn run(lib_path: &str, match cmd.spawn() { Ok(mut process) => { for input in input.iter() { - process.stdin.as_mut().unwrap().write(input.as_bytes()).unwrap(); + process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); } let ProcessOutput { status, output, error } = process.wait_with_output().unwrap(); @@ -79,7 +79,7 @@ pub fn run_background(lib_path: &str, match cmd.spawn() { Ok(mut process) => { for input in input.iter() { - process.stdin.as_mut().unwrap().write(input.as_bytes()).unwrap(); + process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); } Some(process) diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index e5a973e7501a..0ae32bd00a4a 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -23,14 +23,14 @@ use util; #[cfg(target_os = "windows")] use std::ascii::AsciiExt; -use std::io::File; -use std::io::fs::PathExtensions; -use std::io::fs; -use std::io::net::tcp; -use std::io::process::ProcessExit; -use std::io::process; -use std::io::timer; -use std::io; +use std::old_io::File; +use std::old_io::fs::PathExtensions; +use std::old_io::fs; +use std::old_io::net::tcp; +use std::old_io::process::ProcessExit; +use std::old_io::process; +use std::old_io::timer; +use std::old_io; use std::os; use std::iter::repeat; use std::str; @@ -619,7 +619,7 @@ fn find_rust_src_root(config: &Config) -> Option { } fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) { - use std::io::process::{Command, ProcessOutput}; + use std::old_io::process::{Command, ProcessOutput}; if config.lldb_python_dir.is_none() { fatal("Can't run LLDB test because LLDB's python path is not set."); @@ -764,7 +764,7 @@ struct DebuggerCommands { fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) -> DebuggerCommands { - use std::io::{BufferedReader, File}; + use std::old_io::{BufferedReader, File}; let command_directive = format!("{}-command", debugger_prefix); let check_directive = format!("{}-check", debugger_prefix); @@ -1224,7 +1224,7 @@ fn compose_and_run_compiler( fn ensure_dir(path: &Path) { if path.is_dir() { return; } - fs::mkdir(path, io::USER_RWX).unwrap(); + fs::mkdir(path, old_io::USER_RWX).unwrap(); } fn compose_and_run(config: &Config, testfile: &Path, @@ -1401,7 +1401,7 @@ fn dump_output(config: &Config, testfile: &Path, out: &str, err: &str) { fn dump_output_file(config: &Config, testfile: &Path, out: &str, extension: &str) { let outfile = make_out_name(config, testfile, extension); - File::create(&outfile).write(out.as_bytes()).unwrap(); + File::create(&outfile).write_all(out.as_bytes()).unwrap(); } fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> Path { diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index 6f67c88f2c0c..f01b62223ca8 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -75,14 +75,14 @@ Let's get to it! The first thing we need to do for our guessing game is allow our player to input a guess. Put this in your `src/main.rs`: ```{rust,no_run} -use std::io; +use std::old_io; fn main() { println!("Guess the number!"); println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); @@ -121,7 +121,7 @@ explanatory text, and then an example. Let's try to modify our code to add in th `random` function and see what happens: ```{rust,ignore} -use std::io; +use std::old_io; use std::rand; fn main() { @@ -133,7 +133,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); @@ -180,7 +180,7 @@ This says "please give me a random `i32` value." We can change our code to use this hint: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; fn main() { @@ -192,7 +192,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); @@ -233,7 +233,7 @@ unsigned integer approach. If we want a random positive number, we should ask fo a random positive number. Our code looks like this now: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; fn main() { @@ -245,7 +245,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); @@ -276,7 +276,7 @@ two numbers. Let's add that in, along with a `match` statement to compare our guess to the secret number: ```{rust,ignore} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -289,7 +289,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); @@ -331,7 +331,7 @@ but we've given it unsigned integers. In this case, the fix is easy, because we wrote the `cmp` function! Let's change it to take `u32`s: ```{rust,ignore} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -344,7 +344,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); @@ -397,7 +397,7 @@ Anyway, we have a `String`, but we need a `u32`. What to do? Well, there's a function for that: ```{rust,ignore} -let input = io::stdin().read_line() +let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.parse(); @@ -429,7 +429,7 @@ let input_num: Option = "5".parse(); // input_num: Option Anyway, with us now converting our input to a number, our code looks like this: ```{rust,ignore} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -442,7 +442,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.parse(); @@ -479,7 +479,7 @@ need to unwrap the Option. If you remember from before, `match` is a great way to do that. Try this code: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -492,7 +492,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.parse(); @@ -546,7 +546,7 @@ method we can use defined on them: `trim()`. One small modification, and our code looks like this: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -559,7 +559,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.trim().parse(); @@ -620,7 +620,7 @@ As we already discussed, the `loop` keyword gives us an infinite loop. Let's add that in: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -635,7 +635,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.trim().parse(); @@ -696,7 +696,7 @@ Ha! `quit` actually quits. As does any other non-number input. Well, this is suboptimal to say the least. First, let's actually quit when you win the game: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -711,7 +711,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.trim().parse(); @@ -752,7 +752,7 @@ we don't want to quit, we just want to ignore it. Change that `return` to ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -767,7 +767,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.trim().parse(); @@ -831,7 +831,7 @@ think of what it is? That's right, we don't want to print out the secret number. It was good for testing, but it kind of ruins the game. Here's our final source: ```{rust,no_run} -use std::io; +use std::old_io; use std::rand; use std::cmp::Ordering; @@ -844,7 +844,7 @@ fn main() { println!("Please input your guess."); - let input = io::stdin().read_line() + let input = old_io::stdin().read_line() .ok() .expect("Failed to read line"); let input_num: Option = input.trim().parse(); diff --git a/src/doc/trpl/standard-input.md b/src/doc/trpl/standard-input.md index 7145139bba57..0c26fb2b44fa 100644 --- a/src/doc/trpl/standard-input.md +++ b/src/doc/trpl/standard-input.md @@ -8,7 +8,7 @@ and then prints it back out: fn main() { println!("Type something!"); - let input = std::io::stdin().read_line().ok().expect("Failed to read line"); + let input = std::old_io::stdin().read_line().ok().expect("Failed to read line"); println!("{}", input); } @@ -17,7 +17,7 @@ fn main() { Let's go over these chunks, one by one: ```{rust,ignore} -std::io::stdin(); +std::old_io::stdin(); ``` This calls a function, `stdin()`, that lives inside the `std::io` module. As @@ -28,7 +28,7 @@ Since writing the fully qualified name all the time is annoying, we can use the `use` statement to import it in: ```{rust} -use std::io::stdin; +use std::old_io::stdin; stdin(); ``` @@ -37,20 +37,20 @@ However, it's considered better practice to not import individual functions, but to import the module, and only use one level of qualification: ```{rust} -use std::io; +use std::old_io; -io::stdin(); +old_io::stdin(); ``` Let's update our example to use this style: ```{rust,ignore} -use std::io; +use std::old_io; fn main() { println!("Type something!"); - let input = io::stdin().read_line().ok().expect("Failed to read line"); + let input = old_io::stdin().read_line().ok().expect("Failed to read line"); println!("{}", input); } @@ -121,12 +121,12 @@ For now, this gives you enough of a basic understanding to work with. Back to the code we were working on! Here's a refresher: ```{rust,ignore} -use std::io; +use std::old_io; fn main() { println!("Type something!"); - let input = io::stdin().read_line().ok().expect("Failed to read line"); + let input = old_io::stdin().read_line().ok().expect("Failed to read line"); println!("{}", input); } @@ -136,14 +136,14 @@ With long lines like this, Rust gives you some flexibility with the whitespace. We _could_ write the example like this: ```{rust,ignore} -use std::io; +use std::old_io; fn main() { println!("Type something!"); // here, we'll show the types at each step - let input = io::stdin() // std::io::stdio::StdinReader + let input = old_io::stdin() // std::old_io::stdio::StdinReader .read_line() // IoResult .ok() // Option .expect("Failed to read line"); // String diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index ddcc41938f28..02cc4038a69b 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -10,39 +10,30 @@ //! Shareable mutable containers. //! -//! Values of the `Cell` and `RefCell` types may be mutated through -//! shared references (i.e. the common `&T` type), whereas most Rust -//! types can only be mutated through unique (`&mut T`) references. We -//! say that `Cell` and `RefCell` provide *interior mutability*, in -//! contrast with typical Rust types that exhibit *inherited -//! mutability*. +//! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. +//! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) +//! references. We say that `Cell` and `RefCell` provide 'interior mutability', in contrast +//! with typical Rust types that exhibit 'inherited mutability'. //! -//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` -//! provides `get` and `set` methods that change the -//! interior value with a single method call. `Cell` though is only -//! compatible with types that implement `Copy`. For other types, -//! one must use the `RefCell` type, acquiring a write lock before -//! mutating. +//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` provides `get` and `set` +//! methods that change the interior value with a single method call. `Cell` though is only +//! compatible with types that implement `Copy`. For other types, one must use the `RefCell` +//! type, acquiring a write lock before mutating. //! -//! `RefCell` uses Rust's lifetimes to implement *dynamic borrowing*, -//! a process whereby one can claim temporary, exclusive, mutable -//! access to the inner value. Borrows for `RefCell`s are tracked *at -//! runtime*, unlike Rust's native reference types which are entirely -//! tracked statically, at compile time. Because `RefCell` borrows are -//! dynamic it is possible to attempt to borrow a value that is -//! already mutably borrowed; when this happens it results in task -//! panic. +//! `RefCell` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can +//! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell`s are +//! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked +//! statically, at compile time. Because `RefCell` borrows are dynamic it is possible to attempt +//! to borrow a value that is already mutably borrowed; when this happens it results in task panic. //! //! # When to choose interior mutability //! -//! The more common inherited mutability, where one must have unique -//! access to mutate a value, is one of the key language elements that -//! enables Rust to reason strongly about pointer aliasing, statically -//! preventing crash bugs. Because of that, inherited mutability is -//! preferred, and interior mutability is something of a last -//! resort. Since cell types enable mutation where it would otherwise -//! be disallowed though, there are occasions when interior -//! mutability might be appropriate, or even *must* be used, e.g. +//! The more common inherited mutability, where one must have unique access to mutate a value, is +//! one of the key language elements that enables Rust to reason strongly about pointer aliasing, +//! statically preventing crash bugs. Because of that, inherited mutability is preferred, and +//! interior mutability is something of a last resort. Since cell types enable mutation where it +//! would otherwise be disallowed though, there are occasions when interior mutability might be +//! appropriate, or even *must* be used, e.g. //! //! * Introducing inherited mutability roots to shared types. //! * Implementation details of logically-immutable methods. @@ -50,15 +41,13 @@ //! //! ## Introducing inherited mutability roots to shared types //! -//! Shared smart pointer types, including `Rc` and `Arc`, provide -//! containers that can be cloned and shared between multiple parties. -//! Because the contained values may be multiply-aliased, they can -//! only be borrowed as shared references, not mutable references. -//! Without cells it would be impossible to mutate data inside of -//! shared boxes at all! +//! Shared smart pointer types, including `Rc` and `Arc`, provide containers that can be +//! cloned and shared between multiple parties. Because the contained values may be +//! multiply-aliased, they can only be borrowed as shared references, not mutable references. +//! Without cells it would be impossible to mutate data inside of shared boxes at all! //! -//! It's very common then to put a `RefCell` inside shared pointer -//! types to reintroduce mutability: +//! It's very common then to put a `RefCell` inside shared pointer types to reintroduce +//! mutability: //! //! ``` //! use std::collections::HashMap; @@ -80,12 +69,10 @@ //! //! ## Implementation details of logically-immutable methods //! -//! Occasionally it may be desirable not to expose in an API that -//! there is mutation happening "under the hood". This may be because -//! logically the operation is immutable, but e.g. caching forces the -//! implementation to perform mutation; or because you must employ -//! mutation to implement a trait method that was originally defined -//! to take `&self`. +//! Occasionally it may be desirable not to expose in an API that there is mutation happening +//! "under the hood". This may be because logically the operation is immutable, but e.g. caching +//! forces the implementation to perform mutation; or because you must employ mutation to implement +//! a trait method that was originally defined to take `&self`. //! //! ``` //! use std::cell::RefCell; @@ -123,13 +110,11 @@ //! //! ## Mutating implementations of `clone` //! -//! This is simply a special - but common - case of the previous: -//! hiding mutability for operations that appear to be immutable. -//! The `clone` method is expected to not change the source value, and -//! is declared to take `&self`, not `&mut self`. Therefore any -//! mutation that happens in the `clone` method must use cell -//! types. For example, `Rc` maintains its reference counts within a -//! `Cell`. +//! This is simply a special - but common - case of the previous: hiding mutability for operations +//! that appear to be immutable. The `clone` method is expected to not change the source value, and +//! is declared to take `&self`, not `&mut self`. Therefore any mutation that happens in the +//! `clone` method must use cell types. For example, `Rc` maintains its reference counts within a +//! `Cell`. //! //! ``` //! use std::cell::Cell; @@ -153,10 +138,6 @@ //! } //! ``` //! -// FIXME: Explain difference between Cell and RefCell -// FIXME: Downsides to interior mutability -// FIXME: Can't be shared between threads. Dynamic borrows -// FIXME: Relationship to Atomic types and RWLock #![stable(feature = "rust1", since = "1.0.0")] @@ -169,6 +150,8 @@ use option::Option; use option::Option::{None, Some}; /// A mutable memory location that admits only `Copy` data. +/// +/// See the [module-level documentation](../index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct Cell { value: UnsafeCell, @@ -176,6 +159,14 @@ pub struct Cell { impl Cell { /// Creates a new `Cell` containing the given value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> Cell { Cell { @@ -184,6 +175,16 @@ impl Cell { } /// Returns a copy of the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let five = c.get(); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self) -> T { @@ -191,6 +192,16 @@ impl Cell { } /// Sets the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// c.set(10); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn set(&self, value: T) { @@ -201,9 +212,19 @@ impl Cell { /// Get a reference to the underlying `UnsafeCell`. /// - /// This can be used to circumvent `Cell`'s safety checks. + /// # Unsafety /// /// This function is `unsafe` because `UnsafeCell`'s field is public. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let uc = unsafe { c.as_unsafe_cell() }; + /// ``` #[inline] #[unstable(feature = "core")] pub unsafe fn as_unsafe_cell<'a>(&'a self) -> &'a UnsafeCell { @@ -237,6 +258,8 @@ impl PartialEq for Cell { } /// A mutable memory location with dynamically checked borrow rules +/// +/// See the [module-level documentation](../index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell { value: UnsafeCell, @@ -250,7 +273,15 @@ const UNUSED: BorrowFlag = 0; const WRITING: BorrowFlag = -1; impl RefCell { - /// Create a new `RefCell` containing `value` + /// Creates a new `RefCell` containing `value`. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> RefCell { RefCell { @@ -260,6 +291,16 @@ impl RefCell { } /// Consumes the `RefCell`, returning the wrapped value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let five = c.into_inner(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> T { // Since this function takes `self` (the `RefCell`) by value, the @@ -285,12 +326,39 @@ impl RefCell { /// Immutably borrows the wrapped value. /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. + /// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be + /// taken out at the same time. /// /// # Panics /// /// Panics if the value is currently mutably borrowed. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let borrowed_five = c.borrow(); + /// let borrowed_five2 = c.borrow(); + /// ``` + /// + /// An example of panic: + /// + /// ``` + /// use std::cell::RefCell; + /// use std::thread::Thread; + /// + /// let result = Thread::scoped(move || { + /// let c = RefCell::new(5); + /// let m = c.borrow_mut(); + /// + /// let b = c.borrow(); // this causes a panic + /// }).join(); + /// + /// assert!(result.is_err()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn borrow<'a>(&'a self) -> Ref<'a, T> { match self.try_borrow() { @@ -315,12 +383,38 @@ impl RefCell { /// Mutably borrows the wrapped value. /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. + /// The borrow lasts until the returned `RefMut` exits scope. The value cannot be borrowed + /// while this borrow is active. /// /// # Panics /// /// Panics if the value is currently borrowed. + /// + /// # Examples + /// + /// ``` + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// let borrowed_five = c.borrow_mut(); + /// ``` + /// + /// An example of panic: + /// + /// ``` + /// use std::cell::RefCell; + /// use std::thread::Thread; + /// + /// let result = Thread::scoped(move || { + /// let c = RefCell::new(5); + /// let m = c.borrow_mut(); + /// + /// let b = c.borrow_mut(); // this causes a panic + /// }).join(); + /// + /// assert!(result.is_err()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { match self.try_borrow_mut() { @@ -403,6 +497,9 @@ impl<'b> Clone for BorrowRef<'b> { } /// Wraps a borrowed reference to a value in a `RefCell` box. +/// A wrapper type for an immutably borrowed value from a `RefCell`. +/// +/// See the [module-level documentation](../index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct Ref<'b, T:'b> { // FIXME #12808: strange name to try to avoid interfering with @@ -461,7 +558,9 @@ impl<'b> BorrowRefMut<'b> { } } -/// Wraps a mutable borrowed reference to a value in a `RefCell` box. +/// A wrapper type for a mutably borrowed value from a `RefCell`. +/// +/// See the [module-level documentation](../index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] pub struct RefMut<'b, T:'b> { // FIXME #12808: strange name to try to avoid interfering with @@ -490,28 +589,25 @@ impl<'b, T> DerefMut for RefMut<'b, T> { /// The core primitive for interior mutability in Rust. /// -/// `UnsafeCell` type that wraps a type T and indicates unsafe interior -/// operations on the wrapped type. Types with an `UnsafeCell` field are -/// considered to have an *unsafe interior*. The `UnsafeCell` type is the only -/// legal way to obtain aliasable data that is considered mutable. In general, -/// transmuting an &T type into an &mut T is considered undefined behavior. +/// `UnsafeCell` is a type that wraps some `T` and indicates unsafe interior operations on the +/// wrapped type. Types with an `UnsafeCell` field are considered to have an 'unsafe interior'. +/// The `UnsafeCell` type is the only legal way to obtain aliasable data that is considered +/// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior. /// -/// Although it is possible to put an `UnsafeCell` into static item, it is -/// not permitted to take the address of the static item if the item is not -/// declared as mutable. This rule exists because immutable static items are -/// stored in read-only memory, and thus any attempt to mutate their interior -/// can cause segfaults. Immutable static items containing `UnsafeCell` -/// instances are still useful as read-only initializers, however, so we do not -/// forbid them altogether. +/// Although it is possible to put an `UnsafeCell` into static item, it is not permitted to take +/// the address of the static item if the item is not declared as mutable. This rule exists because +/// immutable static items are stored in read-only memory, and thus any attempt to mutate their +/// interior can cause segfaults. Immutable static items containing `UnsafeCell` instances are +/// still useful as read-only initializers, however, so we do not forbid them altogether. /// -/// Types like `Cell` and `RefCell` use this type to wrap their internal data. +/// Types like `Cell` and `RefCell` use this type to wrap their internal data. /// -/// `UnsafeCell` doesn't opt-out from any kind, instead, types with an -/// `UnsafeCell` interior are expected to opt-out from kinds themselves. +/// `UnsafeCell` doesn't opt-out from any marker traits, instead, types with an `UnsafeCell` +/// interior are expected to opt-out from those traits themselves. /// -/// # Example: +/// # Examples /// -/// ```rust +/// ``` /// use std::cell::UnsafeCell; /// use std::marker::Sync; /// @@ -522,9 +618,8 @@ impl<'b, T> DerefMut for RefMut<'b, T> { /// unsafe impl Sync for NotThreadSafe {} /// ``` /// -/// **NOTE:** `UnsafeCell` fields are public to allow static initializers. It -/// is not recommended to access its fields directly, `get` should be used -/// instead. +/// **NOTE:** `UnsafeCell`'s fields are public to allow static initializers. It is not +/// recommended to access its fields directly, `get` should be used instead. #[lang="unsafe"] #[stable(feature = "rust1", since = "1.0.0")] pub struct UnsafeCell { @@ -540,22 +635,52 @@ impl UnsafeCell { /// Construct a new instance of `UnsafeCell` which will wrap the specified /// value. /// - /// All access to the inner value through methods is `unsafe`, and it is - /// highly discouraged to access the fields directly. + /// All access to the inner value through methods is `unsafe`, and it is highly discouraged to + /// access the fields directly. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let uc = UnsafeCell::new(5); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> UnsafeCell { UnsafeCell { value: value } } /// Gets a mutable pointer to the wrapped value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let uc = UnsafeCell::new(5); + /// + /// let five = uc.get(); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self) -> *mut T { &self.value as *const T as *mut T } /// Unwraps the value /// - /// This function is unsafe because there is no guarantee that this or other - /// tasks are currently inspecting the inner value. + /// # Unsafety + /// + /// This function is unsafe because there is no guarantee that this or other threads are + /// currently inspecting the inner value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::UnsafeCell; + /// + /// let uc = UnsafeCell::new(5); + /// + /// let five = unsafe { uc.into_inner() }; + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn into_inner(self) -> T { self.value } diff --git a/src/libcore/error.rs b/src/libcore/error.rs index 9519539f0004..71d5e88cccff 100644 --- a/src/libcore/error.rs +++ b/src/libcore/error.rs @@ -49,7 +49,7 @@ //! //! ``` //! use std::error::FromError; -//! use std::io::{File, IoError}; +//! use std::old_io::{File, IoError}; //! use std::os::{MemoryMap, MapError}; //! use std::path::Path; //! diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8e6715fa38b1..06428ad2f39a 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -238,7 +238,7 @@ impl<'a> Display for Arguments<'a> { } } -/// Format trait for the `:?` format. Useful for debugging, most all types +/// Format trait for the `:?` format. Useful for debugging, all types /// should implement this. #[unstable(feature = "core", reason = "I/O and core have yet to be reconciled")] @@ -249,7 +249,7 @@ pub trait Show { fn fmt(&self, &mut Formatter) -> Result; } -/// Format trait for the `:?` format. Useful for debugging, most all types +/// Format trait for the `:?` format. Useful for debugging, all types /// should implement this. #[unstable(feature = "core", reason = "I/O and core have yet to be reconciled")] diff --git a/src/libcore/result.rs b/src/libcore/result.rs index bfbc96c5a399..ade257165c6a 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -95,7 +95,7 @@ //! by the [`Writer`](../io/trait.Writer.html) trait: //! //! ``` -//! use std::io::IoError; +//! use std::old_io::IoError; //! //! trait Writer { //! fn write_line(&mut self, s: &str) -> Result<(), IoError>; @@ -110,7 +110,7 @@ //! something like this: //! //! ```{.ignore} -//! use std::io::{File, Open, Write}; +//! use std::old_io::{File, Open, Write}; //! //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! // If `write_line` errors, then we'll never know, because the return @@ -128,7 +128,7 @@ //! a marginally useful message indicating why: //! //! ```{.no_run} -//! use std::io::{File, Open, Write}; +//! use std::old_io::{File, Open, Write}; //! //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! file.write_line("important message").ok().expect("failed to write message"); @@ -138,7 +138,7 @@ //! You might also simply assert success: //! //! ```{.no_run} -//! # use std::io::{File, Open, Write}; +//! # use std::old_io::{File, Open, Write}; //! //! # let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! assert!(file.write_line("important message").is_ok()); @@ -148,7 +148,7 @@ //! Or propagate the error up the call stack with `try!`: //! //! ``` -//! # use std::io::{File, Open, Write, IoError}; +//! # use std::old_io::{File, Open, Write, IoError}; //! fn write_message() -> Result<(), IoError> { //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! try!(file.write_line("important message")); @@ -167,7 +167,7 @@ //! It replaces this: //! //! ``` -//! use std::io::{File, Open, Write, IoError}; +//! use std::old_io::{File, Open, Write, IoError}; //! //! struct Info { //! name: String, @@ -191,7 +191,7 @@ //! With this: //! //! ``` -//! use std::io::{File, Open, Write, IoError}; +//! use std::old_io::{File, Open, Write, IoError}; //! //! struct Info { //! name: String, @@ -445,7 +445,7 @@ impl Result { /// ignoring I/O and parse errors: /// /// ``` - /// use std::io::IoResult; + /// use std::old_io::IoResult; /// /// let mut buffer = &mut b"1\n2\n3\n4\n"; /// diff --git a/src/libcoretest/fmt/num.rs b/src/libcoretest/fmt/num.rs index 17180076cd80..dba355373ce6 100644 --- a/src/libcoretest/fmt/num.rs +++ b/src/libcoretest/fmt/num.rs @@ -170,7 +170,7 @@ mod u32 { use test::Bencher; use core::fmt::radix; use std::rand::{weak_rng, Rng}; - use std::io::util::NullWriter; + use std::old_io::util::NullWriter; #[bench] fn format_bin(b: &mut Bencher) { @@ -213,7 +213,7 @@ mod i32 { use test::Bencher; use core::fmt::radix; use std::rand::{weak_rng, Rng}; - use std::io::util::NullWriter; + use std::old_io::util::NullWriter; #[bench] fn format_bin(b: &mut Bencher) { diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 5ed93f0fd991..171b4ec2097b 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -96,7 +96,7 @@ //! ```no_run //! # pub fn render_to(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::io::File; +//! use std::old_io::File; //! let mut f = File::create(&Path::new("example1.dot")); //! render_to(&mut f) //! } @@ -188,7 +188,7 @@ //! ```no_run //! # pub fn render_to(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::io::File; +//! use std::old_io::File; //! let mut f = File::create(&Path::new("example2.dot")); //! render_to(&mut f) //! } @@ -252,7 +252,7 @@ //! ```no_run //! # pub fn render_to(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::io::File; +//! use std::old_io::File; //! let mut f = File::create(&Path::new("example3.dot")); //! render_to(&mut f) //! } @@ -283,7 +283,7 @@ use self::LabelText::*; use std::borrow::IntoCow; -use std::io; +use std::old_io; use std::string::CowString; use std::vec::CowVec; @@ -536,7 +536,7 @@ pub fn default_options() -> Vec { vec![] } /// (Simple wrapper around `render_opts` that passes a default set of options.) pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( g: &'a G, - w: &mut W) -> io::IoResult<()> { + w: &mut W) -> old_io::IoResult<()> { render_opts(g, w, &[]) } @@ -545,14 +545,14 @@ pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( g: &'a G, w: &mut W, - options: &[RenderOption]) -> io::IoResult<()> + options: &[RenderOption]) -> old_io::IoResult<()> { - fn writeln(w: &mut W, arg: &[&str]) -> io::IoResult<()> { + fn writeln(w: &mut W, arg: &[&str]) -> old_io::IoResult<()> { for &s in arg.iter() { try!(w.write_str(s)); } w.write_char('\n') } - fn indent(w: &mut W) -> io::IoResult<()> { + fn indent(w: &mut W) -> old_io::IoResult<()> { w.write_str(" ") } @@ -594,7 +594,7 @@ mod tests { use self::NodeLabels::*; use super::{Id, Labeller, Nodes, Edges, GraphWalk, render}; use super::LabelText::{self, LabelStr, EscStr}; - use std::io::IoResult; + use std::old_io::IoResult; use std::borrow::IntoCow; use std::iter::repeat; diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 05b831a5a592..dfec2c18816e 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -181,8 +181,8 @@ use std::cell::RefCell; use std::fmt; -use std::io::LineBufferedWriter; -use std::io; +use std::old_io::LineBufferedWriter; +use std::old_io; use std::mem; use std::os; use std::ptr; @@ -239,7 +239,7 @@ pub trait Logger { } struct DefaultLogger { - handle: LineBufferedWriter, + handle: LineBufferedWriter, } /// Wraps the log level with fmt implementations. @@ -301,7 +301,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { let mut logger = LOCAL_LOGGER.with(|s| { s.borrow_mut().take() }).unwrap_or_else(|| { - box DefaultLogger { handle: io::stderr() } as Box + box DefaultLogger { handle: old_io::stderr() } as Box }); logger.log(&LogRecord { level: LogLevel(level), diff --git a/src/librbml/io.rs b/src/librbml/io.rs index 9c746c69baaf..13ddad1fee25 100644 --- a/src/librbml/io.rs +++ b/src/librbml/io.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::io::{IoError, IoResult, SeekStyle}; -use std::io; +use std::old_io::{IoError, IoResult, SeekStyle}; +use std::old_io; use std::slice; use std::iter::repeat; @@ -18,14 +18,14 @@ static BUF_CAPACITY: uint = 128; fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult { // compute offset as signed and clamp to prevent overflow let pos = match seek { - io::SeekSet => 0, - io::SeekEnd => end, - io::SeekCur => cur, + old_io::SeekSet => 0, + old_io::SeekEnd => end, + old_io::SeekCur => cur, } as i64; if offset + pos < 0 { Err(IoError { - kind: io::InvalidInput, + kind: old_io::InvalidInput, desc: "invalid seek to a negative offset", detail: None }) @@ -80,7 +80,7 @@ impl SeekableMemWriter { impl Writer for SeekableMemWriter { #[inline] - fn write(&mut self, buf: &[u8]) -> IoResult<()> { + fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { if self.pos == self.buf.len() { self.buf.push_all(buf) } else { @@ -132,7 +132,7 @@ impl Seek for SeekableMemWriter { mod tests { extern crate test; use super::SeekableMemWriter; - use std::io; + use std::old_io; use std::iter::repeat; use test::Bencher; @@ -148,23 +148,23 @@ mod tests { let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(writer.get_ref(), b); - writer.seek(0, io::SeekSet).unwrap(); + writer.seek(0, old_io::SeekSet).unwrap(); assert_eq!(writer.tell(), Ok(0)); writer.write(&[3, 4]).unwrap(); let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; assert_eq!(writer.get_ref(), b); - writer.seek(1, io::SeekCur).unwrap(); + writer.seek(1, old_io::SeekCur).unwrap(); writer.write(&[0, 1]).unwrap(); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; assert_eq!(writer.get_ref(), b); - writer.seek(-1, io::SeekEnd).unwrap(); + writer.seek(-1, old_io::SeekEnd).unwrap(); writer.write(&[1, 2]).unwrap(); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; assert_eq!(writer.get_ref(), b); - writer.seek(1, io::SeekEnd).unwrap(); + writer.seek(1, old_io::SeekEnd).unwrap(); writer.write(&[1]).unwrap(); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; assert_eq!(writer.get_ref(), b); @@ -173,14 +173,14 @@ mod tests { #[test] fn seek_past_end() { let mut r = SeekableMemWriter::new(); - r.seek(10, io::SeekSet).unwrap(); + r.seek(10, old_io::SeekSet).unwrap(); assert!(r.write(&[3]).is_ok()); } #[test] fn seek_before_0() { let mut r = SeekableMemWriter::new(); - assert!(r.seek(-1, io::SeekSet).is_err()); + assert!(r.seek(-1, old_io::SeekSet).is_err()); } fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) { diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 2819dec3ebbf..2500cb864632 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -115,7 +115,7 @@ pub enum EbmlEncoderTag { pub enum Error { IntTooBig(uint), Expected(String), - IoError(std::io::IoError), + IoError(std::old_io::IoError), ApplicationError(String) } @@ -131,7 +131,7 @@ pub mod reader { use std::char; use std::int; - use std::io::extensions::u64_from_be_bytes; + use std::old_io::extensions::u64_from_be_bytes; use std::mem::transmute; use std::num::Int; use std::option::Option; @@ -689,9 +689,9 @@ pub mod reader { pub mod writer { use std::clone::Clone; - use std::io::extensions::u64_to_be_bytes; - use std::io::{Writer, Seek}; - use std::io; + use std::old_io::extensions::u64_to_be_bytes; + use std::old_io::{Writer, Seek}; + use std::old_io; use std::mem; use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, @@ -702,7 +702,7 @@ pub mod writer { use serialize; - pub type EncodeResult = io::IoResult<()>; + pub type EncodeResult = old_io::IoResult<()>; // rbml writing pub struct Encoder<'a, W:'a> { @@ -712,14 +712,14 @@ pub mod writer { fn write_sized_vuint(w: &mut W, n: uint, size: uint) -> EncodeResult { match size { - 1u => w.write(&[0x80u8 | (n as u8)]), - 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]), - 3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8, + 1u => w.write_all(&[0x80u8 | (n as u8)]), + 2u => w.write_all(&[0x40u8 | ((n >> 8_u) as u8), n as u8]), + 3u => w.write_all(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8, n as u8]), - 4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8, + 4u => w.write_all(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8, (n >> 8_u) as u8, n as u8]), - _ => Err(io::IoError { - kind: io::OtherIoError, + _ => Err(old_io::IoError { + kind: old_io::OtherIoError, desc: "int too big", detail: Some(format!("{}", n)) }) @@ -731,8 +731,8 @@ pub mod writer { if n < 0x4000_u { return write_sized_vuint(w, n, 2u); } if n < 0x200000_u { return write_sized_vuint(w, n, 3u); } if n < 0x10000000_u { return write_sized_vuint(w, n, 4u); } - Err(io::IoError { - kind: io::OtherIoError, + Err(old_io::IoError { + kind: old_io::OtherIoError, desc: "int too big", detail: Some(format!("{}", n)) }) @@ -764,16 +764,16 @@ pub mod writer { // Write a placeholder four-byte size. self.size_positions.push(try!(self.writer.tell()) as uint); let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8]; - self.writer.write(zeroes) + self.writer.write_all(zeroes) } pub fn end_tag(&mut self) -> EncodeResult { let last_size_pos = self.size_positions.pop().unwrap(); let cur_pos = try!(self.writer.tell()); - try!(self.writer.seek(last_size_pos as i64, io::SeekSet)); + try!(self.writer.seek(last_size_pos as i64, old_io::SeekSet)); let size = cur_pos as uint - last_size_pos - 4; try!(write_sized_vuint(self.writer, size, 4u)); - let r = try!(self.writer.seek(cur_pos as i64, io::SeekSet)); + let r = try!(self.writer.seek(cur_pos as i64, old_io::SeekSet)); debug!("End tag (size = {:?})", size); Ok(r) @@ -790,7 +790,7 @@ pub mod writer { pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult { try!(write_vuint(self.writer, tag_id)); try!(write_vuint(self.writer, b.len())); - self.writer.write(b) + self.writer.write_all(b) } pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult { @@ -843,12 +843,12 @@ pub mod writer { pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult { debug!("Write {:?} bytes", b.len()); - self.writer.write(b) + self.writer.write_all(b) } pub fn wr_str(&mut self, s: &str) -> EncodeResult { debug!("Write str: {:?}", s); - self.writer.write(s.as_bytes()) + self.writer.write_all(s.as_bytes()) } } @@ -890,7 +890,7 @@ pub mod writer { } impl<'a, W: Writer + Seek> serialize::Encoder for Encoder<'a, W> { - type Error = io::IoError; + type Error = old_io::IoError; fn emit_nil(&mut self) -> EncodeResult { Ok(()) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 1197276b9908..e6f76dedca95 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -34,8 +34,8 @@ use middle::astencode::vtable_decoder_helpers; use std::collections::HashMap; use std::hash::{self, Hash, SipHasher}; -use std::io::extensions::u64_from_be_bytes; -use std::io; +use std::old_io::extensions::u64_from_be_bytes; +use std::old_io; use std::num::FromPrimitive; use std::rc::Rc; use std::str; @@ -1178,7 +1178,7 @@ fn get_attributes(md: rbml::Doc) -> Vec { } fn list_crate_attributes(md: rbml::Doc, hash: &Svh, - out: &mut io::Writer) -> io::IoResult<()> { + out: &mut old_io::Writer) -> old_io::IoResult<()> { try!(write!(out, "=Crate Attributes ({})=\n", *hash)); let r = get_attributes(md); @@ -1223,7 +1223,7 @@ pub fn get_crate_deps(data: &[u8]) -> Vec { return deps; } -fn list_crate_deps(data: &[u8], out: &mut io::Writer) -> io::IoResult<()> { +fn list_crate_deps(data: &[u8], out: &mut old_io::Writer) -> old_io::IoResult<()> { try!(write!(out, "=External Dependencies=\n")); for dep in get_crate_deps(data).iter() { try!(write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)); @@ -1262,7 +1262,7 @@ pub fn get_crate_name(data: &[u8]) -> String { maybe_get_crate_name(data).expect("no crate name in crate") } -pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Writer) -> io::IoResult<()> { +pub fn list_crate_metadata(bytes: &[u8], out: &mut old_io::Writer) -> old_io::IoResult<()> { let hash = get_crate_hash(bytes); let md = rbml::Doc::new(bytes); try!(list_crate_attributes(md, &hash, out)); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2de453812492..f6c5ba4b52bc 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -122,7 +122,7 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder, // Item info table encoding fn encode_family(rbml_w: &mut Encoder, c: char) { rbml_w.start_tag(tag_items_data_item_family); - rbml_w.writer.write(&[c as u8]); + rbml_w.writer.write_all(&[c as u8]); rbml_w.end_tag(); } @@ -149,7 +149,7 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder, fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { rbml_w.start_tag(tag_items_data_item_variant); let s = def_to_string(vid); - rbml_w.writer.write(s.as_bytes()); + rbml_w.writer.write_all(s.as_bytes()); rbml_w.end_tag(); rbml_w.start_tag(tag_mod_child); @@ -259,7 +259,7 @@ fn encode_symbol(ecx: &EncodeContext, match ecx.item_symbols.borrow().get(&id) { Some(x) => { debug!("encode_symbol(id={}, str={})", id, *x); - rbml_w.writer.write(x.as_bytes()); + rbml_w.writer.write_all(x.as_bytes()); } None => { ecx.diag.handler().bug( @@ -274,14 +274,14 @@ fn encode_disr_val(_: &EncodeContext, disr_val: ty::Disr) { rbml_w.start_tag(tag_disr_val); let s = disr_val.to_string(); - rbml_w.writer.write(s.as_bytes()); + rbml_w.writer.write_all(s.as_bytes()); rbml_w.end_tag(); } fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) { rbml_w.start_tag(tag_items_data_parent_item); let s = def_to_string(id); - rbml_w.writer.write(s.as_bytes()); + rbml_w.writer.write_all(s.as_bytes()); rbml_w.end_tag(); } @@ -299,7 +299,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder, encode_def_id(rbml_w, f.id); rbml_w.start_tag(tag_item_field_origin); let s = def_to_string(origin); - rbml_w.writer.write(s.as_bytes()); + rbml_w.writer.write_all(s.as_bytes()); rbml_w.end_tag(); rbml_w.end_tag(); } @@ -636,17 +636,17 @@ fn encode_explicit_self(rbml_w: &mut Encoder, // Encode the base self type. match *explicit_self { ty::StaticExplicitSelfCategory => { - rbml_w.writer.write(&[ 's' as u8 ]); + rbml_w.writer.write_all(&[ 's' as u8 ]); } ty::ByValueExplicitSelfCategory => { - rbml_w.writer.write(&[ 'v' as u8 ]); + rbml_w.writer.write_all(&[ 'v' as u8 ]); } ty::ByBoxExplicitSelfCategory => { - rbml_w.writer.write(&[ '~' as u8 ]); + rbml_w.writer.write_all(&[ '~' as u8 ]); } ty::ByReferenceExplicitSelfCategory(_, m) => { // FIXME(#4846) encode custom lifetime - rbml_w.writer.write(&['&' as u8]); + rbml_w.writer.write_all(&['&' as u8]); encode_mutability(rbml_w, m); } } @@ -656,21 +656,21 @@ fn encode_explicit_self(rbml_w: &mut Encoder, fn encode_mutability(rbml_w: &mut Encoder, m: ast::Mutability) { match m { - ast::MutImmutable => { rbml_w.writer.write(&[ 'i' as u8 ]); } - ast::MutMutable => { rbml_w.writer.write(&[ 'm' as u8 ]); } + ast::MutImmutable => { rbml_w.writer.write_all(&[ 'i' as u8 ]); } + ast::MutMutable => { rbml_w.writer.write_all(&[ 'm' as u8 ]); } } } } fn encode_item_sort(rbml_w: &mut Encoder, sort: char) { rbml_w.start_tag(tag_item_trait_item_sort); - rbml_w.writer.write(&[ sort as u8 ]); + rbml_w.writer.write_all(&[ sort as u8 ]); rbml_w.end_tag(); } fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) { rbml_w.start_tag(tag_item_trait_parent_sort); - rbml_w.writer.write(&[ sort as u8 ]); + rbml_w.writer.write_all(&[ sort as u8 ]); rbml_w.end_tag(); } @@ -679,7 +679,7 @@ fn encode_provided_source(rbml_w: &mut Encoder, for source in source_opt.iter() { rbml_w.start_tag(tag_item_method_provided_source); let s = def_to_string(*source); - rbml_w.writer.write(s.as_bytes()); + rbml_w.writer.write_all(s.as_bytes()); rbml_w.end_tag(); } } @@ -926,7 +926,7 @@ fn encode_method_argument_names(rbml_w: &mut Encoder, rbml_w.start_tag(tag_method_argument_name); if let ast::PatIdent(_, ref path1, _) = arg.pat.node { let name = token::get_ident(path1.node); - rbml_w.writer.write(name.get().as_bytes()); + rbml_w.writer.write_all(name.get().as_bytes()); } rbml_w.end_tag(); } @@ -1646,7 +1646,7 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { ast::MetaWord(ref name) => { rbml_w.start_tag(tag_meta_item_word); rbml_w.start_tag(tag_meta_item_name); - rbml_w.writer.write(name.get().as_bytes()); + rbml_w.writer.write_all(name.get().as_bytes()); rbml_w.end_tag(); rbml_w.end_tag(); } @@ -1655,10 +1655,10 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { ast::LitStr(ref value, _) => { rbml_w.start_tag(tag_meta_item_name_value); rbml_w.start_tag(tag_meta_item_name); - rbml_w.writer.write(name.get().as_bytes()); + rbml_w.writer.write_all(name.get().as_bytes()); rbml_w.end_tag(); rbml_w.start_tag(tag_meta_item_value); - rbml_w.writer.write(value.get().as_bytes()); + rbml_w.writer.write_all(value.get().as_bytes()); rbml_w.end_tag(); rbml_w.end_tag(); } @@ -1668,7 +1668,7 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { ast::MetaList(ref name, ref items) => { rbml_w.start_tag(tag_meta_item_list); rbml_w.start_tag(tag_meta_item_name); - rbml_w.writer.write(name.get().as_bytes()); + rbml_w.writer.write_all(name.get().as_bytes()); rbml_w.end_tag(); for inner_item in items.iter() { encode_meta_item(rbml_w, &**inner_item); @@ -1800,7 +1800,7 @@ fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) { rbml_w.end_tag(); rbml_w.start_tag(tag_native_libraries_name); - rbml_w.writer.write(lib.as_bytes()); + rbml_w.writer.write_all(lib.as_bytes()); rbml_w.end_tag(); rbml_w.end_tag(); @@ -1975,29 +1975,29 @@ fn encode_crate_dep(rbml_w: &mut Encoder, dep: decoder::CrateDep) { rbml_w.start_tag(tag_crate_dep); rbml_w.start_tag(tag_crate_dep_crate_name); - rbml_w.writer.write(dep.name.as_bytes()); + rbml_w.writer.write_all(dep.name.as_bytes()); rbml_w.end_tag(); rbml_w.start_tag(tag_crate_dep_hash); - rbml_w.writer.write(dep.hash.as_str().as_bytes()); + rbml_w.writer.write_all(dep.hash.as_str().as_bytes()); rbml_w.end_tag(); rbml_w.end_tag(); } fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) { rbml_w.start_tag(tag_crate_hash); - rbml_w.writer.write(hash.as_str().as_bytes()); + rbml_w.writer.write_all(hash.as_str().as_bytes()); rbml_w.end_tag(); } fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) { rbml_w.start_tag(tag_crate_crate_name); - rbml_w.writer.write(crate_name.as_bytes()); + rbml_w.writer.write_all(crate_name.as_bytes()); rbml_w.end_tag(); } fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) { rbml_w.start_tag(tag_crate_triple); - rbml_w.writer.write(triple.as_bytes()); + rbml_w.writer.write_all(triple.as_bytes()); rbml_w.end_tag(); } @@ -2011,7 +2011,7 @@ fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) { cstore::RequireStatic => "s", })).to_string()) }).collect::>(); - rbml_w.writer.write(s.connect(",").as_bytes()); + rbml_w.writer.write_all(s.connect(",").as_bytes()); } None => {} } diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index ddee1f79d6a6..26046cfb43d8 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -13,8 +13,8 @@ pub use self::FileMatch::*; use std::collections::HashSet; -use std::io::fs::PathExtensions; -use std::io::fs; +use std::old_io::fs::PathExtensions; +use std::old_io::fs; use std::os; use util::fs as myfs; diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index b1043a4152cf..3ee4017292c4 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -231,8 +231,8 @@ use rustc_back::target::Target; use std::ffi::CString; use std::cmp; use std::collections::HashMap; -use std::io::fs::PathExtensions; -use std::io; +use std::old_io::fs::PathExtensions; +use std::old_io; use std::ptr; use std::slice; use std::time::Duration; @@ -796,7 +796,7 @@ pub fn read_meta_section_name(is_osx: bool) -> &'static str { // A diagnostic function for dumping crate metadata to an output stream pub fn list_file_metadata(is_osx: bool, path: &Path, - out: &mut io::Writer) -> io::IoResult<()> { + out: &mut old_io::Writer) -> old_io::IoResult<()> { match get_metadata_section(is_osx, path) { Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), Err(msg) => { diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index cb6b7e56b577..2ee4b6fbbd4a 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -377,6 +377,14 @@ fn parse_scope(st: &mut PState) -> region::CodeExtent { let node_id = parse_uint(st) as ast::NodeId; region::CodeExtent::Misc(node_id) } + 'B' => { + let node_id = parse_uint(st) as ast::NodeId; + let first_stmt_index = parse_uint(st); + let block_remainder = region::BlockRemainder { + block: node_id, first_statement_index: first_stmt_index, + }; + region::CodeExtent::Remainder(block_remainder) + } _ => panic!("parse_scope: bad input") } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 54b930fbda9c..2dc334bfe95f 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -51,7 +51,7 @@ pub type abbrev_map<'tcx> = RefCell, ty_abbrev>>; pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { match cx.abbrevs.borrow_mut().get(&t) { - Some(a) => { w.write(a.s.as_bytes()); return; } + Some(a) => { w.write_all(a.s.as_bytes()); return; } None => {} } let pos = w.tell().unwrap(); @@ -276,7 +276,9 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) { fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) { match scope { - region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id) + region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id), + region::CodeExtent::Remainder(region::BlockRemainder { + block: b, first_statement_index: i }) => mywrite!(w, "B{}{}", b, i), } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index fcc2be985a55..091ef9d52eb4 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -37,7 +37,7 @@ use syntax::parse::token; use syntax::ptr::P; use syntax; -use std::io::Seek; +use std::old_io::Seek; use std::rc::Rc; use rbml::io::SeekableMemWriter; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index a17278698103..d3c843d1d50c 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -19,7 +19,7 @@ pub use self::EntryOrExit::*; use middle::cfg; use middle::cfg::CFGIndex; use middle::ty; -use std::io; +use std::old_io; use std::uint; use std::iter::repeat; use syntax::ast; @@ -105,7 +105,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> { fn pre(&self, ps: &mut pprust::State, - node: pprust::AnnNode) -> io::IoResult<()> { + node: pprust::AnnNode) -> old_io::IoResult<()> { let id = match node { pprust::NodeIdent(_) | pprust::NodeName(_) => 0, pprust::NodeExpr(expr) => expr.id, @@ -457,13 +457,13 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { debug!("Dataflow result for {}:", self.analysis_name); debug!("{}", { - self.pretty_print_to(box io::stderr(), blk).unwrap(); + self.pretty_print_to(box old_io::stderr(), blk).unwrap(); "" }); } - fn pretty_print_to(&self, wr: Box, - blk: &ast::Block) -> io::IoResult<()> { + fn pretty_print_to(&self, wr: Box, + blk: &ast::Block) -> old_io::IoResult<()> { let mut ps = pprust::rust_printer_annotated(wr, self); try!(ps.cbox(pprust::indent_unit)); try!(ps.ibox(0u)); diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 18c36f870b5b..cfef88a8deb4 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -809,6 +809,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { let scope_id = same_regions[0].scope_id; let parent = self.tcx.map.get_parent(scope_id); let parent_node = self.tcx.map.find(parent); + let taken = lifetimes_in_scope(self.tcx, scope_id); + let life_giver = LifeGiver::with_taken(&taken[]); let node_inner = match parent_node { Some(ref node) => match *node { ast_map::NodeItem(ref item) => { @@ -851,8 +853,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { }; let (fn_decl, generics, unsafety, ident, expl_self, span) = node_inner.expect("expect item fn"); - let taken = lifetimes_in_scope(self.tcx, scope_id); - let life_giver = LifeGiver::with_taken(&taken[]); let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, generics, same_regions, &life_giver); let (fn_decl, expl_self, generics) = rebuilder.rebuild(); diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index f8f962cd86d2..8803fe7cf38a 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -26,7 +26,7 @@ use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux::Repr; use std::collections::hash_map::Entry::Vacant; -use std::io::{self, File}; +use std::old_io::{self, File}; use std::os; use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; use syntax::ast; @@ -217,7 +217,7 @@ pub type ConstraintMap<'tcx> = FnvHashMap>; fn dump_region_constraints_to<'a, 'tcx:'a >(tcx: &'a ty::ctxt<'tcx>, map: &ConstraintMap<'tcx>, - path: &str) -> io::IoResult<()> { + path: &str) -> old_io::IoResult<()> { debug!("dump_region_constraints map (len: {}) path: {}", map.len(), path); let g = ConstraintGraph::new(tcx, format!("region_constraints"), map); let mut f = File::create(&Path::new(path)); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 0131b9f1491e..00fa6546b480 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -118,7 +118,7 @@ use middle::ty::ClosureTyper; use lint; use util::nodemap::NodeMap; -use std::{fmt, io, uint}; +use std::{fmt, old_io, uint}; use std::rc::Rc; use std::iter::repeat; use syntax::ast::{self, NodeId, Expr}; @@ -693,10 +693,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn write_vars(&self, - wr: &mut io::Writer, + wr: &mut old_io::Writer, ln: LiveNode, mut test: F) - -> io::IoResult<()> where + -> old_io::IoResult<()> where F: FnMut(uint) -> LiveNode, { let node_base_idx = self.idx(ln, Variable(0)); @@ -740,7 +740,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn ln_str(&self, ln: LiveNode) -> String { let mut wr = Vec::new(); { - let wr = &mut wr as &mut io::Writer; + let wr = &mut wr as &mut old_io::Writer; write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln)); self.write_vars(wr, ln, |idx| self.users[idx].reader); write!(wr, " writes"); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 67c0e52d6649..9bba01f8af77 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -26,6 +26,7 @@ use syntax::codemap::{self, Span}; use syntax::{ast, visit}; use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local}; use syntax::ast_util::{stmt_id}; +use syntax::ast_map; use syntax::visit::{Visitor, FnKind}; /// CodeExtent represents a statically-describable extent that can be @@ -38,7 +39,32 @@ use syntax::visit::{Visitor, FnKind}; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Show, Copy)] pub enum CodeExtent { - Misc(ast::NodeId) + Misc(ast::NodeId), + Remainder(BlockRemainder), +} + +/// Represents a subscope of `block` for a binding that is introduced +/// by `block.stmts[first_statement_index]`. Such subscopes represent +/// a suffix of the block. Note that each subscope does not include +/// the initializer expression, if any, for the statement indexed by +/// `first_statement_index`. +/// +/// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`: +/// +/// * the subscope with `first_statement_index == 0` is scope of both +/// `a` and `b`; it does not include EXPR_1, but does include +/// everything after that first `let`. (If you want a scope that +/// includes EXPR_1 as well, then do not use `CodeExtent::Remainder`, +/// but instead another `CodeExtent` that encompasses the whole block, +/// e.g. `CodeExtent::Misc`. +/// +/// * the subscope with `first_statement_index == 1` is scope of `c`, +/// and thus does not include EXPR_2, but covers the `...`. +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, + RustcDecodable, Show, Copy)] +pub struct BlockRemainder { + pub block: ast::NodeId, + pub first_statement_index: uint, } impl CodeExtent { @@ -55,6 +81,7 @@ impl CodeExtent { pub fn node_id(&self) -> ast::NodeId { match *self { CodeExtent::Misc(node_id) => node_id, + CodeExtent::Remainder(br) => br.block, } } @@ -65,8 +92,41 @@ impl CodeExtent { { match *self { CodeExtent::Misc(node_id) => CodeExtent::Misc(f_id(node_id)), + CodeExtent::Remainder(br) => + CodeExtent::Remainder(BlockRemainder { + block: f_id(br.block), first_statement_index: br.first_statement_index }), } } + + /// Returns the span of this CodeExtent. Note that in general the + /// returned span may not correspond to the span of any node id in + /// the AST. + pub fn span(&self, ast_map: &ast_map::Map) -> Option { + match ast_map.find(self.node_id()) { + Some(ast_map::NodeBlock(ref blk)) => { + match *self { + CodeExtent::Misc(_) => Some(blk.span), + + CodeExtent::Remainder(r) => { + assert_eq!(r.block, blk.id); + // Want span for extent starting after the + // indexed statement and ending at end of + // `blk`; reuse span of `blk` and shift `lo` + // forward to end of indexed statement. + // + // (This is the special case aluded to in the + // doc-comment for this method) + let stmt_span = blk.stmts[r.first_statement_index].span; + Some(Span { lo: stmt_span.hi, ..blk.span }) + } + } + } + Some(ast_map::NodeExpr(ref expr)) => Some(expr.span), + Some(ast_map::NodeStmt(ref stmt)) => Some(stmt.span), + Some(ast_map::NodeItem(ref item)) => Some(item.span), + Some(_) | None => None, + } + } } /// The region maps encode information about region relationships. @@ -74,7 +134,8 @@ impl CodeExtent { /// - `scope_map` maps from a scope id to the enclosing scope id; this is /// usually corresponding to the lexical nesting, though in the case of /// closures the parent scope is the innermost conditional expression or repeating -/// block +/// block. (Note that the enclosing scope id for the block +/// associated with a closure is the closure itself.) /// /// - `var_map` maps from a variable or binding id to the block in which /// that variable is declared. @@ -115,12 +176,77 @@ pub struct RegionMaps { terminating_scopes: RefCell>, } -#[derive(Copy)] -pub struct Context { - var_parent: Option, +/// Carries the node id for the innermost block or match expression, +/// for building up the `var_map` which maps ids to the blocks in +/// which they were declared. +#[derive(PartialEq, Eq, Show, Copy)] +enum InnermostDeclaringBlock { + None, + Block(ast::NodeId), + Statement(DeclaringStatementContext), + Match(ast::NodeId), +} - // Innermost enclosing expression - parent: Option, +impl InnermostDeclaringBlock { + fn to_code_extent(&self) -> Option { + let extent = match *self { + InnermostDeclaringBlock::None => { + return Option::None; + } + InnermostDeclaringBlock::Block(id) | + InnermostDeclaringBlock::Match(id) => CodeExtent::from_node_id(id), + InnermostDeclaringBlock::Statement(s) => s.to_code_extent(), + }; + Option::Some(extent) + } +} + +/// Contextual information for declarations introduced by a statement +/// (i.e. `let`). It carries node-id's for statement and enclosing +/// block both, as well as the statement's index within the block. +#[derive(PartialEq, Eq, Show, Copy)] +struct DeclaringStatementContext { + stmt_id: ast::NodeId, + block_id: ast::NodeId, + stmt_index: uint, +} + +impl DeclaringStatementContext { + fn to_code_extent(&self) -> CodeExtent { + CodeExtent::Remainder(BlockRemainder { + block: self.block_id, + first_statement_index: self.stmt_index, + }) + } +} + +#[derive(PartialEq, Eq, Show, Copy)] +enum InnermostEnclosingExpr { + None, + Some(ast::NodeId), + Statement(DeclaringStatementContext), +} + +impl InnermostEnclosingExpr { + fn to_code_extent(&self) -> Option { + let extent = match *self { + InnermostEnclosingExpr::None => { + return Option::None; + } + InnermostEnclosingExpr::Statement(s) => + s.to_code_extent(), + InnermostEnclosingExpr::Some(parent_id) => + CodeExtent::from_node_id(parent_id), + }; + Some(extent) + } +} + +#[derive(Show, Copy)] +pub struct Context { + var_parent: InnermostDeclaringBlock, + + parent: InnermostEnclosingExpr, } struct RegionResolutionVisitor<'a> { @@ -381,16 +507,13 @@ impl RegionMaps { } } -/// Records the current parent (if any) as the parent of `child_id`. +/// Records the current parent (if any) as the parent of `child_scope`. fn record_superlifetime(visitor: &mut RegionResolutionVisitor, - child_id: ast::NodeId, + child_scope: CodeExtent, _sp: Span) { - match visitor.cx.parent { - Some(parent_id) => { - let child_scope = CodeExtent::from_node_id(child_id); - let parent_scope = CodeExtent::from_node_id(parent_id); - visitor.region_maps.record_encl_scope(child_scope, parent_scope); - } + match visitor.cx.parent.to_code_extent() { + Some(parent_scope) => + visitor.region_maps.record_encl_scope(child_scope, parent_scope), None => {} } } @@ -399,11 +522,9 @@ fn record_superlifetime(visitor: &mut RegionResolutionVisitor, fn record_var_lifetime(visitor: &mut RegionResolutionVisitor, var_id: ast::NodeId, _sp: Span) { - match visitor.cx.var_parent { - Some(parent_id) => { - let parent_scope = CodeExtent::from_node_id(parent_id); - visitor.region_maps.record_var_scope(var_id, parent_scope); - } + match visitor.cx.var_parent.to_code_extent() { + Some(parent_scope) => + visitor.region_maps.record_var_scope(var_id, parent_scope), None => { // this can happen in extern fn declarations like // @@ -415,21 +536,72 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor, fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) { debug!("resolve_block(blk.id={:?})", blk.id); - // Record the parent of this block. - record_superlifetime(visitor, blk.id, blk.span); + let prev_cx = visitor.cx; + + let blk_scope = CodeExtent::Misc(blk.id); + record_superlifetime(visitor, blk_scope, blk.span); // We treat the tail expression in the block (if any) somewhat // differently from the statements. The issue has to do with - // temporary lifetimes. If the user writes: + // temporary lifetimes. Consider the following: // - // { - // ... (&foo()) ... - // } + // quux({ + // let inner = ... (&bar()) ...; // + // (... (&foo()) ...) // (the tail expression) + // }, other_argument()); + // + // Each of the statements within the block is a terminating + // scope, and thus a temporary (e.g. the result of calling + // `bar()` in the initalizer expression for `let inner = ...;`) + // will be cleaned up immediately after its corresponding + // statement (i.e. `let inner = ...;`) executes. + // + // On the other hand, temporaries associated with evaluating the + // tail expression for the block are assigned lifetimes so that + // they will be cleaned up as part of the terminating scope + // *surrounding* the block expression. Here, the terminating + // scope for the block expression is the `quux(..)` call; so + // those temporaries will only be cleaned up *after* both + // `other_argument()` has run and also the call to `quux(..)` + // itself has returned. + + visitor.cx = Context { + var_parent: InnermostDeclaringBlock::Block(blk.id), + parent: InnermostEnclosingExpr::Some(blk.id), + }; + + { + // This block should be kept approximately in sync with + // `visit::walk_block`. (We manually walk the block, rather + // than call `walk_block`, in order to maintain precise + // `InnermostDeclaringBlock` information.) + + for (i, statement) in blk.stmts.iter().enumerate() { + if let ast::StmtDecl(_, stmt_id) = statement.node { + // Each StmtDecl introduces a subscope for bindings + // introduced by the declaration; this subscope covers + // a suffix of the block . Each subscope in a block + // has the previous subscope in the block as a parent, + // except for the first such subscope, which has the + // block itself as a parent. + let declaring = DeclaringStatementContext { + stmt_id: stmt_id, + block_id: blk.id, + stmt_index: i, + }; + record_superlifetime( + visitor, declaring.to_code_extent(), statement.span); + visitor.cx = Context { + var_parent: InnermostDeclaringBlock::Statement(declaring), + parent: InnermostEnclosingExpr::Statement(declaring), + }; + } + visitor.visit_stmt(&**statement) + } + visit::walk_expr_opt(visitor, &blk.expr) + } - let prev_cx = visitor.cx; - visitor.cx = Context {var_parent: Some(blk.id), parent: Some(blk.id)}; - visit::walk_block(visitor, blk); visitor.cx = prev_cx; } @@ -449,7 +621,7 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &ast::Arm) { } fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &ast::Pat) { - record_superlifetime(visitor, pat.id, pat.span); + record_superlifetime(visitor, CodeExtent::from_node_id(pat.id), pat.span); // If this is a binding (or maybe a binding, I'm too lazy to check // the def map) then record the lifetime of that binding. @@ -468,11 +640,17 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) { debug!("resolve_stmt(stmt.id={:?})", stmt_id); let stmt_scope = CodeExtent::from_node_id(stmt_id); + + // Every statement will clean up the temporaries created during + // execution of that statement. Therefore each statement has an + // associated destruction scope that represents the extent of the + // statement plus its destructors, and thus the extent for which + // regions referenced by the destructors need to survive. visitor.region_maps.mark_as_terminating_scope(stmt_scope); - record_superlifetime(visitor, stmt_id, stmt.span); + record_superlifetime(visitor, stmt_scope, stmt.span); let prev_parent = visitor.cx.parent; - visitor.cx.parent = Some(stmt_id); + visitor.cx.parent = InnermostEnclosingExpr::Some(stmt_id); visit::walk_stmt(visitor, stmt); visitor.cx.parent = prev_parent; } @@ -480,10 +658,11 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) { fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { debug!("resolve_expr(expr.id={:?})", expr.id); - record_superlifetime(visitor, expr.id, expr.span); + let expr_scope = CodeExtent::Misc(expr.id); + record_superlifetime(visitor, expr_scope, expr.span); let prev_cx = visitor.cx; - visitor.cx.parent = Some(expr.id); + visitor.cx.parent = InnermostEnclosingExpr::Some(expr.id); { let region_maps = &mut visitor.region_maps; @@ -527,11 +706,11 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { // The variable parent of everything inside (most importantly, the // pattern) is the body. - visitor.cx.var_parent = Some(body.id); + visitor.cx.var_parent = InnermostDeclaringBlock::Block(body.id); } ast::ExprMatch(..) => { - visitor.cx.var_parent = Some(expr.id); + visitor.cx.var_parent = InnermostDeclaringBlock::Match(expr.id); } ast::ExprAssignOp(..) | ast::ExprIndex(..) | @@ -568,19 +747,13 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { debug!("resolve_local(local.id={:?},local.init={:?})", local.id,local.init.is_some()); - let blk_id = match visitor.cx.var_parent { - Some(id) => id, - None => { - visitor.sess.span_bug( - local.span, - "local without enclosing block"); - } - }; - // For convenience in trans, associate with the local-id the var // scope that will be used for any bindings declared in this // pattern. - let blk_scope = CodeExtent::from_node_id(blk_id); + let blk_scope = visitor.cx.var_parent.to_code_extent() + .unwrap_or_else(|| visitor.sess.span_bug( + local.span, "local without enclosing block")); + visitor.region_maps.record_var_scope(local.id, blk_scope); // As an exception to the normal rules governing temporary @@ -803,7 +976,10 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) { // Items create a new outer block scope as far as we're concerned. let prev_cx = visitor.cx; - visitor.cx = Context {var_parent: None, parent: None}; + visitor.cx = Context { + var_parent: InnermostDeclaringBlock::None, + parent: InnermostEnclosingExpr::None + }; visit::walk_item(visitor, item); visitor.cx = prev_cx; } @@ -829,15 +1005,20 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, let outer_cx = visitor.cx; // The arguments and `self` are parented to the body of the fn. - visitor.cx = Context { parent: Some(body.id), - var_parent: Some(body.id) }; + visitor.cx = Context { + parent: InnermostEnclosingExpr::Some(body.id), + var_parent: InnermostDeclaringBlock::Block(body.id) + }; visit::walk_fn_decl(visitor, decl); // The body of the fn itself is either a root scope (top-level fn) // or it continues with the inherited scope (closures). match fk { visit::FkItemFn(..) | visit::FkMethod(..) => { - visitor.cx = Context { parent: None, var_parent: None }; + visitor.cx = Context { + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None + }; visitor.visit_block(body); visitor.cx = outer_cx; } @@ -898,7 +1079,10 @@ pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps { let mut visitor = RegionResolutionVisitor { sess: sess, region_maps: &maps, - cx: Context { parent: None, var_parent: None } + cx: Context { + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None, + } }; visit::walk_crate(&mut visitor, krate); } @@ -911,7 +1095,10 @@ pub fn resolve_inlined_item(sess: &Session, let mut visitor = RegionResolutionVisitor { sess: sess, region_maps: region_maps, - cx: Context { parent: None, var_parent: None } + cx: Context { + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None + } }; visit::walk_inlined_item(&mut visitor, item); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 0ee26ce1cd3c..86cf030c8288 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3126,7 +3126,6 @@ pub fn type_is_scalar(ty: Ty) -> bool { ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) | ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_bare_fn(..) | ty_ptr(_) => true, - ty_tup(ref tys) if tys.is_empty() => true, _ => false } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index f93f5903e014..5601898136c7 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,6 +10,7 @@ use middle::def; +use middle::region; use middle::subst::{VecPerParamSpace,Subst}; use middle::subst; use middle::ty::{BoundRegion, BrAnon, BrNamed}; @@ -84,37 +85,41 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) -> (String, Option) { return match region { ReScope(scope) => { - match cx.map.find(scope.node_id()) { - Some(ast_map::NodeBlock(ref blk)) => { - explain_span(cx, "block", blk.span) - } - Some(ast_map::NodeExpr(expr)) => { - match expr.node { - ast::ExprCall(..) => explain_span(cx, "call", expr.span), - ast::ExprMethodCall(..) => { - explain_span(cx, "method call", expr.span) - }, - ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => - explain_span(cx, "if let", expr.span), - ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => { - explain_span(cx, "while let", expr.span) - }, - ast::ExprMatch(..) => explain_span(cx, "match", expr.span), - _ => explain_span(cx, "expression", expr.span) - } - } - Some(ast_map::NodeStmt(stmt)) => { - explain_span(cx, "statement", stmt.span) - } - Some(ast_map::NodeItem(it)) => { - let tag = item_scope_tag(&*it); - explain_span(cx, tag, it.span) - } + let new_string; + let on_unknown_scope = |&:| { + (format!("unknown scope: {:?}. Please report a bug.", scope), None) + }; + let span = match scope.span(&cx.map) { + Some(s) => s, + None => return on_unknown_scope(), + }; + let tag = match cx.map.find(scope.node_id()) { + Some(ast_map::NodeBlock(_)) => "block", + Some(ast_map::NodeExpr(expr)) => match expr.node { + ast::ExprCall(..) => "call", + ast::ExprMethodCall(..) => "method call", + ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let", + ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => "while let", + ast::ExprMatch(..) => "match", + _ => "expression", + }, + Some(ast_map::NodeStmt(_)) => "statement", + Some(ast_map::NodeItem(it)) => item_scope_tag(&*it), Some(_) | None => { // this really should not happen - (format!("unknown scope: {:?}. Please report a bug.", scope), None) + return on_unknown_scope(); } - } + }; + let scope_decorated_tag = match scope { + region::CodeExtent::Misc(_) => tag, + region::CodeExtent::Remainder(r) => { + new_string = format!("block suffix following statement {}", + r.first_statement_index); + new_string.as_slice() + } + }; + explain_span(cx, scope_decorated_tag, span) + } ReFree(ref fr) => { @@ -867,6 +872,17 @@ impl<'tcx> Repr<'tcx> for ty::FreeRegion { } } +impl<'tcx> Repr<'tcx> for region::CodeExtent { + fn repr(&self, _tcx: &ctxt) -> String { + match *self { + region::CodeExtent::Misc(node_id) => + format!("Misc({})", node_id), + region::CodeExtent::Remainder(rem) => + format!("Remainder({}, {})", rem.block, rem.first_statement_index), + } + } +} + impl<'tcx> Repr<'tcx> for ast::DefId { fn repr(&self, tcx: &ctxt) -> String { // Unfortunately, there seems to be no way to attempt to print diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index fa754b4a3018..ee8bc71668b3 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -10,10 +10,10 @@ //! A helper class for dealing with static archives -use std::io::fs::PathExtensions; -use std::io::process::{Command, ProcessOutput}; -use std::io::{fs, TempDir}; -use std::io; +use std::old_io::fs::PathExtensions; +use std::old_io::process::{Command, ProcessOutput}; +use std::old_io::{fs, TempDir}; +use std::old_io; use std::os; use std::str; use syntax::diagnostic::Handler as ErrorHandler; @@ -172,7 +172,7 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. - pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> { + pub fn add_native_library(&mut self, name: &str) -> old_io::IoResult<()> { let location = find_library(name, &self.archive.slib_prefix[], &self.archive.slib_suffix[], @@ -187,7 +187,7 @@ impl<'a> ArchiveBuilder<'a> { /// This ignores adding the bytecode from the rlib, and if LTO is enabled /// then the object file also isn't added. pub fn add_rlib(&mut self, rlib: &Path, name: &str, - lto: bool) -> io::IoResult<()> { + lto: bool) -> old_io::IoResult<()> { // Ignoring obj file starting with the crate name // as simple comparison is not enough - there // might be also an extra name suffix @@ -205,7 +205,7 @@ impl<'a> ArchiveBuilder<'a> { } /// Adds an arbitrary file to this archive - pub fn add_file(&mut self, file: &Path) -> io::IoResult<()> { + pub fn add_file(&mut self, file: &Path) -> old_io::IoResult<()> { let filename = Path::new(file.filename().unwrap()); let new_file = self.work_dir.path().join(&filename); try!(fs::copy(file, &new_file)); @@ -274,8 +274,9 @@ impl<'a> ArchiveBuilder<'a> { self.archive } - fn add_archive(&mut self, archive: &Path, name: &str, mut skip: F) -> io::IoResult<()> where - F: FnMut(&str) -> bool, + fn add_archive(&mut self, archive: &Path, name: &str, + mut skip: F) -> old_io::IoResult<()> + where F: FnMut(&str) -> bool, { let loc = TempDir::new("rsar").unwrap(); diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index d7deb09985f7..24f81b024789 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::io; -use std::io::fs; +use std::old_io; +use std::old_io::fs; use std::os; /// Returns an absolute path in the filesystem that `path` points to. The /// returned path does not contain any symlinks in its hierarchy. -pub fn realpath(original: &Path) -> io::IoResult { +pub fn realpath(original: &Path) -> old_io::IoResult { static MAX_LINKS_FOLLOWED: uint = 256; let original = os::make_absolute(original).unwrap(); @@ -32,12 +32,12 @@ pub fn realpath(original: &Path) -> io::IoResult { loop { if followed == MAX_LINKS_FOLLOWED { - return Err(io::standard_error(io::InvalidInput)) + return Err(old_io::standard_error(old_io::InvalidInput)) } match fs::lstat(&result) { Err(..) => break, - Ok(ref stat) if stat.kind != io::FileType::Symlink => break, + Ok(ref stat) if stat.kind != old_io::FileType::Symlink => break, Ok(..) => { followed += 1; let path = try!(fs::readlink(&result)); @@ -53,10 +53,10 @@ pub fn realpath(original: &Path) -> io::IoResult { #[cfg(all(not(windows), test))] mod test { - use std::io; - use std::io::fs::{File, symlink, mkdir, mkdir_recursive}; + use std::old_io; + use std::old_io::fs::{File, symlink, mkdir, mkdir_recursive}; use super::realpath; - use std::io::TempDir; + use std::old_io::TempDir; #[test] fn realpath_works() { @@ -68,7 +68,7 @@ mod test { let linkdir = tmpdir.join("test3"); File::create(&file).unwrap(); - mkdir(&dir, io::USER_RWX).unwrap(); + mkdir(&dir, old_io::USER_RWX).unwrap(); symlink(&file, &link).unwrap(); symlink(&dir, &linkdir).unwrap(); @@ -91,8 +91,8 @@ mod test { let e = d.join("e"); let f = a.join("f"); - mkdir_recursive(&b, io::USER_RWX).unwrap(); - mkdir_recursive(&d, io::USER_RWX).unwrap(); + mkdir_recursive(&b, old_io::USER_RWX).unwrap(); + mkdir_recursive(&d, old_io::USER_RWX).unwrap(); File::create(&f).unwrap(); symlink(&Path::new("../d/e"), &c).unwrap(); symlink(&Path::new("../f"), &e).unwrap(); diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index d24fd6a5b3f0..bafd5fbe9448 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -11,7 +11,7 @@ use std::collections::HashSet; use std::os; -use std::io::IoError; +use std::old_io::IoError; use syntax::ast; pub struct RPathConfig where diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index ac133cabc3b8..715bcc4f36dd 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::io::{Command, IoError, OtherIoError}; +use std::old_io::{Command, IoError, OtherIoError}; use target::TargetOptions; use self::Arch::*; diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs index 1b079323bf9c..fcea900283d2 100644 --- a/src/librustc_back/target/i686_apple_darwin.rs +++ b/src/librustc_back/target/i686_apple_darwin.rs @@ -12,6 +12,7 @@ use target::Target; pub fn target() -> Target { let mut base = super::apple_base::opts(); + base.cpu = "yonah".to_string(); base.pre_link_args.push("-m32".to_string()); Target { diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs index c2ab68ee0525..249f2d440e68 100644 --- a/src/librustc_back/target/i686_pc_windows_gnu.rs +++ b/src/librustc_back/target/i686_pc_windows_gnu.rs @@ -12,6 +12,7 @@ use target::Target; pub fn target() -> Target { let mut options = super::windows_base::opts(); + options.cpu = "pentium4".to_string(); // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs index 7910eba7ea12..4450d8d67782 100644 --- a/src/librustc_back/target/i686_unknown_dragonfly.rs +++ b/src/librustc_back/target/i686_unknown_dragonfly.rs @@ -12,6 +12,7 @@ use target::Target; pub fn target() -> Target { let mut base = super::dragonfly_base::opts(); + base.cpu = "pentium4".to_string(); base.pre_link_args.push("-m32".to_string()); Target { diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs index c93a564fef5f..f21f6adfb4c0 100644 --- a/src/librustc_back/target/i686_unknown_linux_gnu.rs +++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs @@ -12,6 +12,7 @@ use target::Target; pub fn target() -> Target { let mut base = super::linux_base::opts(); + base.cpu = "pentium4".to_string(); base.pre_link_args.push("-m32".to_string()); Target { diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index dd0fa527f172..a63e8237b4be 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -48,7 +48,7 @@ use serialize::json::Json; use syntax::{diagnostic, abi}; use std::default::Default; -use std::io::fs::PathExtensions; +use std::old_io::fs::PathExtensions; mod windows_base; mod linux_base; @@ -302,7 +302,7 @@ impl Target { /// JSON decoding. pub fn search(target: &str) -> Result { use std::os; - use std::io::File; + use std::old_io::File; use std::path::Path; use serialize::json; diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs index f2abfd4564c7..0b3b2bea62d7 100644 --- a/src/librustc_back/target/x86_64_apple_darwin.rs +++ b/src/librustc_back/target/x86_64_apple_darwin.rs @@ -12,7 +12,7 @@ use target::Target; pub fn target() -> Target { let mut base = super::apple_base::opts(); - base.cpu = "x86-64".to_string(); + base.cpu = "core2".to_string(); base.eliminate_frame_pointer = false; base.pre_link_args.push("-m64".to_string()); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4d5c2b765fee..6e76519ce236 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -30,8 +30,8 @@ use rustc_privacy; use serialize::json; -use std::io; -use std::io::fs; +use std::old_io; +use std::old_io::fs; use std::os; use syntax::ast; use syntax::ast_map; @@ -100,6 +100,7 @@ pub fn compile_input(sess: Session, &id[])); let mut forest = ast_map::Forest::new(expanded_crate); + let arenas = ty::CtxtArenas::new(); let ast_map = assign_node_ids_and_map(&sess, &mut forest); write_out_deps(&sess, input, &outputs, &id[]); @@ -111,7 +112,6 @@ pub fn compile_input(sess: Session, &ast_map, &id[])); - let arenas = ty::CtxtArenas::new(); let analysis = phase_3_run_analysis_passes(sess, ast_map, &arenas, @@ -794,14 +794,14 @@ fn write_out_deps(sess: &Session, _ => return, }; - let result = (|&:| -> io::IoResult<()> { + let result = (|&:| -> old_io::IoResult<()> { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let files: Vec = sess.codemap().files.borrow() .iter().filter(|fmap| fmap.is_real_file()) .map(|fmap| escape_dep_filename(&fmap.name[])) .collect(); - let mut file = try!(io::File::create(&deps_filename)); + let mut file = try!(old_io::File::create(&deps_filename)); for path in out_filenames.iter() { try!(write!(&mut file as &mut Writer, "{}: {}\n\n", path.display(), files.connect(" "))); diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index ffce577899bf..727638c29c35 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -73,7 +73,7 @@ use rustc::metadata::creader::CrateOrString::Str; use rustc::util::common::time; use std::cmp::Ordering::Equal; -use std::io; +use std::old_io; use std::iter::repeat; use std::os; use std::sync::mpsc::channel; @@ -142,7 +142,7 @@ fn run_compiler(args: &[String]) { 1u => { let ifile = &matches.free[0][]; if ifile == "-" { - let contents = io::stdin().read_to_end().unwrap(); + let contents = old_io::stdin().read_to_end().unwrap(); let src = String::from_utf8(contents).unwrap(); (Input::Str(src), None) } else { @@ -196,7 +196,7 @@ fn run_compiler(args: &[String]) { if r.contains(&("ls".to_string())) { match input { Input::File(ref ifile) => { - let mut stdout = io::stdout(); + let mut stdout = old_io::stdout(); list_metadata(&sess, &(*ifile), &mut stdout).unwrap(); } Input::Str(_) => { @@ -599,7 +599,7 @@ fn parse_crate_attrs(sess: &Session, input: &Input) -> } pub fn list_metadata(sess: &Session, path: &Path, - out: &mut io::Writer) -> io::IoResult<()> { + out: &mut old_io::Writer) -> old_io::IoResult<()> { metadata::loader::list_file_metadata(sess.target.target.options.is_like_osx, path, out) } @@ -612,8 +612,8 @@ pub fn monitor(f: F) { static STACK_SIZE: uint = 8 * 1024 * 1024; // 8MB let (tx, rx) = channel(); - let w = io::ChanWriter::new(tx); - let mut r = io::ChanReader::new(rx); + let w = old_io::ChanWriter::new(tx); + let mut r = old_io::ChanReader::new(rx); let mut cfg = thread::Builder::new().name("rustc".to_string()); @@ -623,7 +623,7 @@ pub fn monitor(f: F) { cfg = cfg.stack_size(STACK_SIZE); } - match cfg.scoped(move || { std::io::stdio::set_stderr(box w); f() }).join() { + match cfg.scoped(move || { std::old_io::stdio::set_stderr(box w); f() }).join() { Ok(()) => { /* fallthrough */ } Err(value) => { // Thread panicked without emitting a fatal diagnostic @@ -665,7 +665,7 @@ pub fn monitor(f: F) { // Panic so the process returns a failure code, but don't pollute the // output with some unnecessary panic messages, we've already // printed everything that we needed to. - io::stdio::set_stderr(box io::util::NullWriter); + old_io::stdio::set_stderr(box old_io::util::NullWriter); panic!(); } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 582e10323248..b09e9f143577 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -38,7 +38,7 @@ use syntax::ptr::P; use graphviz as dot; -use std::io::{self, MemReader}; +use std::old_io::{self, MemReader}; use std::option; use std::str::FromStr; @@ -208,7 +208,7 @@ impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> { impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { fn pre(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> io::IoResult<()> { + node: pprust::AnnNode) -> old_io::IoResult<()> { match node { pprust::NodeExpr(_) => s.popen(), _ => Ok(()) @@ -216,7 +216,7 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { } fn post(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> io::IoResult<()> { + node: pprust::AnnNode) -> old_io::IoResult<()> { match node { pprust::NodeIdent(_) | pprust::NodeName(_) => Ok(()), @@ -259,7 +259,7 @@ impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { fn post(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> io::IoResult<()> { + node: pprust::AnnNode) -> old_io::IoResult<()> { match node { pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => { try!(pp::space(&mut s.s)); @@ -294,7 +294,7 @@ impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> { impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { fn pre(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> io::IoResult<()> { + node: pprust::AnnNode) -> old_io::IoResult<()> { match node { pprust::NodeExpr(_) => s.popen(), _ => Ok(()) @@ -302,7 +302,7 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { } fn post(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> io::IoResult<()> { + node: pprust::AnnNode) -> old_io::IoResult<()> { let tcx = &self.analysis.ty_cx; match node { pprust::NodeExpr(expr) => { @@ -548,9 +548,9 @@ pub fn pretty_print_input(sess: Session, let mut rdr = MemReader::new(src); let out = match ofile { - None => box io::stdout() as Box, + None => box old_io::stdout() as Box, Some(p) => { - let r = io::File::create(&p); + let r = old_io::File::create(&p); match r { Ok(w) => box w as Box, Err(e) => panic!("print-print failed to open {} due to {}", @@ -643,11 +643,11 @@ pub fn pretty_print_input(sess: Session, }.unwrap() } -fn print_flowgraph(variants: Vec, +fn print_flowgraph(variants: Vec, analysis: ty::CrateAnalysis, code: blocks::Code, mode: PpFlowGraphMode, - mut out: W) -> io::IoResult<()> { + mut out: W) -> old_io::IoResult<()> { let ty_cx = &analysis.ty_cx; let cfg = match code { blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block), @@ -687,11 +687,11 @@ fn print_flowgraph(variants: Vec, } } - fn expand_err_details(r: io::IoResult<()>) -> io::IoResult<()> { + fn expand_err_details(r: old_io::IoResult<()>) -> old_io::IoResult<()> { r.map_err(|ioerr| { let orig_detail = ioerr.detail.clone(); let m = "graphviz::render failed"; - io::IoError { + old_io::IoError { detail: Some(match orig_detail { None => m.to_string(), Some(d) => format!("{}: {}", m, d) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 3543fe072690..52d7415a523d 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -103,7 +103,7 @@ fn test_env(source_string: &str, let codemap = CodeMap::new(); let diagnostic_handler = - diagnostic::mk_handler(emitter); + diagnostic::mk_handler(true, emitter); let span_diagnostic_handler = diagnostic::mk_span_handler(diagnostic_handler, codemap); @@ -115,6 +115,7 @@ fn test_env(source_string: &str, .expect("phase 2 aborted"); let mut forest = ast_map::Forest::new(krate); + let arenas = ty::CtxtArenas::new(); let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest); let krate = ast_map.krate(); @@ -125,7 +126,6 @@ fn test_env(source_string: &str, let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map); let region_map = region::resolve_crate(&sess, krate); let stability_index = stability::Index::build(&sess, krate); - let arenas = ty::CtxtArenas::new(); let tcx = ty::mk_ctxt(sess, &arenas, def_map, diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index eedfc9407515..f5a6f3d95a2c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -27,9 +27,9 @@ use util::common::time; use util::ppaux; use util::sha2::{Digest, Sha256}; -use std::io::fs::PathExtensions; -use std::io::{fs, TempDir, Command}; -use std::io; +use std::old_io::fs::PathExtensions; +use std::old_io::{fs, TempDir, Command}; +use std::old_io; use std::mem; use std::str; use std::string::String; @@ -425,7 +425,7 @@ pub fn invalid_output_for_target(sess: &Session, fn is_writeable(p: &Path) -> bool { match p.stat() { Err(..) => true, - Ok(m) => m.perm & io::USER_WRITE == io::USER_WRITE + Ok(m) => m.perm & old_io::USER_WRITE == old_io::USER_WRITE } } @@ -586,8 +586,7 @@ fn link_rlib<'a>(sess: &'a Session, // the same filename for metadata (stomping over one another) let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir"); let metadata = tmpdir.path().join(METADATA_FILENAME); - match fs::File::create(&metadata).write(&trans.metadata - []) { + match fs::File::create(&metadata).write_all(&trans.metadata[]) { Ok(..) => {} Err(e) => { sess.err(&format!("failed to write {}: {}", @@ -671,13 +670,13 @@ fn link_rlib<'a>(sess: &'a Session, fn write_rlib_bytecode_object_v1(writer: &mut T, bc_data_deflated: &[u8]) - -> ::std::io::IoResult<()> { + -> ::std::old_io::IoResult<()> { let bc_data_deflated_size: u64 = bc_data_deflated.len() as u64; - try! { writer.write(RLIB_BYTECODE_OBJECT_MAGIC) }; + try! { writer.write_all(RLIB_BYTECODE_OBJECT_MAGIC) }; try! { writer.write_le_u32(1) }; try! { writer.write_le_u64(bc_data_deflated_size) }; - try! { writer.write(&bc_data_deflated[]) }; + try! { writer.write_all(&bc_data_deflated[]) }; let number_of_bytes_written_so_far = RLIB_BYTECODE_OBJECT_MAGIC.len() + // magic id @@ -1201,7 +1200,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // Fix up permissions of the copy, as fs::copy() preserves // permissions, but the original file may have been installed // by a package manager and may be read-only. - match fs::chmod(&dst, io::USER_READ | io::USER_WRITE) { + match fs::chmod(&dst, old_io::USER_READ | old_io::USER_WRITE) { Ok(..) => {} Err(e) => { sess.err(&format!("failed to chmod {} when preparing \ diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 4fd456d813a6..15b9d6237ed4 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -23,8 +23,8 @@ use syntax::diagnostic; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; use std::ffi::{self, CString}; -use std::io::Command; -use std::io::fs; +use std::old_io::Command; +use std::old_io::fs; use std::iter::Unfold; use std::ptr; use std::str; @@ -728,9 +728,9 @@ pub fn run_passes(sess: &Session, println!("{:?}", &cmd); } - cmd.stdin(::std::io::process::Ignored) - .stdout(::std::io::process::InheritFd(1)) - .stderr(::std::io::process::InheritFd(2)); + cmd.stdin(::std::old_io::process::Ignored) + .stdout(::std::old_io::process::InheritFd(1)) + .stderr(::std::old_io::process::InheritFd(2)); match cmd.status() { Ok(status) => { if !status.success() { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 71ca6a4db03d..7e7176d661c6 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -33,7 +33,7 @@ use middle::def; use middle::ty::{self, Ty}; use std::cell::Cell; -use std::io::{self, File, fs}; +use std::old_io::{self, File, fs}; use std::os; use syntax::ast_util::{self, PostExpansionMethod}; @@ -1532,7 +1532,7 @@ pub fn process_crate(sess: &Session, }, }; - match fs::mkdir_recursive(&root_path, io::USER_RWX) { + match fs::mkdir_recursive(&root_path, old_io::USER_RWX) { Err(e) => sess.err(&format!("Could not create directory {}: {}", root_path.display(), e)[]), _ => (), diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 230a4c5d4272..5a98bc4da368 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -1784,15 +1784,16 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("trans_closure(..., param_substs={})", param_substs.repr(ccx.tcx())); - let arena = TypedArena::new(); - let fcx = new_fn_ctxt(ccx, - llfndecl, - fn_ast_id, - closure_env.kind != closure::NotClosure, - output_type, - param_substs, - Some(body.span), - &arena); + let (arena, fcx): (TypedArena<_>, FunctionContext); + arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, + llfndecl, + fn_ast_id, + closure_env.kind != closure::NotClosure, + output_type, + param_substs, + Some(body.span), + &arena); let mut bcx = init_function(&fcx, false, output_type); // cleanup scope for the incoming arguments @@ -2046,9 +2047,10 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx ty_to_string(ccx.tcx(), ctor_ty))[]) }; - let arena = TypedArena::new(); - let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty, - param_substs, None, &arena); + let (arena, fcx): (TypedArena<_>, FunctionContext); + arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty, + param_substs, None, &arena); let bcx = init_function(&fcx, false, result_ty); assert!(!fcx.needs_ret_allocas); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 73d174c2c341..d038407791ef 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -322,16 +322,17 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( &function_name[]); // - let block_arena = TypedArena::new(); let empty_substs = Substs::trans_empty(); - let fcx = new_fn_ctxt(ccx, - llfn, - ast::DUMMY_NODE_ID, - false, - sig.output, - &empty_substs, - None, - &block_arena); + let (block_arena, fcx): (TypedArena<_>, FunctionContext); + block_arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, + llfn, + ast::DUMMY_NODE_ID, + false, + sig.output, + &empty_substs, + None, + &block_arena); let mut bcx = init_function(&fcx, false, sig.output); // the first argument (`self`) will be ptr to the the fn pointer diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index c1d98987991e..69d1922ab9ad 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -540,11 +540,12 @@ fn make_generic_glue<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx(), t)); let _s = StatRecorder::new(ccx, glue_name); - let arena = TypedArena::new(); let empty_param_substs = Substs::trans_empty(); - let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, - ty::FnConverging(ty::mk_nil(ccx.tcx())), - &empty_param_substs, None, &arena); + let (arena, fcx): (TypedArena<_>, FunctionContext); + arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, + ty::FnConverging(ty::mk_nil(ccx.tcx())), + &empty_param_substs, None, &arena); let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx()))); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 580a2d5ae3dc..187b73b1b095 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -601,17 +601,17 @@ pub fn trans_object_shim<'a, 'tcx>( let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig); - // - let block_arena = TypedArena::new(); let empty_substs = Substs::trans_empty(); - let fcx = new_fn_ctxt(ccx, - llfn, - ast::DUMMY_NODE_ID, - false, - sig.output, - &empty_substs, - None, - &block_arena); + let (block_arena, fcx): (TypedArena<_>, FunctionContext); + block_arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, + llfn, + ast::DUMMY_NODE_ID, + false, + sig.output, + &empty_substs, + None, + &block_arena); let mut bcx = init_function(&fcx, false, sig.output); // the first argument (`self`) will be a trait object diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 61332ada506d..4c5a8144cbd0 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1049,8 +1049,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // if there are any. assert_eq!(substs.types.len(subst::FnSpace), 0); assert_eq!(substs.regions().len(subst::FnSpace), 0); - let mut substs = substs; let placeholder; + let mut substs = substs; if !method.generics.types.is_empty_in(subst::FnSpace) || !method.generics.regions.is_empty_in(subst::FnSpace) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b172598ebb5..65560040f47c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -990,86 +990,65 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } -fn check_cast(fcx: &FnCtxt, - cast_expr: &ast::Expr, - e: &ast::Expr, - t: &ast::Ty) { - let id = cast_expr.id; - let span = cast_expr.span; - - // Find the type of `e`. Supply hints based on the type we are casting to, - // if appropriate. - let t_1 = fcx.to_ty(t); - let t_1 = structurally_resolved_type(fcx, span, t_1); - - check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1)); - - let t_e = fcx.expr_ty(e); - - debug!("t_1={}", fcx.infcx().ty_to_string(t_1)); - debug!("t_e={}", fcx.infcx().ty_to_string(t_e)); - - if ty::type_is_error(t_e) { - fcx.write_error(id); - return - } - - if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) { - let tstr = fcx.infcx().ty_to_string(t_1); - fcx.type_error_message(span, |actual| { - format!("cast to unsized type: `{}` as `{}`", actual, tstr) - }, t_e, None); - match t_e.sty { - ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => { - let mtstr = match mt { - ast::MutMutable => "mut ", - ast::MutImmutable => "" - }; - if ty::type_is_trait(t_1) { - span_help!(fcx.tcx().sess, t.span, "did you mean `&{}{}`?", mtstr, tstr); - } else { - span_help!(fcx.tcx().sess, span, - "consider using an implicit coercion to `&{}{}` instead", - mtstr, tstr); - } - } - ty::ty_uniq(..) => { - span_help!(fcx.tcx().sess, t.span, "did you mean `Box<{}>`?", tstr); - } - _ => { - span_help!(fcx.tcx().sess, e.span, - "consider using a box or reference as appropriate"); +fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + span: Span, + t_span: Span, + e_span: Span, + t_1: Ty<'tcx>, + t_e: Ty<'tcx>, + id: ast::NodeId) { + let tstr = fcx.infcx().ty_to_string(t_1); + fcx.type_error_message(span, |actual| { + format!("cast to unsized type: `{}` as `{}`", actual, tstr) + }, t_e, None); + match t_e.sty { + ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => { + let mtstr = match mt { + ast::MutMutable => "mut ", + ast::MutImmutable => "" + }; + if ty::type_is_trait(t_1) { + span_help!(fcx.tcx().sess, t_span, "did you mean `&{}{}`?", mtstr, tstr); + } else { + span_help!(fcx.tcx().sess, span, + "consider using an implicit coercion to `&{}{}` instead", + mtstr, tstr); } } - fcx.write_error(id); - return + ty::ty_uniq(..) => { + span_help!(fcx.tcx().sess, t_span, "did you mean `Box<{}>`?", tstr); + } + _ => { + span_help!(fcx.tcx().sess, e_span, + "consider using a box or reference as appropriate"); + } } + fcx.write_error(id); +} - if ty::type_is_trait(t_1) { - // This will be looked up later on. - vtable::check_object_cast(fcx, cast_expr, e, t_1); - fcx.write_ty(id, t_1); - return - } - let t_1 = structurally_resolved_type(fcx, span, t_1); - let t_e = structurally_resolved_type(fcx, span, t_e); - - if ty::type_is_nil(t_e) { +fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + span: Span, + t_1: Ty<'tcx>, + t_e: Ty<'tcx>, + e: &ast::Expr) { + fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + span: Span, + t_1: Ty<'tcx>, + t_e: Ty<'tcx>) { fcx.type_error_message(span, |actual| { - format!("cast from nil: `{}` as `{}`", - actual, - fcx.infcx().ty_to_string(t_1)) - }, t_e, None); - } else if ty::type_is_nil(t_1) { - fcx.type_error_message(span, |actual| { - format!("cast to nil: `{}` as `{}`", + format!("illegal cast; cast through an \ + integer first: `{}` as `{}`", actual, fcx.infcx().ty_to_string(t_1)) }, t_e, None); } let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e); + let t_e_is_scalar = ty::type_is_scalar(t_e); + let t_e_is_integral = ty::type_is_integral(t_e); + let t_e_is_float = ty::type_is_floating_point(t_e); + let t_e_is_c_enum = ty::type_is_c_like_enum(fcx.tcx(), t_e); let t_1_is_scalar = ty::type_is_scalar(t_1); let t_1_is_char = ty::type_is_char(t_1); @@ -1078,18 +1057,9 @@ fn check_cast(fcx: &FnCtxt, // casts to scalars other than `char` and `bare fn` are trivial let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn; + if t_e_is_bare_fn_item && t_1_is_bare_fn { demand::coerce(fcx, e.span, t_1, &*e); - } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial { - if t_1_is_float || ty::type_is_unsafe_ptr(t_1) { - fcx.type_error_message(span, |actual| { - format!("illegal cast; cast through an \ - integer first: `{}` as `{}`", - actual, - fcx.infcx().ty_to_string(t_1)) - }, t_e, None); - } - // casts from C-like enums are allowed } else if t_1_is_char { let t_e = fcx.infcx().shallow_resolve(t_e); if t_e.sty != ty::ty_uint(ast::TyU8) { @@ -1101,6 +1071,16 @@ fn check_cast(fcx: &FnCtxt, } else if t_1.sty == ty::ty_bool { span_err!(fcx.tcx().sess, span, E0054, "cannot cast as `bool`, compare with zero instead"); + } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !( + t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) { + // Casts to float must go through an integer or boolean + cast_through_integer_err(fcx, span, t_1, t_e) + } else if t_e_is_c_enum && t_1_is_trivial { + if ty::type_is_unsafe_ptr(t_1) { + // ... and likewise with C enum -> *T + cast_through_integer_err(fcx, span, t_1, t_e) + } + // casts from C-like enums are allowed } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) { fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool { @@ -1142,7 +1122,7 @@ fn check_cast(fcx: &FnCtxt, demand::coerce(fcx, e.span, t_1, &*e); } } - } else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) { + } else if !(t_e_is_scalar && t_1_is_trivial) { /* If more type combinations should be supported than are supported here, then file an enhancement issue and @@ -1153,15 +1133,49 @@ fn check_cast(fcx: &FnCtxt, actual, fcx.infcx().ty_to_string(t_1)) }, t_e, None); - } else if ty::type_is_unsafe_ptr(t_e) && t_1_is_float { - fcx.type_error_message(span, |actual| { - format!("cannot cast from pointer to float directly: `{}` as `{}`; cast through an \ - integer first", - actual, - fcx.infcx().ty_to_string(t_1)) - }, t_e, None); + } +} + +fn check_cast(fcx: &FnCtxt, + cast_expr: &ast::Expr, + e: &ast::Expr, + t: &ast::Ty) { + let id = cast_expr.id; + let span = cast_expr.span; + + // Find the type of `e`. Supply hints based on the type we are casting to, + // if appropriate. + let t_1 = fcx.to_ty(t); + let t_1 = structurally_resolved_type(fcx, span, t_1); + + check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1)); + + let t_e = fcx.expr_ty(e); + + debug!("t_1={}", fcx.infcx().ty_to_string(t_1)); + debug!("t_e={}", fcx.infcx().ty_to_string(t_e)); + + if ty::type_is_error(t_e) { + fcx.write_error(id); + return } + if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) { + report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id); + return + } + + if ty::type_is_trait(t_1) { + // This will be looked up later on. + vtable::check_object_cast(fcx, cast_expr, e, t_1); + fcx.write_ty(id, t_1); + return + } + + let t_1 = structurally_resolved_type(fcx, span, t_1); + let t_e = structurally_resolved_type(fcx, span, t_e); + + check_cast_inner(fcx, span, t_1, t_e, e); fcx.write_ty(id, t_1); } @@ -3087,8 +3101,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let name = ident.get(); // only find fits with at least one matching letter let mut best_dist = name.len(); - let mut best = None; let fields = ty::lookup_struct_fields(tcx, id); + let mut best = None; for elem in fields.iter() { let n = elem.name.as_str(); // ignore already set fields diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a4cafe88bcdb..fc3d6f5912ff 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -126,9 +126,9 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, .expect("phase_2_configure_and_expand aborted in rustdoc!"); let mut forest = ast_map::Forest::new(krate); + let arenas = ty::CtxtArenas::new(); let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest); - let arenas = ty::CtxtArenas::new(); let ty::CrateAnalysis { exported_items, public_items, ty_cx, .. } = driver::phase_3_run_analysis_passes(sess, diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 157d2580ad97..79ca24a18d4d 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{io, str}; +use std::{old_io, str}; #[derive(Clone)] pub struct ExternalHtml{ @@ -33,8 +33,8 @@ impl ExternalHtml { } } -pub fn load_string(input: &Path) -> io::IoResult> { - let mut f = try!(io::File::open(input)); +pub fn load_string(input: &Path) -> old_io::IoResult> { + let mut f = try!(old_io::File::open(input)); let d = try!(f.read_to_end()); Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string()).ok()) } @@ -45,12 +45,12 @@ macro_rules! load_or_return { let input = Path::new($input); match ::externalfiles::load_string(&input) { Err(e) => { - let _ = writeln!(&mut io::stderr(), + let _ = writeln!(&mut old_io::stderr(), "error reading `{}`: {}", input.display(), e); return $cant_read; } Ok(None) => { - let _ = writeln!(&mut io::stderr(), + let _ = writeln!(&mut old_io::stderr(), "error reading `{}`: not UTF-8", input.display()); return $not_utf8; } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 885017152de4..38b191846f19 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -15,7 +15,7 @@ use html::escape::Escape; -use std::io; +use std::old_io; use syntax::parse::lexer; use syntax::parse::token; use syntax::parse; @@ -46,7 +46,7 @@ pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { /// source. fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&str>, id: Option<&str>, - out: &mut Writer) -> io::IoResult<()> { + out: &mut Writer) -> old_io::IoResult<()> { use syntax::parse::lexer::Reader; try!(write!(out, "
 {
 }
 
 pub fn render(
-    dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
-    -> io::IoResult<()>
+    dst: &mut old_io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
+    -> old_io::IoResult<()>
 {
     write!(dst,
 r##"
@@ -159,7 +159,7 @@ r##"
     )
 }
 
-pub fn redirect(dst: &mut io::Writer, url: &str) -> io::IoResult<()> {
+pub fn redirect(dst: &mut old_io::Writer, url: &str) -> old_io::IoResult<()> {
     //