diff --git a/README.md b/README.md index b6a73730d351c..c88c237cbee89 100644 --- a/README.md +++ b/README.md @@ -15,28 +15,34 @@ Read ["Installing Rust"] from [The Book]. ## Building from Source 1. Make sure you have installed the dependencies: - * `g++` 4.7 or `clang++` 3.x - * `python` 2.6 or later (but not 3.x) - * GNU `make` 3.81 or later - * `curl` - * `git` + + * `g++` 4.7 or `clang++` 3.x + * `python` 2.6 or later (but not 3.x) + * GNU `make` 3.81 or later + * `curl` + * `git` 2. Clone the [source] with `git`: - $ git clone https://github.com/rust-lang/rust.git - $ cd rust + ```sh + $ git clone https://github.com/rust-lang/rust.git + $ cd rust + ``` [source]: https://github.com/rust-lang/rust 3. Build and install: - $ ./configure - $ make && make install + ```sh + $ ./configure + $ make && make install + ``` - > ***Note:*** You may need to use `sudo make install` if you do not normally have - > permission to modify the destination directory. The install locations can - > be adjusted by passing a `--prefix` argument to `configure`. Various other - > options are also supported, pass `--help` for more information on them. + > ***Note:*** You may need to use `sudo make install` if you do not + > normally have permission to modify the destination directory. The + > install locations can be adjusted by passing a `--prefix` argument + > to `configure`. Various other options are also supported – pass + > `--help` for more information on them. When complete, `make install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the @@ -47,27 +53,30 @@ Read ["Installing Rust"] from [The Book]. ### Building on Windows -To easily build on windows we can use [MSYS2](http://msys2.github.io/): +[MSYS2](http://msys2.github.io/) can be used to easily build Rust on Windows: 1. Grab the latest MSYS2 installer and go through the installer. -2. Now from the MSYS2 terminal we want to install the mingw64 toolchain and the other - tools we need. -```bash -# choose one based on platform -$ pacman -S mingw-w64-i686-toolchain -$ pacman -S mingw-w64-x86_64-toolchain +2. From the MSYS2 terminal, install the `mingw64` toolchain and other required + tools. + + ```sh + # Choose one based on platform: + $ pacman -S mingw-w64-i686-toolchain + $ pacman -S mingw-w64-x86_64-toolchain + + $ pacman -S base-devel + ``` -$ pacman -S base-devel -``` +3. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed + MYSY2 (i.e. `C:\msys`), depending on whether you want 32-bit or 64-bit Rust. -3. With that now start `mingw32_shell.bat` or `mingw64_shell.bat` - from where you installed MSYS2 (i.e. `C:\msys`). Which one you - choose depends on if you want 32 or 64 bit Rust. -4. From there just navigate to where you have Rust's source code, configure and build it: +4. Navigate to Rust's source code, configure and build it: - $ ./configure - $ make && make install + ```sh + $ ./configure + $ make && make install + ``` ## Notes @@ -92,15 +101,15 @@ There is more advice about hacking on Rust in [CONTRIBUTING.md]. [CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md -## Getting help +## Getting Help The Rust community congregates in a few places: -* [StackOverflow] - Direct questions about using the language here. -* [users.rust-lang.org] - General discussion, broader questions. +* [Stack Overflow] - Direct questions about using the language. +* [users.rust-lang.org] - General discussion and broader questions. * [/r/rust] - News and general discussion. -[StackOverflow]: http://stackoverflow.com/questions/tagged/rust +[Stack Overflow]: http://stackoverflow.com/questions/tagged/rust [/r/rust]: http://reddit.com/r/rust [users.rust-lang.org]: http://users.rust-lang.org/ @@ -111,7 +120,7 @@ To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md). Rust has an [IRC] culture and most real-time collaboration happens in a variety of channels on Mozilla's IRC network, irc.mozilla.org. The most popular channel is [#rust], a venue for general discussion about -Rust, and a good place to ask for help, +Rust, and a good place to ask for help. [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat [#rust]: irc://irc.mozilla.org/rust diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 278ce5565d9fc..417e050c8b8b3 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -268,7 +268,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { logfile: config.logfile.clone(), run_tests: true, run_benchmarks: true, - nocapture: false, + nocapture: env::var("RUST_TEST_NOCAPTURE").is_ok(), color: test::AutoColor, } } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 9c217651c3edc..e5570fe0b8fb0 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::env; + use common::Config; use common; use util; @@ -125,6 +127,16 @@ pub fn load_props(testfile: &Path) -> TestProps { true }); + for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_TASKS"] { + match env::var(key) { + Ok(val) => + if exec_env.iter().find(|&&(ref x, _)| *x == key.to_string()).is_none() { + exec_env.push((key.to_string(), val)) + }, + Err(..) => {} + } + } + TestProps { error_patterns: error_patterns, compile_flags: compile_flags, diff --git a/src/doc/intro.md b/src/doc/intro.md index d9bfe71e2e428..c9d834ee123bb 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -426,39 +426,33 @@ use std::thread::Thread; fn main() { let mut numbers = vec![1, 2, 3]; - for i in 0..3 { - Thread::spawn(move || { + let guards: Vec<_> = (0..3).map(|i| { + Thread::scoped(move || { for j in 0..3 { numbers[j] += 1 } }); - } + }).collect(); } ``` It gives us this error: ```text -6:71 error: capture of moved value: `numbers` - for j in 0..3 { numbers[j] += 1 } - ^~~~~~~ -7:50 note: `numbers` moved into closure environment here - spawn(move || { - for j in 0..3 { numbers[j] += 1 } - }); -6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing) - for j in 0..3 { numbers[j] += 1 } - ^~~~~~~~~~~~~~~ +7:29: 9:10 error: cannot move out of captured outer variable in an `FnMut` closure +7 Thread::scoped(move || { +8 for j in 0..3 { numbers[j] += 1 } +9 }); ``` -It mentions that "numbers moved into closure environment". Because we -declared the closure as a moving closure, and it referred to -`numbers`, the closure will try to take ownership of the vector. But -the closure itself is created in a loop, and hence we will actually -create three closures, one for every iteration of the loop. This means -that all three of those closures would try to own `numbers`, which is -impossible -- `numbers` must have just one owner. Rust detects this -and gives us the error: we claim that `numbers` has ownership, but our -code tries to make three owners. This may cause a safety problem, so -Rust disallows it. +It mentions that "captured outer variable in an `FnMut` closure". +Because we declared the closure as a moving closure, and it referred +to `numbers`, the closure will try to take ownership of the +vector. But the closure itself is created in a loop, and hence we will +actually create three closures, one for every iteration of the +loop. This means that all three of those closures would try to own +`numbers`, which is impossible -- `numbers` must have just one +owner. Rust detects this and gives us the error: we claim that +`numbers` has ownership, but our code tries to make three owners. This +may cause a safety problem, so Rust disallows it. What to do here? Rust has two types that helps us: `Arc` and `Mutex`. *Arc* stands for "atomically reference counted". In other words, an Arc will @@ -480,14 +474,14 @@ use std::sync::{Arc,Mutex}; fn main() { let numbers = Arc::new(Mutex::new(vec![1, 2, 3])); - for i in 0..3 { + let guards: Vec<_> = (0..3).map(|i| { let number = numbers.clone(); - Thread::spawn(move || { + Thread::scoped(move || { let mut array = number.lock().unwrap(); array[i] += 1; println!("numbers[{}] is {}", i, array[i]); }); - } + }).collect(); } ``` @@ -516,8 +510,10 @@ numbers[1] is 3 numbers[0] is 2 ``` -Each time, we get a slightly different output, because each thread works in a -different order. You may not get the same output as this sample, even. +Each time, we can get a slithtly different output because the threads +are not quaranteed to run in any set order. If you get the same order +every time it is because each of these threads are very small and +complete too fast for their indeterminate behavior to surface. The important part here is that the Rust compiler was able to use ownership to give us assurance _at compile time_ that we weren't doing something incorrect @@ -539,13 +535,13 @@ safety check that makes this an error about moved values: use std::thread::Thread; fn main() { - let vec = vec![1, 2, 3]; - - for i in 0..3 { - Thread::spawn(move || { - println!("{}", vec[i]); + let numbers = vec![1, 2, 3]; + + let guards: Vec<_> = (0..3).map(|i| { + Thread::scoped(move || { + println!("{}", numbers[i]); }); - } + }).collect(); } ``` diff --git a/src/doc/reference.md b/src/doc/reference.md index e6ff29799f4c6..357ff813fef3f 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -515,6 +515,9 @@ This last example is different because it is not possible to use the suffix syntax with a floating point literal ending in a period. `2.f64` would attempt to call a method named `f64` on `2`. +The representation semantics of floating-point numbers are described in +["Machine Types"](#machine-types). + #### Boolean literals The two values of the boolean type are written `true` and `false`. @@ -3554,7 +3557,8 @@ Tuple types and values are denoted by listing the types or values of their elements, respectively, in a parenthesized, comma-separated list. Because tuple elements don't have a name, they can only be accessed by -pattern-matching. +pattern-matching or by using `N` directly as a field to access the +`N`th element. An example of a tuple type and its use: @@ -3563,6 +3567,7 @@ type Pair<'a> = (i32, &'a str); let p: Pair<'static> = (10, "hello"); let (a, b) = p; assert!(b != "world"); +assert!(p.0 == 10); ``` ### Array, and Slice types diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 1f5d3eadae3b9..f3c0195855c34 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -12,7 +12,7 @@ Rust has two distinct terms that relate to the module system: *crate* and *module*. A crate is synonymous with a *library* or *package* in other languages. Hence "Cargo" as the name of Rust's package management tool: you ship your crates to others with Cargo. Crates can produce an executable or a -shared library, depending on the project. +library, depending on the project. Each crate has an implicit *root module* that contains the code for that crate. You can then define a tree of sub-modules under that root module. Modules allow diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 45c08af04f877..33dc1ba07ca86 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -57,14 +57,13 @@ for i in 0..nums.len() { } ``` -This is strictly worse than using an actual iterator. The `.iter()` method on -vectors returns an iterator which iterates through a reference to each element -of the vector in turn. So write this: +This is strictly worse than using an actual iterator. You can iterate over vectors +directly, so write this: ```rust let nums = vec![1, 2, 3]; -for num in nums.iter() { +for num in &nums { println!("{}", num); } ``` @@ -86,16 +85,17 @@ see it. This code works fine too: ```rust let nums = vec![1, 2, 3]; -for num in nums.iter() { +for num in &nums { println!("{}", *num); } ``` -Now we're explicitly dereferencing `num`. Why does `iter()` give us references? -Well, if it gave us the data itself, we would have to be its owner, which would -involve making a copy of the data and giving us the copy. With references, -we're just borrowing a reference to the data, and so it's just passing -a reference, without needing to do the copy. +Now we're explicitly dereferencing `num`. Why does `&nums` give us +references? Firstly, because we explicitly asked it to with +`&`. Secondly, if it gave us the data itself, we would have to be its +owner, which would involve making a copy of the data and giving us the +copy. With references, we're just borrowing a reference to the data, +and so it's just passing a reference, without needing to do the move. So, now that we've established that ranges are often not what you want, let's talk about what you do want instead. @@ -230,9 +230,9 @@ let nums = (1..100).collect::>(); Now, `collect()` will require that the range gives it some numbers, and so it will do the work of generating the sequence. -Ranges are one of two basic iterators that you'll see. The other is `iter()`, -which you've used before. `iter()` can turn a vector into a simple iterator -that gives you each element in turn: +Ranges are one of two basic iterators that you'll see. The other is `iter()`. +`iter()` can turn a vector into a simple iterator that gives you each element +in turn: ```rust let nums = [1, 2, 3]; diff --git a/src/doc/trpl/more-strings.md b/src/doc/trpl/more-strings.md index 20f1406aebbab..a2a558094e196 100644 --- a/src/doc/trpl/more-strings.md +++ b/src/doc/trpl/more-strings.md @@ -38,8 +38,9 @@ string literal or a `String`. # String -A `String` is a heap-allocated string. This string is growable, and is also -guaranteed to be UTF-8. +A `String` is a heap-allocated string. This string is growable, and is +also guaranteed to be UTF-8. `String`s are commonly created by +converting from a string slice using the `to_string` method. ``` let mut s = "Hello".to_string(); @@ -49,7 +50,7 @@ s.push_str(", world."); println!("{}", s); ``` -You can coerce a `String` into a `&str` by dereferencing it: +A reference to a `String` will automatically coerce to a string slice: ``` fn takes_slice(slice: &str) { @@ -58,7 +59,7 @@ fn takes_slice(slice: &str) { fn main() { let s = "Hello".to_string(); - takes_slice(&*s); + takes_slice(&s); } ``` diff --git a/src/doc/trpl/static-and-dynamic-dispatch.md b/src/doc/trpl/static-and-dynamic-dispatch.md index 98dac9bf84bb4..1baf41329f561 100644 --- a/src/doc/trpl/static-and-dynamic-dispatch.md +++ b/src/doc/trpl/static-and-dynamic-dispatch.md @@ -79,10 +79,11 @@ fn main() { } ``` -This has some upsides: static dispatching of any method calls, allowing for -inlining and hence usually higher performance. It also has some downsides: -causing code bloat due to many copies of the same function existing in the -binary, one for each type. +This has a great upside: static dispatch allows function calls to be +inlined because the callee is known at compile time, and inlining is +the key to good optimization. Static dispatch is fast, but it comes at +a tradeoff: 'code bloat', due to many copies of the same function +existing in the binary, one for each type. Furthermore, compilers aren’t perfect and may “optimize” code to become slower. For example, functions inlined too eagerly will bloat the instruction cache diff --git a/src/doc/trpl/strings.md b/src/doc/trpl/strings.md index 8ebebc98baf6b..2c2e6a8c7c5ac 100644 --- a/src/doc/trpl/strings.md +++ b/src/doc/trpl/strings.md @@ -25,8 +25,10 @@ compiled program, and exists for the entire duration it runs. The `string` binding is a reference to this statically allocated string. String slices have a fixed size, and cannot be mutated. -A `String`, on the other hand, is an in-memory string. This string is -growable, and is also guaranteed to be UTF-8. +A `String`, on the other hand, is a heap-allocated string. This string +is growable, and is also guaranteed to be UTF-8. `String`s are +commonly created by converting from a string slice using the +`to_string` method. ```{rust} let mut s = "Hello".to_string(); // mut s: String diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 4e14085599b60..4e7aa8357a7cd 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -649,53 +649,78 @@ it exists. The marker is the attribute `#[lang="..."]` and there are various different values of `...`, i.e. various different 'lang items'. -For example, `Box` pointers require two lang items, one for allocation -and one for deallocation. A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: +For example, there are three lang items related to task panicking: +one, `panic_bounds_check`, is called on panics due to out-of-bounds +array accesses; the second, `panic`, is used by explicit invocations +of `panic!`, and a third, `panic_fmt`, handles unwinding the stack in +the Rust standard library. + +A freestanding program that provides its own definition of the +`panic_bounds_check` lang item: ``` -#![feature(lang_items, box_syntax, start, no_std)] +#![feature(lang_items, intrinsics, start, no_std)] #![no_std] -extern crate libc; - -extern { - fn abort() -> !; -} +// To be able to print to standard output from this demonstration +// program, we link with `printf` from the C standard library. Note +// that this requires we null-terminate our strings with "\0". -#[lang = "owned_box"] -pub struct Box(*mut T); +mod printf { + #[link(name="c")] + extern { fn printf(f: *const u8, ...); } -#[lang="exchange_malloc"] -unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; + extern "rust-intrinsic" { + pub fn transmute(e: T) -> U; + } - // malloc failed - if p as usize == 0 { - abort(); + pub unsafe fn print0(s: &str) { + let (bytes, _len): (*const u8, usize) = transmute(s); + printf(bytes); } - p + pub unsafe fn print2(s: &str, arg1: u32, arg2: u32) { + let (bytes, _len): (*const u8, usize) = transmute(s); + printf(bytes, arg1, arg2); + } } -#[lang="exchange_free"] -unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { - libc::free(ptr as *mut libc::c_void) + +#[lang="panic_bounds_check"] +fn panic_bounds_check(_file_line: &(&'static str, usize), + index: usize, len: usize) { + // For simplicity of demonstration, just print message and exit. + extern { fn exit(status: u32) -> !; } + + let index = index as u32; + let len = len as u32; + unsafe { + printf::print2("panic_bounds_check index: %d len: %d\n\0", index, len); + + // (we pass 0 since this is expected behavior for the demonstration.) + exit(0); + } } #[start] -fn main(argc: isize, argv: *const *const u8) -> isize { - let x = box 1; - - 0 +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let a = [100, 200, 300]; + unsafe { printf::print0("doing a[4] for a.len() == 3\n\0"); } + a[4]; + unsafe { printf::print0("Should not get here.\n\0"); } + return 0; } +// Again, these functions and traits are used by the compiler, and are +// normally provided by libstd. (The `Sized` and `Copy` lang_items +// require definitions due to the type-parametric code above.) + #[lang = "stack_exhausted"] extern fn stack_exhausted() {} #[lang = "eh_personality"] extern fn eh_personality() {} #[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -``` -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. +#[lang="sized"] pub trait Sized {} +#[lang="copy"] pub trait Copy {} +``` Other features provided by lang items include: @@ -712,6 +737,6 @@ Other features provided by lang items include: `contravariant_lifetime`, etc. Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define functions for `exchange_malloc` -and `exchange_free`. `rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. +array indexing `a[i]` then there is no need to define a function for +`panic_bounds_check`. `rustc` will emit an error when an item is +needed but not found in the current crate or any that it depends on. diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 21218201182f9..f28f9976f0c5d 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -110,7 +110,7 @@ fn reverse_bits(byte: u8) -> u8 { result } -// Take two BitV's, and return iterators of their words, where the shorter one +// Take two BitVec's, and return iterators of their words, where the shorter one // has been padded with 0's fn match_words <'a,'b>(a: &'a BitVec, b: &'b BitVec) -> (MatchWords<'a>, MatchWords<'b>) { let a_len = a.storage.len(); diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 92dc01dc3e4e4..f3b2e9738979c 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -10,44 +10,39 @@ // // ignore-lexer-test FIXME #15679 -//! Unicode string manipulation (`str` type) +//! Unicode string manipulation (the `str` type). //! -//! # Basic Usage +//! Rust's `str` type is one of the core primitive types of the language. `&str` is the borrowed +//! string type. This type of string can only be created from other strings, unless it is a static +//! string (see below). As the word "borrowed" implies, this type of string is owned elsewhere, and +//! this string cannot be moved out of. //! -//! Rust's string type is one of the core primitive types of the language. While -//! represented by the name `str`, the name `str` is not actually a valid type in -//! Rust. Each string must also be decorated with a pointer. `String` is used -//! for an owned string, so there is only one commonly-used `str` type in Rust: -//! `&str`. +//! # Examples //! -//! `&str` is the borrowed string type. This type of string can only be created -//! from other strings, unless it is a static string (see below). As the word -//! "borrowed" implies, this type of string is owned elsewhere, and this string -//! cannot be moved out of. +//! Here's some code that uses a `&str`: //! -//! As an example, here's some code that uses a string. -//! -//! ```rust -//! fn main() { -//! let borrowed_string = "This string is borrowed with the 'static lifetime"; -//! } //! ``` +//! let s = "Hello, world."; +//! ``` +//! +//! This `&str` is a `&'static str`, which is the type of string literals. They're `'static` +//! because literals are available for the entire lifetime of the program. //! -//! From the example above, you can guess that Rust's string literals have the -//! `'static` lifetime. This is akin to C's concept of a static string. -//! More precisely, string literals are immutable views with a 'static lifetime -//! (otherwise known as the lifetime of the entire program), and thus have the -//! type `&'static str`. +//! You can get a non-`'static` `&str` by taking a slice of a `String`: +//! +//! ``` +//! # let some_string = "Hello, world.".to_string(); +//! let s = &some_string; +//! ``` //! //! # Representation //! -//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a -//! stream of UTF-8 bytes. All [strings](../../reference.html#literals) are -//! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are -//! not null-terminated and can thus contain null bytes. +//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a stream of UTF-8 +//! bytes. All [strings](../../reference.html#literals) are guaranteed to be validly encoded UTF-8 +//! sequences. Additionally, strings are not null-terminated and can thus contain null bytes. //! -//! The actual representation of strings have direct mappings to slices: `&str` -//! is the same as `&[u8]`. +//! The actual representation of `str`s have direct mappings to slices: `&str` is the same as +//! `&[u8]`. #![doc(primitive = "str")] #![stable(feature = "rust1", since = "1.0.0")] @@ -166,8 +161,9 @@ enum DecompositionType { Compatible } -/// External iterator for a string's decomposition's characters. -/// Use with the `std::iter` module. +/// External iterator for a string decomposition's characters. +/// +/// For use with the `std::iter` module. #[derive(Clone)] #[unstable(feature = "collections")] pub struct Decompositions<'a> { @@ -256,8 +252,9 @@ enum RecompositionState { Finished } -/// External iterator for a string's recomposition's characters. -/// Use with the `std::iter` module. +/// External iterator for a string recomposition's characters. +/// +/// For use with the `std::iter` module. #[derive(Clone)] #[unstable(feature = "collections")] pub struct Recompositions<'a> { @@ -354,7 +351,8 @@ impl<'a> Iterator for Recompositions<'a> { } /// External iterator for a string's UTF16 codeunits. -/// Use with the `std::iter` module. +/// +/// For use with the `std::iter` module. #[derive(Clone)] #[unstable(feature = "collections")] pub struct Utf16Units<'a> { @@ -430,23 +428,21 @@ pub trait StrExt: Index { /// Replaces all occurrences of one string with another. /// - /// # Arguments - /// - /// * `from` - The string to replace - /// * `to` - The replacement string - /// - /// # Return value - /// - /// The original string with all occurrences of `from` replaced with `to`. + /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a second `&str` to + /// replace it with. If the original `&str` isn't found, no change occurs. /// /// # Examples /// - /// ```rust + /// ``` /// let s = "this is old"; /// /// assert_eq!(s.replace("old", "new"), "this is new"); + /// ``` + /// + /// When a `&str` isn't found: /// - /// // not found, so no change. + /// ``` + /// let s = "this is old"; /// assert_eq!(s.replace("cookie monster", "little lamb"), s); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -520,32 +516,28 @@ pub trait StrExt: Index { } } - /// Returns true if a string contains a string pattern. - /// - /// # Arguments - /// - /// - pat - The string pattern to look for + /// Returns `true` if `self` contains another `&str`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert!("bananas".contains("nana")); + /// + /// assert!(!"bananas".contains("foobar")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { core_str::StrExt::contains(&self[..], pat) } - /// Returns true if a string contains a char pattern. + /// Returns `true` if `self` contains a `char`. /// - /// # Arguments - /// - /// - pat - The char pattern to look for - /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert!("hello".contains_char('e')); + /// + /// assert!(!"hello".contains_char('z')); /// ``` #[unstable(feature = "collections")] #[deprecated(since = "1.0.0", reason = "use `contains()` with a char")] @@ -553,13 +545,13 @@ pub trait StrExt: Index { core_str::StrExt::contains_char(&self[..], pat) } - /// An iterator over the characters of `self`. Note, this iterates - /// over Unicode code-points, not Unicode graphemes. + /// An iterator over the codepoints of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let v: Vec = "abc åäö".chars().collect(); + /// /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -567,12 +559,13 @@ pub trait StrExt: Index { core_str::StrExt::chars(&self[..]) } - /// An iterator over the bytes of `self` + /// An iterator over the bytes of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let v: Vec = "bors".bytes().collect(); + /// /// assert_eq!(v, b"bors".to_vec()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -581,47 +574,66 @@ pub trait StrExt: Index { } /// An iterator over the characters of `self` and their byte offsets. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<(usize, char)> = "abc".char_indices().collect(); + /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')]; + /// + /// assert_eq!(v, b); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn char_indices(&self) -> CharIndices { core_str::StrExt::char_indices(&self[..]) } /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`. + /// matched by a pattern. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. /// - /// ```rust + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, vec![""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); /// assert_eq!(v, vec!["abc", "def", "ghi"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); /// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "".split('X').collect(); - /// assert_eq!(v, vec![""]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { core_str::StrExt::split(&self[..], pat) } - /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`, restricted to splitting at most `count` - /// times. + /// An iterator over substrings of `self`, separated by characters matched by a pattern, + /// restricted to splitting at most `count` times. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. /// - /// ```rust + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]); /// - /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["abc", "def2ghi"]); - /// /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]); /// @@ -631,72 +643,89 @@ pub trait StrExt: Index { /// let v: Vec<&str> = "".splitn(1, 'X').collect(); /// assert_eq!(v, vec![""]); /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, vec!["abc", "def2ghi"]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { core_str::StrExt::splitn(&self[..], count, pat) } /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`. + /// matched by a pattern. /// - /// Equivalent to `split`, except that the trailing substring - /// is skipped if empty (terminator semantics). + /// Equivalent to `split`, except that the trailing substring is skipped if empty. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. /// - /// ```rust + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); /// assert_eq!(v, vec!["A", "B"]); /// /// let v: Vec<&str> = "A..B..".split_terminator('.').collect(); /// assert_eq!(v, vec!["A", "", "B", ""]); + /// ``` /// - /// let v: Vec<&str> = "Mary had a little lamb".split(' ').rev().collect(); - /// assert_eq!(v, vec!["lamb", "little", "a", "had", "Mary"]); - /// - /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).rev().collect(); - /// assert_eq!(v, vec!["ghi", "def", "abc"]); + /// More complex patterns with a lambda: /// - /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect(); - /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]); + /// ``` + /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, vec!["abc", "def", "ghi"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { core_str::StrExt::split_terminator(&self[..], pat) } - /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`, starting from the end of the string. + /// An iterator over substrings of `self`, separated by characters matched by a pattern, + /// starting from the end of the string. + /// /// Restricted to splitting at most `count` times. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// ```rust + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect(); /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]); /// - /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["ghi", "abc1def"]); - /// /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]); /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, vec!["ghi", "abc1def"]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> { core_str::StrExt::rsplitn(&self[..], count, pat) } - /// An iterator over the start and end indices of the disjoint - /// matches of the pattern `pat` within `self`. + /// An iterator over the start and end indices of the disjoint matches of a `&str` within + /// `self`. /// - /// That is, each returned value `(start, end)` satisfies - /// `self.slice(start, end) == sep`. For matches of `sep` within - /// `self` that overlap, only the indices corresponding to the - /// first match are returned. + /// That is, each returned value `(start, end)` satisfies `self.slice(start, end) == sep`. For + /// matches of `sep` within `self` that overlap, only the indices corresponding to the first + /// match are returned. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); /// assert_eq!(v, vec![(0,3), (6,9), (12,15)]); /// @@ -714,11 +743,11 @@ pub trait StrExt: Index { core_str::StrExt::match_indices(&self[..], pat) } - /// An iterator over the substrings of `self` separated by the pattern `sep`. + /// An iterator over the substrings of `self` separated by a `&str`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect(); /// assert_eq!(v, vec!["", "XXX", "YYY", ""]); /// @@ -731,15 +760,25 @@ pub trait StrExt: Index { core_str::StrExt::split_str(&self[..], pat) } - /// An iterator over the lines of a string (subsequences separated - /// by `\n`). This does not include the empty string after a - /// trailing `\n`. + /// An iterator over the lines of a string, separated by `\n`. /// - /// # Example + /// This does not include the empty string after a trailing `\n`. /// - /// ```rust + /// # Examples + /// + /// ``` + /// let four_lines = "foo\nbar\n\nbaz"; + /// let v: Vec<&str> = four_lines.lines().collect(); + /// + /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` /// let four_lines = "foo\nbar\n\nbaz\n"; /// let v: Vec<&str> = four_lines.lines().collect(); + /// /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -747,15 +786,25 @@ pub trait StrExt: Index { core_str::StrExt::lines(&self[..]) } - /// An iterator over the lines of a string, separated by either - /// `\n` or `\r\n`. As with `.lines()`, this does not include an - /// empty trailing line. + /// An iterator over the lines of a string, separated by either `\n` or `\r\n`. /// - /// # Example + /// As with `.lines()`, this does not include an empty trailing line. /// - /// ```rust + /// # Examples + /// + /// ``` + /// let four_lines = "foo\r\nbar\n\r\nbaz"; + /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// + /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` /// let four_lines = "foo\r\nbar\n\r\nbaz\n"; /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -781,26 +830,25 @@ pub trait StrExt: Index { #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")] fn slice_to(&self, end: usize) -> &str; - /// Returns a slice of the string from the character range - /// [`begin`..`end`). + /// Returns a slice of the string from the character range [`begin`..`end`). /// - /// That is, start at the `begin`-th code point of the string and - /// continue to the `end`-th code point. This does not detect or - /// handle edge cases such as leaving a combining character as the - /// first code point of the string. + /// That is, start at the `begin`-th code point of the string and continue to the `end`-th code + /// point. This does not detect or handle edge cases such as leaving a combining character as + /// the first code point of the string. /// - /// Due to the design of UTF-8, this operation is `O(end)`. - /// See `slice`, `slice_to` and `slice_from` for `O(1)` - /// variants that use byte indices rather than code point - /// indices. + /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`, `slice_to` and + /// `slice_from` for `O(1)` variants that use byte indices rather than code point indices. /// - /// Panics if `begin` > `end` or the either `begin` or `end` are - /// beyond the last character of the string. + /// # Panics /// - /// # Example + /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the last character of + /// the string. /// - /// ```rust + /// # Examples + /// + /// ``` /// let s = "Löwe 老虎 Léopard"; + /// /// assert_eq!(s.slice_chars(0, 4), "Löwe"); /// assert_eq!(s.slice_chars(5, 7), "老虎"); /// ``` @@ -810,22 +858,34 @@ pub trait StrExt: Index { core_str::StrExt::slice_chars(&self[..], begin, end) } - /// Takes a bytewise (not UTF-8) slice from a string. + /// Takes a bytewise slice from a string. /// /// Returns the substring from [`begin`..`end`). /// - /// Caller must check both UTF-8 character boundaries and the boundaries of - /// the entire slice as well. + /// # Unsafety + /// + /// Caller must check both UTF-8 character boundaries and the boundaries of the entire slice as + /// well. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard"); + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { core_str::StrExt::slice_unchecked(&self[..], begin, end) } - /// Returns true if the pattern `pat` is a prefix of the string. + /// Returns `true` if the given `&str` is a prefix of the string. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert!("banana".starts_with("ba")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -833,9 +893,9 @@ pub trait StrExt: Index { core_str::StrExt::starts_with(&self[..], pat) } - /// Returns true if the pattern `pat` is a suffix of the string. + /// Returns true if the given `&str` is a suffix of the string. /// - /// # Example + /// # Examples /// /// ```rust /// assert!("banana".ends_with("nana")); @@ -847,19 +907,24 @@ pub trait StrExt: Index { core_str::StrExt::ends_with(&self[..], pat) } - /// Returns a string with all pre- and suffixes that match - /// the pattern `pat` repeatedly removed. + /// Returns a string with all pre- and suffixes that match a pattern repeatedly removed. /// - /// # Arguments + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// * pat - a string pattern + /// # Examples /// - /// # Example + /// Simple `&str` patterns: /// - /// ```rust + /// ``` /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -869,19 +934,24 @@ pub trait StrExt: Index { core_str::StrExt::trim_matches(&self[..], pat) } - /// Returns a string with all prefixes that match - /// the pattern `pat` repeatedly removed. + /// Returns a string with all prefixes that match a pattern repeatedly removed. /// - /// # Arguments + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// * pat - a string pattern + /// # Examples /// - /// # Example + /// Simple `&str` patterns: /// - /// ```rust + /// ``` /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -889,19 +959,23 @@ pub trait StrExt: Index { core_str::StrExt::trim_left_matches(&self[..], pat) } - /// Returns a string with all suffixes that match - /// the pattern `pat` repeatedly removed. + /// Returns a string with all suffixes that match a pattern repeatedly removed. /// - /// # Arguments + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// * pat - a string pattern + /// # Examples /// - /// # Example + /// Simple `&str` patterns: /// - /// ```rust + /// ``` /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -911,17 +985,18 @@ pub trait StrExt: Index { core_str::StrExt::trim_right_matches(&self[..], pat) } - /// Check that `index`-th byte lies at the start and/or end of a - /// UTF-8 code point sequence. + /// Check that `index`-th byte lies at the start and/or end of a UTF-8 code point sequence. /// - /// The start and end of the string (when `index == self.len()`) - /// are considered to be boundaries. + /// The start and end of the string (when `index == self.len()`) are considered to be + /// boundaries. + /// + /// # Panics /// /// Panics if `index` is greater than `self.len()`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let s = "Löwe 老虎 Léopard"; /// assert!(s.is_char_boundary(0)); /// // start of `老` @@ -940,19 +1015,21 @@ pub trait StrExt: Index { core_str::StrExt::is_char_boundary(&self[..], index) } - /// Pluck a character out of a string and return the index of the next - /// character. + /// Given a byte position, return the next char and its index. /// - /// This function can be used to iterate over the Unicode characters of a - /// string. + /// This can be used to iterate over the Unicode characters of a string. /// - /// # Example + /// # Panics /// - /// This example manually iterates through the characters of a - /// string; this should normally be done by `.chars()` or - /// `.char_indices`. + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. /// - /// ```rust + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars()` or `.char_indices()`. + /// + /// ``` /// use std::str::CharRange; /// /// let s = "中华Việt Nam"; @@ -978,28 +1055,13 @@ pub trait StrExt: Index { /// 14: a /// 15: m /// ``` - /// - /// # Arguments - /// - /// * s - The string - /// * i - The byte offset of the char to extract - /// - /// # Return value - /// - /// A record {ch: char, next: usize} containing the char value and the byte - /// index of the next Unicode character. - /// - /// # Panics - /// - /// If `i` is greater than or equal to the length of the string. - /// If `i` is not the index of the beginning of a valid UTF-8 character. #[unstable(feature = "collections", reason = "naming is uncertain with container conventions")] fn char_range_at(&self, start: usize) -> CharRange { core_str::StrExt::char_range_at(&self[..], start) } - /// Given a byte position and a str, return the previous char and its position. + /// Given a byte position, return the previous `char` and its position. /// /// This function can be used to iterate over a Unicode string in reverse. /// @@ -1009,50 +1071,89 @@ pub trait StrExt: Index { /// /// If `i` is greater than the length of the string. /// If `i` is not an index following a valid UTF-8 character. + /// + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars().rev()` or `.char_indices()`. + /// + /// ``` + /// use std::str::CharRange; + /// + /// let s = "中华Việt Nam"; + /// let mut i = s.len(); + /// while i < 0 { + /// let CharRange {ch, next} = s.char_range_at_reverse(i); + /// println!("{}: {}", i, ch); + /// i = next; + /// } + /// ``` + /// + /// This outputs: + /// + /// ```text + /// 16: m + /// 15: a + /// 14: N + /// 13: + /// 12: t + /// 11: ệ + /// 8: i + /// 7: V + /// 6: 华 + /// 3: 中 + /// ``` #[unstable(feature = "collections", reason = "naming is uncertain with container conventions")] fn char_range_at_reverse(&self, start: usize) -> CharRange { core_str::StrExt::char_range_at_reverse(&self[..], start) } - /// Plucks the character starting at the `i`th byte of a string. + /// Given a byte position, return the `char` at that position. /// - /// # Example + /// # Panics /// - /// ```rust + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` /// let s = "abπc"; /// assert_eq!(s.char_at(1), 'b'); /// assert_eq!(s.char_at(2), 'π'); - /// assert_eq!(s.char_at(4), 'c'); /// ``` - /// - /// # Panics - /// - /// If `i` is greater than or equal to the length of the string. - /// If `i` is not the index of the beginning of a valid UTF-8 character. #[unstable(feature = "collections", reason = "naming is uncertain with container conventions")] fn char_at(&self, i: usize) -> char { core_str::StrExt::char_at(&self[..], i) } - /// Plucks the character ending at the `i`th byte of a string. + /// Given a byte position, return the `char` at that position, counting from the end. /// /// # Panics /// /// If `i` is greater than the length of the string. /// If `i` is not an index following a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` + /// let s = "abπc"; + /// assert_eq!(s.char_at_reverse(1), 'a'); + /// assert_eq!(s.char_at_reverse(2), 'b'); + /// ``` #[unstable(feature = "collections", reason = "naming is uncertain with container conventions")] fn char_at_reverse(&self, i: usize) -> char { core_str::StrExt::char_at_reverse(&self[..], i) } - /// Work with the byte buffer of a string as a byte slice. + /// Convert `self` to a byte slice. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert_eq!("bors".as_bytes(), b"bors"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1060,27 +1161,39 @@ pub trait StrExt: Index { core_str::StrExt::as_bytes(&self[..]) } - /// Returns the byte index of the first character of `self` that - /// matches the pattern `pat`. + /// Returns the byte index of the first character of `self` that matches the pattern, if it + /// exists. /// - /// # Return value + /// Returns `None` if it doesn't exist. /// - /// `Some` containing the byte index of the last matching character - /// or `None` if there is no match + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// # Example + /// # Examples /// - /// ```rust + /// Simple `&str` patterns: + /// + /// ``` /// let s = "Löwe 老虎 Léopard"; /// /// assert_eq!(s.find('L'), Some(0)); /// assert_eq!(s.find('é'), Some(14)); /// - /// // the first space + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); + /// ``` /// - /// // neither are found + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; /// let x: &[_] = &['1', '2']; + /// /// assert_eq!(s.find(x), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1088,27 +1201,38 @@ pub trait StrExt: Index { core_str::StrExt::find(&self[..], pat) } - /// Returns the byte index of the last character of `self` that - /// matches the pattern `pat`. + /// Returns the byte index of the last character of `self` that matches the pattern, if it + /// exists. /// - /// # Return value + /// Returns `None` if it doesn't exist. /// - /// `Some` containing the byte index of the last matching character - /// or `None` if there is no match. + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// # Example + /// # Examples /// - /// ```rust + /// Simple `&str` patterns: + /// + /// ``` /// let s = "Löwe 老虎 Léopard"; /// /// assert_eq!(s.rfind('L'), Some(13)); /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; /// - /// // the second space /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12)); + /// ``` + /// + /// Not finding the pattern: /// - /// // searches for an occurrence of either `1` or `2`, but neither are found + /// ``` + /// let s = "Löwe 老虎 Léopard"; /// let x: &[_] = &['1', '2']; + /// /// assert_eq!(s.rfind(x), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1118,20 +1242,15 @@ pub trait StrExt: Index { core_str::StrExt::rfind(&self[..], pat) } - /// Returns the byte index of the first matching substring + /// Returns the byte index of the first matching substring if it exists. /// - /// # Arguments + /// Returns `None` if it doesn't exist. /// - /// * `needle` - The string to search for + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// # Return value - /// - /// `Some` containing the byte index of the first matching substring - /// or `None` if there is no match. - /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let s = "Löwe 老虎 Léopard"; /// /// assert_eq!(s.find_str("老虎 L"), Some(6)); @@ -1143,21 +1262,24 @@ pub trait StrExt: Index { core_str::StrExt::find_str(&self[..], needle) } - /// Retrieves the first character from a string slice and returns - /// it. This does not allocate a new string; instead, it returns a - /// slice that point one character beyond the character that was - /// shifted. If the string does not contain any characters, - /// None is returned instead. + /// Retrieves the first character from a `&str` and returns it. /// - /// # Example + /// This does not allocate a new string; instead, it returns a slice that points one character + /// beyond the character that was shifted. /// - /// ```rust + /// If the slice does not contain any characters, None is returned instead. + /// + /// # Examples + /// + /// ``` /// let s = "Löwe 老虎 Léopard"; /// let (c, s1) = s.slice_shift_char().unwrap(); + /// /// assert_eq!(c, 'L'); /// assert_eq!(s1, "öwe 老虎 Léopard"); /// /// let (c, s2) = s1.slice_shift_char().unwrap(); + /// /// assert_eq!(c, 'ö'); /// assert_eq!(s2, "we 老虎 Léopard"); /// ``` @@ -1169,11 +1291,13 @@ pub trait StrExt: Index { /// Returns the byte offset of an inner slice relative to an enclosing outer slice. /// + /// # Panics + /// /// Panics if `inner` is not a direct slice contained within self. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let string = "a\nb\nc"; /// let lines: Vec<&str> = string.lines().collect(); /// @@ -1187,11 +1311,17 @@ pub trait StrExt: Index { core_str::StrExt::subslice_offset(&self[..], inner) } - /// Return an unsafe pointer to the strings buffer. + /// Return an unsafe pointer to the `&str`'s buffer. + /// + /// The caller must ensure that the string outlives this pointer, and that it is not + /// reallocated (e.g. by pushing to the string). /// - /// The caller must ensure that the string outlives this pointer, - /// and that it is not reallocated (e.g. by pushing to the - /// string). + /// # Examples + /// + /// ``` + /// let s = "Hello"; + /// let p = s.as_ptr(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] fn as_ptr(&self) -> *const u8 { @@ -1205,13 +1335,13 @@ pub trait StrExt: Index { Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) } } - /// Return the number of bytes in this string + /// Returns the length of `self` in bytes. /// - /// # Example + /// # Examples /// /// ``` /// assert_eq!("foo".len(), 3); - /// assert_eq!("ƒoo".len(), 4); + /// assert_eq!("ƒoo".len(), 4); // fancy f! /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1219,9 +1349,9 @@ pub trait StrExt: Index { core_str::StrExt::len(&self[..]) } - /// Returns true if this slice contains no bytes + /// Returns true if this slice has a length of zero bytes. /// - /// # Example + /// # Examples /// /// ``` /// assert!("".is_empty()); @@ -1232,12 +1362,21 @@ pub trait StrExt: Index { core_str::StrExt::is_empty(&self[..]) } - /// Parse this string into the specified type. + /// Parses `self` into the specified type. + /// + /// # Failure + /// + /// Will return `Err` if it's not possible to parse `self` into the type. /// /// # Example /// /// ``` /// assert_eq!("4".parse::(), Ok(4)); + /// ``` + /// + /// Failing: + /// + /// ``` /// assert!("j".parse::().is_err()); /// ``` #[inline] @@ -1246,23 +1385,26 @@ pub trait StrExt: Index { core_str::StrExt::parse(&self[..]) } - /// Returns an iterator over the - /// [grapheme clusters](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) - /// of the string. + /// Returns an iterator over the [grapheme clusters][graphemes] of `self`. + /// + /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries /// /// If `is_extended` is true, the iterator is over the *extended grapheme clusters*; /// otherwise, the iterator is over the *legacy grapheme clusters*. /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) /// recommends extended grapheme cluster boundaries for general processing. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::>(); /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]; + /// /// assert_eq!(gr1.as_slice(), b); + /// /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; + /// /// assert_eq!(gr2.as_slice(), b); /// ``` #[unstable(feature = "collections", @@ -1271,14 +1413,15 @@ pub trait StrExt: Index { UnicodeStr::graphemes(&self[..], is_extended) } - /// Returns an iterator over the grapheme clusters of self and their byte offsets. - /// See `graphemes()` method for more information. + /// Returns an iterator over the grapheme clusters of `self` and their byte offsets. See + /// `graphemes()` for more information. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::>(); /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + /// /// assert_eq!(gr_inds.as_slice(), b); /// ``` #[unstable(feature = "collections", @@ -1287,15 +1430,17 @@ pub trait StrExt: Index { UnicodeStr::grapheme_indices(&self[..], is_extended) } - /// An iterator over the words of a string (subsequences separated - /// by any sequence of whitespace). Sequences of whitespace are - /// collapsed, so empty "words" are not included. + /// An iterator over the non-empty words of `self`. /// - /// # Example + /// A 'word' is a subsequence separated by any sequence of whitespace. Sequences of whitespace + /// are collapsed, so empty "words" are not included. /// - /// ```rust + /// # Examples + /// + /// ``` /// let some_words = " Mary had\ta little \n\t lamb"; /// let v: Vec<&str> = some_words.words().collect(); + /// /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); /// ``` #[unstable(feature = "str_words", @@ -1304,34 +1449,55 @@ pub trait StrExt: Index { UnicodeStr::words(&self[..]) } - /// Returns a string's displayed width in columns, treating control - /// characters as zero-width. + /// Returns a string's displayed width in columns. + /// + /// Control characters have zero width. /// - /// `is_cjk` determines behavior for characters in the Ambiguous category: - /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1. - /// In CJK locales, `is_cjk` should be `true`, else it should be `false`. - /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) - /// recommends that these characters be treated as 1 column (i.e., - /// `is_cjk` = `false`) if the locale is unknown. + /// `is_cjk` determines behavior for characters in the Ambiguous category: if `is_cjk` is + /// `true`, these are 2 columns wide; otherwise, they are 1. In CJK locales, `is_cjk` should be + /// `true`, else it should be `false`. [Unicode Standard Annex + /// #11](http://www.unicode.org/reports/tr11/) recommends that these characters be treated as 1 + /// column (i.e., `is_cjk` = `false`) if the locale is unknown. #[unstable(feature = "collections", reason = "this functionality may only be provided by libunicode")] fn width(&self, is_cjk: bool) -> usize { UnicodeStr::width(&self[..], is_cjk) } - /// Returns a string with leading and trailing whitespace removed. + /// Returns a `&str` with leading and trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim(), "Hello\tworld"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn trim(&self) -> &str { UnicodeStr::trim(&self[..]) } - /// Returns a string with leading whitespace removed. + /// Returns a `&str` with leading whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_left(), "Hello\tworld\t"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn trim_left(&self) -> &str { UnicodeStr::trim_left(&self[..]) } - /// Returns a string with trailing whitespace removed. + /// Returns a `&str` with trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_right(), " Hello\tworld"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn trim_right(&self) -> &str { UnicodeStr::trim_right(&self[..]) diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index b0b9a80589d0d..7d789bedc50b5 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -465,7 +465,8 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, * Replace all regions bound by `binder` with skolemized regions and * return a map indicating which bound-region was replaced with what * skolemized region. This is the first step of checking subtyping - * when higher-ranked things are involved. See `doc.rs` for more details. + * when higher-ranked things are involved. See `README.md` for more + * details. */ let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br| { @@ -490,7 +491,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, * and checks to determine whether any of the skolemized regions created * in `skol_map` would "escape" -- meaning that they are related to * other regions in some way. If so, the higher-ranked subtyping doesn't - * hold. See `doc.rs` for more details. + * hold. See `README.md` for more details. */ debug!("leak_check: skol_map={}", @@ -533,7 +534,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, /// passed; currently, it's used in the trait matching code to create /// a set of nested obligations frmo an impl that matches against /// something higher-ranked. More details can be found in -/// `middle::traits::doc.rs`. +/// `librustc/middle/traits/README.md`. /// /// As a brief example, consider the obligation `for<'a> Fn(&'a int) /// -> &'a int`, and the impl: diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 5959b4a7c507a..7800d99f8ed4c 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See doc.rs +//! See README.md pub use self::Constraint::*; pub use self::Verify::*; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index e539f6ae6cb93..7db1138ac72f6 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -852,7 +852,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { // The idea is that call.callee_id represents *the time when // the invoked function is actually running* and call.id // represents *the time to prepare the arguments and make the - // call*. See the section "Borrows in Calls" borrowck/doc.rs + // call*. See the section "Borrows in Calls" borrowck/README.md // for an extended explanation of why this distinction is // important. // diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 6d3b910e720a7..9ef4a436b8d02 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See `doc.rs` for high-level documentation +//! See `README.md` for high-level documentation use super::Normalized; use super::SelectionContext; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 085758b44b5c7..2ce8eeb8f5a95 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See `doc.rs` for high-level documentation +//! See `README.md` for high-level documentation #![allow(dead_code)] // FIXME -- just temporarily pub use self::MethodMatchResult::*; @@ -547,7 +547,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // The selection process begins by examining all in-scope impls, // caller obligations, and so forth and assembling a list of - // candidates. See `doc.rs` and the `Candidate` type for more details. + // candidates. See `README.md` and the `Candidate` type for more + // details. fn candidate_from_obligation<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) @@ -1619,7 +1620,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // Confirmation unifies the output type parameters of the trait // with the values found in the obligation, possibly yielding a - // type error. See `doc.rs` for more details. + // type error. See `README.md` for more details. fn confirm_candidate(&mut self, obligation: &TraitObligation<'tcx>, diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index a3cc23b7bba83..ca740f5378219 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -212,7 +212,7 @@ pub fn memoized(cache: &RefCell>, arg: T, f: F) -> F: FnOnce(T) -> U, { let key = arg.clone(); - let result = cache.borrow().get(&key).map(|result| result.clone()); + let result = cache.borrow().get(&key).cloned(); match result { Some(result) => result, None => { diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index c5a3042892271..08f0897e7617e 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -53,8 +53,8 @@ Here `x` represents some variable, `LV.f` is a field reference, and `*LV` is a pointer dereference. There is no auto-deref or other niceties. This means that if you have a type like: -```text -struct S { f: uint } +```rust +struct S { f: i32 } ``` and a variable `a: Box`, then the rust expression `a.f` would correspond @@ -63,8 +63,8 @@ to an `LV` of `(*a).f`. Here is the formal grammar for the types we'll consider: ```text -TY = () | S<'LT...> | Box | & 'LT MQ TY -MQ = mut | imm | const +TY = i32 | bool | S<'LT...> | Box | & 'LT MQ TY +MQ = mut | imm ``` Most of these types should be pretty self explanatory. Here `S` is a @@ -82,13 +82,13 @@ SD = struct S<'LT...> { (f: TY)... } Now, imagine we had a program like this: -```text -struct Foo { f: uint, g: uint } +```rust +struct Foo { f: i32, g: i32 } ... 'a: { - let mut x: Box = ...; - let y = &mut (*x).f; - x = ...; + let mut x: Box = ...; + let y = &mut (*x).f; + x = ...; } ``` @@ -198,7 +198,7 @@ The kinds of expressions which in-scope loans can render illegal are: Now that we hopefully have some kind of intuitive feeling for how the borrow checker works, let's look a bit more closely now at the precise -conditions that it uses. For simplicity I will ignore const loans. +conditions that it uses. I will present the rules in a modified form of standard inference rules, which looks as follows: @@ -261,12 +261,11 @@ that will go into the final loan. We'll discuss in more detail below. ## Checking mutability Checking mutability is fairly straightforward. We just want to prevent -immutable data from being borrowed as mutable. Note that it is ok to -borrow mutable data as immutable, since that is simply a -freeze. Formally we define a predicate `MUTABLE(LV, MQ)` which, if -defined, means that "borrowing `LV` with mutability `MQ` is ok. The -Rust code corresponding to this predicate is the function -`check_mutability` in `middle::borrowck::gather_loans`. +immutable data from being borrowed as mutable. Note that it is ok to borrow +mutable data as immutable, since that is simply a freeze. The judgement +`MUTABILITY(LV, MQ)` means the mutability of `LV` is compatible with a borrow +of mutability `MQ`. The Rust code corresponding to this predicate is the +function `check_mutability` in `middle::borrowck::gather_loans`. ### Checking mutability of variables @@ -275,15 +274,14 @@ but also the code in `mem_categorization`. Let's begin with the rules for variables, which state that if a variable is declared as mutable, it may be borrowed any which way, but -otherwise the variable must be borrowed as immutable or const: +otherwise the variable must be borrowed as immutable: ```text MUTABILITY(X, MQ) // M-Var-Mut DECL(X) = mut -MUTABILITY(X, MQ) // M-Var-Imm +MUTABILITY(X, imm) // M-Var-Imm DECL(X) = imm - MQ = imm | const ``` ### Checking mutability of owned content @@ -304,12 +302,11 @@ MUTABILITY(*LV, MQ) // M-Deref-Unique ### Checking mutability of immutable pointer types Immutable pointer types like `&T` can only -be borrowed if MQ is immutable or const: +be borrowed if MQ is immutable: ```text -MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm +MUTABILITY(*LV, imm) // M-Deref-Borrowed-Imm TYPE(LV) = &Ty - MQ == imm | const ``` ### Checking mutability of mutable pointer types @@ -323,12 +320,11 @@ MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut ## Checking aliasability -The goal of the aliasability check is to ensure that we never permit -`&mut` borrows of aliasable data. Formally we define a predicate -`ALIASABLE(LV, MQ)` which if defined means that -"borrowing `LV` with mutability `MQ` is ok". The -Rust code corresponding to this predicate is the function -`check_aliasability()` in `middle::borrowck::gather_loans`. +The goal of the aliasability check is to ensure that we never permit `&mut` +borrows of aliasable data. The judgement `ALIASABLE(LV, MQ)` means the +aliasability of `LV` is compatible with a borrow of mutability `MQ`. The Rust +code corresponding to this predicate is the function `check_aliasability()` in +`middle::borrowck::gather_loans`. ### Checking aliasability of variables @@ -379,40 +375,6 @@ Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that `MQ`". The Rust code corresponding to this predicate is the module `middle::borrowck::gather_loans::lifetime`. -### The Scope function - -Several of the rules refer to a helper function `SCOPE(LV)=LT`. The -`SCOPE(LV)` yields the lifetime `LT` for which the lvalue `LV` is -guaranteed to exist, presuming that no mutations occur. - -The scope of a local variable is the block where it is declared: - -```text - SCOPE(X) = block where X is declared -``` - -The scope of a field is the scope of the struct: - -```text - SCOPE(LV.f) = SCOPE(LV) -``` - -The scope of a unique referent is the scope of the pointer, since -(barring mutation or moves) the pointer will not be freed until -the pointer itself `LV` goes out of scope: - -```text - SCOPE(*LV) = SCOPE(LV) if LV has type Box -``` - -The scope of a borrowed referent is the scope associated with the -pointer. This is a conservative approximation, since the data that -the pointer points at may actually live longer: - -```text - SCOPE(*LV) = LT if LV has type &'LT T or &'LT mut T -``` - ### Checking lifetime of variables The rule for variables states that a variable can only be borrowed a @@ -420,7 +382,7 @@ lifetime `LT` that is a subregion of the variable's scope: ```text LIFETIME(X, LT, MQ) // L-Local - LT <= SCOPE(X) + LT <= block where X is declared ``` ### Checking lifetime for owned content @@ -466,15 +428,12 @@ are computed based on the kind of borrow: ```text &mut LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE) &LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM) -&const LV => RESTRICTIONS(LV, LT, []) ``` The reasoning here is that a mutable borrow must be the only writer, therefore it prevents other writes (`MUTATE`), mutable borrows (`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow permits other immutable borrows but forbids writes and mutable borrows. -Finally, a const borrow just wants to be sure that the value is not -moved out from under it, so no actions are forbidden. ### Restrictions for loans of a local variable @@ -548,8 +507,8 @@ specify that the lifetime of the loan must be less than the lifetime of the `&Ty` pointer. In simple cases, this clause is redundant, since the `LIFETIME()` function will already enforce the required rule: -``` -fn foo(point: &'a Point) -> &'static f32 { +```rust +fn foo(point: &'a Point) -> &'static i32 { &point.x // Error } ``` @@ -558,8 +517,8 @@ The above example fails to compile both because of clause (1) above but also by the basic `LIFETIME()` check. However, in more advanced examples involving multiple nested pointers, clause (1) is needed: -``` -fn foo(point: &'a &'b mut Point) -> &'b f32 { +```rust +fn foo(point: &'a &'b mut Point) -> &'b i32 { &point.x // Error } ``` @@ -577,8 +536,8 @@ which is only `'a`, not `'b`. Hence this example yields an error. As a final twist, consider the case of two nested *immutable* pointers, rather than a mutable pointer within an immutable one: -``` -fn foo(point: &'a &'b Point) -> &'b f32 { +```rust +fn foo(point: &'a &'b Point) -> &'b i32 { &point.x // OK } ``` @@ -599,8 +558,8 @@ The rules pertaining to `LIFETIME` exist to ensure that we don't create a borrowed pointer that outlives the memory it points at. So `LIFETIME` prevents a function like this: -``` -fn get_1<'a>() -> &'a int { +```rust +fn get_1<'a>() -> &'a i32 { let x = 1; &x } @@ -619,8 +578,8 @@ after we return and hence the remaining code in `'a` cannot possibly mutate it. This distinction is important for type checking functions like this one: -``` -fn inc_and_get<'a>(p: &'a mut Point) -> &'a int { +```rust +fn inc_and_get<'a>(p: &'a mut Point) -> &'a i32 { p.x += 1; &p.x } @@ -641,19 +600,6 @@ in terms of capability, the caller passed in the ability to mutate `*p` is borrowed since that would be a move of `p`, as `&mut` pointers are affine.) -### Restrictions for loans of const aliasable referents - -Freeze pointers are read-only. There may be `&mut` or `&` aliases, and -we can not prevent *anything* but moves in that case. So the -`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. -Because moves from a `&const` lvalue are never legal, it is not -necessary to add any restrictions at all to the final result. - -```text - RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed - TYPE(LV) = &const Ty -``` - ### Restrictions for loans of mutable borrowed referents Mutable borrowed pointers are guaranteed to be the only way to mutate @@ -685,7 +631,7 @@ maximum of `LT'`. Here is a concrete example of a bug this rule prevents: -``` +```rust // Test region-reborrow-from-shorter-mut-ref.rs: fn copy_pointer<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T { &mut **p // ERROR due to clause (1) @@ -713,10 +659,10 @@ ways to violate the rules is to move the base pointer to a new name and access it via that new name, thus bypassing the restrictions on the old name. Here is an example: -``` +```rust // src/test/compile-fail/borrowck-move-mut-base-ptr.rs -fn foo(t0: &mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo(t0: &mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` let t1 = t0; //~ ERROR cannot move out of `t0` *t1 = 22; // OK, not a write through `*t0` } @@ -733,11 +679,11 @@ danger is to mutably borrow the base path. This can lead to two bad scenarios. The most obvious is that the mutable borrow itself becomes another path to access the same data, as shown here: -``` +```rust // src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` let mut t2 = &mut t0; //~ ERROR cannot borrow `t0` **t2 += 1; // Mutates `*t0` } @@ -754,11 +700,11 @@ of `t0`. Hence the claim `&mut t0` is illegal. Another danger with an `&mut` pointer is that we could swap the `t0` value away to create a new path: -``` +```rust // src/test/compile-fail/borrowck-swap-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` *t1 = 22; } @@ -772,37 +718,37 @@ careful to ensure this example is still illegal. referent is claimed, even freezing the base pointer can be dangerous, as shown in the following example: -``` +```rust // src/test/compile-fail/borrowck-borrow-of-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &mut int = &mut *t0; // Claims `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &mut i32 = &mut *t0; // Claims `*t0` let mut t2 = &t0; //~ ERROR cannot borrow `t0` - let q: &int = &*t2; // Freezes `*t0` but not through `*p` + let q: &i32 = &*t2; // Freezes `*t0` but not through `*p` *p += 1; // violates type of `*q` } ``` Here the problem is that `*t0` is claimed by `p`, and hence `p` wants to be the controlling pointer through which mutation or freezes occur. -But `t2` would -- if it were legal -- have the type `& &mut int`, and +But `t2` would -- if it were legal -- have the type `& &mut i32`, and hence would be a mutable pointer in an aliasable location, which is considered frozen (since no one can write to `**t2` as it is not a -unique path). Therefore, we could reasonably create a frozen `&int` +unique path). Therefore, we could reasonably create a frozen `&i32` pointer pointing at `*t0` that coexists with the mutable pointer `p`, which is clearly unsound. However, it is not always unsafe to freeze the base pointer. In particular, if the referent is frozen, there is no harm in it: -``` +```rust // src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` let mut t2 = &t0; - let q: &int = &*t2; // Freezes `*t0`, but that's ok... - let r: &int = &*t0; // ...after all, could do same thing directly. + let q: &i32 = &*t2; // Freezes `*t0`, but that's ok... + let r: &i32 = &*t0; // ...after all, could do same thing directly. } ``` @@ -811,11 +757,11 @@ thing `t2` can be used for is to further freeze `*t0`, which is already frozen. In particular, we cannot assign to `*t0` through the new alias `t2`, as demonstrated in this test case: -``` +```rust // src/test/run-pass/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs -fn foo(t0: & &mut int) { +fn foo(t0: & &mut i32) { let t1 = t0; - let p: &int = &**t0; + let p: &i32 = &**t0; **t1 = 22; //~ ERROR cannot assign } ``` @@ -855,6 +801,9 @@ prohibited from both freezes and claims. This would avoid the need to prevent `const` borrows of the base pointer when the referent is borrowed. +[ Previous revisions of this document discussed `&const` in more detail. +See the revision history. ] + # Moves and initialization The borrow checker is also in charge of ensuring that: @@ -881,9 +830,9 @@ moves/uninitializations of the variable that is being used. Let's look at a simple example: -``` -fn foo(a: Box) { - let b: Box; // Gen bit 0. +```rust +fn foo(a: Box) { + let b: Box; // Gen bit 0. if cond { // Bits: 0 use(&*a); @@ -897,7 +846,7 @@ fn foo(a: Box) { use(&*b); // Error. } -fn use(a: &int) { } +fn use(a: &i32) { } ``` In this example, the variable `b` is created uninitialized. In one @@ -1028,8 +977,8 @@ not) the destructor invocation for that path. A simple example of this is the following: ```rust -struct D { p: int } -impl D { fn new(x: int) -> D { ... } +struct D { p: i32 } +impl D { fn new(x: i32) -> D { ... } impl Drop for D { ... } fn foo(a: D, b: D, t: || -> bool) { @@ -1142,7 +1091,7 @@ the elements of an array that has been passed by value, such as the following: ```rust -fn foo(a: [D; 10], i: uint) -> D { +fn foo(a: [D; 10], i: i32) -> D { a[i] } ``` @@ -1158,7 +1107,7 @@ all-but-one element of the array. A place where that distinction would arise is the following: ```rust -fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D { +fn foo(a: [D; 10], b: [D; 10], i: i32, t: bool) -> D { if t { a[i] } else { @@ -1173,7 +1122,7 @@ fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D { There are a number of ways that the trans backend could choose to compile this (e.g. a `[bool; 10]` array for each such moved array; -or an `Option` for each moved array). From the viewpoint of the +or an `Option` for each moved array). From the viewpoint of the borrow-checker, the important thing is to record what kind of fragment is implied by the relevant moves. diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index 41ccee4f8fbf0..8cb4090bf3929 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -10,7 +10,7 @@ //! Helper routines used for fragmenting structural paths due to moves for //! tracking drop obligations. Please see the extensive comments in the -//! section "Structural fragments" in `doc.rs`. +//! section "Structural fragments" in `README.md`. use self::Fragment::*; diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 1c57097ae2633..9f7b4cf26e1c4 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -106,8 +106,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { //! lvalue `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. - // See the SCOPE(LV) function in doc.rs - match cmt.cat { mc::cat_rvalue(temp_scope) => { temp_scope diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 333aef81390bf..d51ad6e0c97b5 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -173,7 +173,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { } } -/// Implements the A-* rules in doc.rs. +/// Implements the A-* rules in README.md. fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, borrow_span: Span, loan_cause: euv::LoanCause, @@ -375,7 +375,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { cmt: mc::cmt<'tcx>, req_kind: ty::BorrowKind) -> Result<(),()> { - //! Implements the M-* rules in doc.rs. + //! Implements the M-* rules in README.md. match req_kind { ty::UniqueImmBorrow | ty::ImmBorrow => { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index dfd98881ace86..fd7880212f10b 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -295,7 +295,7 @@ impl<'tcx> PartialEq for LoanPath<'tcx> { #[derive(PartialEq, Eq, Hash, Debug)] pub enum LoanPathKind<'tcx> { - LpVar(ast::NodeId), // `x` in doc.rs + LpVar(ast::NodeId), // `x` in README.md LpUpvar(ty::UpvarId), // `x` captured by-value into closure LpDowncast(Rc>, ast::DefId), // `x` downcast to particular enum variant LpExtend(Rc>, mc::MutabilityCategory, LoanPathElem) @@ -336,8 +336,8 @@ impl ToInteriorKind for mc::InteriorKind { #[derive(Copy, PartialEq, Eq, Hash, Debug)] pub enum LoanPathElem { - LpDeref(mc::PointerKind), // `*LV` in doc.rs - LpInterior(InteriorKind), // `LV.f` in doc.rs + LpDeref(mc::PointerKind), // `*LV` in README.md + LpInterior(InteriorKind), // `LV.f` in README.md } pub fn closure_to_block(closure_id: ast::NodeId, diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 9c5ddc06519b9..0f7f8e61e37e0 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -9,7 +9,7 @@ // except according to those terms. //! Data structures used for tracking moves. Please see the extensive -//! comments in the section "Moves and initialization" in `doc.rs`. +//! comments in the section "Moves and initialization" in `README.md`. pub use self::MoveKind::*; @@ -33,7 +33,7 @@ use syntax::codemap::Span; pub mod fragments; pub struct MoveData<'tcx> { - /// Move paths. See section "Move paths" in `doc.rs`. + /// Move paths. See section "Move paths" in `README.md`. pub paths: RefCell>>, /// Cache of loan path to move path index, for easy lookup. @@ -464,7 +464,7 @@ impl<'tcx> MoveData<'tcx> { /// assignments into the provided data flow contexts. /// Moves are generated by moves and killed by assignments and /// scoping. Assignments are generated by assignment to variables and - /// killed by scoping. See `doc.rs` for more details. + /// killed by scoping. See `README.md` for more details. fn add_gen_kills(&self, tcx: &ty::ctxt<'tcx>, dfcx_moves: &mut MoveDataFlow, diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 28dcbe3ae86b2..59fca4b031886 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -663,23 +663,21 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { match typ.node { // Common case impl for a struct or something basic. ast::TyPath(ref path, id) => { - match self.lookup_type_ref(id) { - Some(id) => { - let sub_span = self.span.sub_span_for_type_name(path.span); - self.fmt.ref_str(recorder::TypeRef, - path.span, - sub_span, - id, - self.cur_scope); - self.fmt.impl_str(path.span, - sub_span, - item.id, - Some(id), - trait_id, - self.cur_scope); - }, - None => () - } + let sub_span = self.span.sub_span_for_type_name(path.span); + let self_id = self.lookup_type_ref(id).map(|id| { + self.fmt.ref_str(recorder::TypeRef, + path.span, + sub_span, + id, + self.cur_scope); + id + }); + self.fmt.impl_str(path.span, + sub_span, + item.id, + self_id, + trait_id, + self.cur_scope); }, _ => { // Less useful case, impl for a compound type. @@ -1002,28 +1000,39 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { ast::PatStruct(ref path, ref fields, _) => { self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef)); visit::walk_path(self, path); - let struct_def = match self.lookup_type_ref(p.id) { - Some(sd) => sd, - None => { - self.sess.span_bug(p.span, - &format!("Could not find struct_def for `{}`", - self.span.snippet(p.span))); + + let def = self.analysis.ty_cx.def_map.borrow()[p.id]; + let struct_def = match def { + def::DefConst(..) => None, + def::DefVariant(_, variant_id, _) => Some(variant_id), + _ => { + match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) { + None => { + self.sess.span_bug(p.span, + &format!("Could not find struct_def for `{}`", + self.span.snippet(p.span))); + } + Some(def_id) => Some(def_id), + } } }; - for &Spanned { node: ref field, span } in fields { - let sub_span = self.span.span_for_first_ident(span); - let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def); - for f in fields { - if f.name == field.ident.name { - self.fmt.ref_str(recorder::VarRef, - span, - sub_span, - f.id, - self.cur_scope); - break; + + if let Some(struct_def) = struct_def { + let struct_fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def); + for &Spanned { node: ref field, span } in fields { + let sub_span = self.span.span_for_first_ident(span); + for f in &struct_fields { + if f.name == field.ident.name { + self.fmt.ref_str(recorder::VarRef, + span, + sub_span, + f.id, + self.cur_scope); + break; + } } + self.visit_pat(&*field.pat); } - self.visit_pat(&*field.pat); } } ast::PatEnum(ref path, _) => { diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 96211832c1cc9..e0598583a1954 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -122,7 +122,7 @@ use syntax::codemap::DUMMY_SP; /// A `Datum` encapsulates the result of evaluating an expression. It /// describes where the value is stored, what Rust type the value has, /// whether it is addressed by reference, and so forth. Please refer -/// the section on datums in `doc.rs` for more details. +/// the section on datums in `README.md` for more details. #[derive(Clone, Copy)] pub struct Datum<'tcx, K> { /// The llvm value. This is either a pointer to the Rust value or diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index ed86925bd57da..256cd415a33af 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Method lookup: the secret sauce of Rust. See `doc.rs`. +//! Method lookup: the secret sauce of Rust. See `README.md`. use astconv::AstConv; use check::{FnCtxt}; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f5d2b8aed29df..df2fb538c0a50 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -203,7 +203,7 @@ fn test_resize_policy() { // produces identical results to a linear naive reinsertion from the same // element. // -// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs +// FIXME(Gankro, pczarn): review the proof and put it all in a separate README.md /// A hash map implementation which uses linear probing with Robin /// Hood bucket stealing. diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 0e64370df60ec..100d3e6ed4aa9 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -23,9 +23,9 @@ //! //! Rust's collections can be grouped into four major categories: //! -//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitV` +//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitVec` //! * Maps: `HashMap`, `BTreeMap`, `VecMap` -//! * Sets: `HashSet`, `BTreeSet`, `BitVSet` +//! * Sets: `HashSet`, `BTreeSet`, `BitSet` //! * Misc: `BinaryHeap` //! //! # When Should You Use Which Collection? @@ -73,11 +73,11 @@ //! * There is no meaningful value to associate with your keys. //! * You just want a set. //! -//! ### Use a `BitV` when: +//! ### Use a `BitVec` when: //! * You want to store an unbounded number of booleans in a small space. //! * You want a bit vector. //! -//! ### Use a `BitVSet` when: +//! ### Use a `BitSet` when: //! * You want a `VecSet`. //! //! ### Use a `BinaryHeap` when: diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 8976813d3f91e..8900713974bed 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -224,7 +224,7 @@ impl CString { /// Returns the contents of this `CString` as a slice of bytes. /// /// The returned slice does **not** contain the trailing nul separator and - /// it is guaranteet to not have any interior nul bytes. + /// it is guaranteed to not have any interior nul bytes. pub fn as_bytes(&self) -> &[u8] { &self.inner[..self.inner.len() - 1] } @@ -333,7 +333,7 @@ impl CStr { /// Return the inner pointer to this C string. /// /// The returned pointer will be valid for as long as `self` is and points - /// to a continguous region of memory terminated with a 0 byte to represent + /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. pub fn as_ptr(&self) -> *const libc::c_char { self.inner.as_ptr() diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 968adfafeab73..15ae8b027e128 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -1751,6 +1751,72 @@ mod tests { assert_pow!((8, 3 ) => 512); assert_pow!((2u64, 50) => 1125899906842624); } + + #[test] + fn test_uint_to_str_overflow() { + let mut u8_val: u8 = 255_u8; + assert_eq!(u8_val.to_string(), "255"); + + u8_val += 1 as u8; + assert_eq!(u8_val.to_string(), "0"); + + let mut u16_val: u16 = 65_535_u16; + assert_eq!(u16_val.to_string(), "65535"); + + u16_val += 1 as u16; + assert_eq!(u16_val.to_string(), "0"); + + let mut u32_val: u32 = 4_294_967_295_u32; + assert_eq!(u32_val.to_string(), "4294967295"); + + u32_val += 1 as u32; + assert_eq!(u32_val.to_string(), "0"); + + let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; + assert_eq!(u64_val.to_string(), "18446744073709551615"); + + u64_val += 1 as u64; + assert_eq!(u64_val.to_string(), "0"); + } + + fn from_str(t: &str) -> Option { + ::str::FromStr::from_str(t).ok() + } + + #[test] + fn test_uint_from_str_overflow() { + let mut u8_val: u8 = 255_u8; + assert_eq!(from_str::("255"), Some(u8_val)); + assert_eq!(from_str::("256"), None); + + u8_val += 1 as u8; + assert_eq!(from_str::("0"), Some(u8_val)); + assert_eq!(from_str::("-1"), None); + + let mut u16_val: u16 = 65_535_u16; + assert_eq!(from_str::("65535"), Some(u16_val)); + assert_eq!(from_str::("65536"), None); + + u16_val += 1 as u16; + assert_eq!(from_str::("0"), Some(u16_val)); + assert_eq!(from_str::("-1"), None); + + let mut u32_val: u32 = 4_294_967_295_u32; + assert_eq!(from_str::("4294967295"), Some(u32_val)); + assert_eq!(from_str::("4294967296"), None); + + u32_val += 1 as u32; + assert_eq!(from_str::("0"), Some(u32_val)); + assert_eq!(from_str::("-1"), None); + + let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; + assert_eq!(from_str::("18446744073709551615"), Some(u64_val)); + assert_eq!(from_str::("18446744073709551616"), None); + + u64_val += 1 as u64; + assert_eq!(from_str::("0"), Some(u64_val)); + assert_eq!(from_str::("-1"), None); + } } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 8d4f0344beb62..c9e6a8f66d1d2 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -48,68 +48,6 @@ mod tests { assert_eq!(FromStrRadix::from_str_radix("Z", 10).ok(), None::<$T>); assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$T>); } - - #[test] - fn test_uint_to_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert_eq!(u8_val.to_string(), "255"); - - u8_val += 1 as u8; - assert_eq!(u8_val.to_string(), "0"); - - let mut u16_val: u16 = 65_535_u16; - assert_eq!(u16_val.to_string(), "65535"); - - u16_val += 1 as u16; - assert_eq!(u16_val.to_string(), "0"); - - let mut u32_val: u32 = 4_294_967_295_u32; - assert_eq!(u32_val.to_string(), "4294967295"); - - u32_val += 1 as u32; - assert_eq!(u32_val.to_string(), "0"); - - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert_eq!(u64_val.to_string(), "18446744073709551615"); - - u64_val += 1 as u64; - assert_eq!(u64_val.to_string(), "0"); - } - - #[test] - fn test_uint_from_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert_eq!(from_str::("255"), Some(u8_val)); - assert_eq!(from_str::("256"), None); - - u8_val += 1 as u8; - assert_eq!(from_str::("0"), Some(u8_val)); - assert_eq!(from_str::("-1"), None); - - let mut u16_val: u16 = 65_535_u16; - assert_eq!(from_str::("65535"), Some(u16_val)); - assert_eq!(from_str::("65536"), None); - - u16_val += 1 as u16; - assert_eq!(from_str::("0"), Some(u16_val)); - assert_eq!(from_str::("-1"), None); - - let mut u32_val: u32 = 4_294_967_295_u32; - assert_eq!(from_str::("4294967295"), Some(u32_val)); - assert_eq!(from_str::("4294967296"), None); - - u32_val += 1 as u32; - assert_eq!(from_str::("0"), Some(u32_val)); - assert_eq!(from_str::("-1"), None); - - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert_eq!(from_str::("18446744073709551615"), Some(u64_val)); - assert_eq!(from_str::("18446744073709551616"), None); - - u64_val += 1 as u64; - assert_eq!(from_str::("0"), Some(u64_val)); - assert_eq!(from_str::("-1"), None); - } } ) } diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 224f1ef1a8b9b..74d2bfb40e19a 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -10,7 +10,6 @@ //! Implementation of the `build` subcommand, used to compile a book. -use std::os; use std::env; use std::old_io; use std::old_io::{fs, File, BufferedWriter, TempDir, IoResult}; @@ -82,7 +81,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> { let src; if env::args().len() < 3 { - src = os::getcwd().unwrap().clone(); + src = env::current_dir().unwrap().clone(); } else { src = Path::new(env::args().nth(2).unwrap().clone()); } @@ -150,7 +149,7 @@ impl Subcommand for Build { } fn usage(&self) {} fn execute(&mut self, term: &mut Term) -> CommandResult<()> { - let cwd = os::getcwd().unwrap(); + let cwd = env::current_dir().unwrap(); let src; let tgt; diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index ace57f0ac2c0b..9bcfc7f45d341 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -12,7 +12,6 @@ #![feature(collections)] #![feature(core)] #![feature(old_io)] -#![feature(os)] #![feature(env)] #![feature(old_path)] #![feature(rustdoc)] diff --git a/src/rustbook/test.rs b/src/rustbook/test.rs index c5d4875423ae1..d17a569903a51 100644 --- a/src/rustbook/test.rs +++ b/src/rustbook/test.rs @@ -17,7 +17,7 @@ use error::Error; use term::Term; use book; use std::old_io::{Command, File}; -use std::os; +use std::env; struct Test; @@ -35,7 +35,7 @@ impl Subcommand for Test { } fn usage(&self) {} fn execute(&mut self, term: &mut Term) -> CommandResult<()> { - let cwd = os::getcwd().unwrap(); + let cwd = env::current_dir().unwrap(); let src = cwd.clone(); let summary = File::open(&src.join("SUMMARY.md")); diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs index 9126058a4e6f4..d60751eddc7bc 100644 --- a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs +++ b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -11,7 +11,7 @@ // Test that attempt to reborrow an `&mut` pointer in an aliasable // location yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo(t0: & &mut isize) { let t1 = t0; diff --git a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs b/src/test/compile-fail/borrowck-move-mut-base-ptr.rs index 5bdea6a2bd996..2fb89e6364bb1 100644 --- a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs +++ b/src/test/compile-fail/borrowck-move-mut-base-ptr.rs @@ -11,7 +11,7 @@ // Test that attempt to move `&mut` pointer while pointee is borrowed // yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo(t0: &mut isize) { let p: &isize = &*t0; // Freezes `*t0` diff --git a/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs b/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs index 71dc61abb64e9..bdeb7ea69bdfb 100644 --- a/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs +++ b/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs @@ -11,7 +11,7 @@ // Test that attempt to mutably borrow `&mut` pointer while pointee is // borrowed yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo<'a>(mut t0: &'a mut isize, mut t1: &'a mut isize) { diff --git a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs b/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs index 0102a90918846..552fcec8e2858 100644 --- a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs +++ b/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs @@ -11,7 +11,7 @@ // Test that attempt to swap `&mut` pointer while pointee is borrowed // yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md use std::mem::swap; diff --git a/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs b/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs index b7aa2989ac582..48129f2b6ddc3 100644 --- a/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs +++ b/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs @@ -11,7 +11,7 @@ // Test that freezing an `&mut` pointer while referent is // frozen is legal. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo<'a>(mut t0: &'a mut int, mut t1: &'a mut int) {