From ef1308c407c34d91d176f1de6c0f86ecbea615f4 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 15 Feb 2015 15:30:09 +0100 Subject: [PATCH 01/28] Handle RUST_TEST_NOCAPTURE in compiletest and set add if to run env closes #17829 --- src/compiletest/compiletest.rs | 2 +- src/compiletest/header.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 385f1b9e79154..d43fe242c65a1 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -267,7 +267,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 c253967964322..fceac9716b115 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, From 2b7f7f21eddc39a1aa28e239d04009268e08dd85 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 17 Feb 2015 17:06:19 +0100 Subject: [PATCH 02/28] Replace `exchange_malloc`/`exchange_free` demo with something unrelated to Box. Precursor for landing overloaded-`box`, since that will decouple the `box` syntax from the exchange heap (and in fact will eliminate the use of the two aforementioned lang items). Instead, the new demonstration program shows a definition of the `panic_bounds_check` lang item. (We do not have that many procedural lang-items to choose from, which is a good sign for our efforts to decouple the compiler from the runtime!) --- src/doc/trpl/unsafe.md | 87 +++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 31 deletions(-) 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. From 55f625a96b84a2605b6f80ee3facf8061d0b00b0 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 18 Feb 2015 23:24:28 +0200 Subject: [PATCH 03/28] os.getcwd renamed to env::current_dir --- src/rustbook/build.rs | 4 ++-- src/rustbook/test.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 6f5fc5c1969f0..12eb156873e8b 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -82,7 +82,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 +150,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/test.rs b/src/rustbook/test.rs index d3cb8a7316e86..19c640ec7947e 100644 --- a/src/rustbook/test.rs +++ b/src/rustbook/test.rs @@ -18,6 +18,7 @@ use term::Term; use book; use std::old_io::{Command, File}; use std::os; +use std::env; struct Test; @@ -35,7 +36,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")); From 2f735f52c9034ed8a30b7255329fa342dfeb20a5 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 18 Feb 2015 23:25:58 +0200 Subject: [PATCH 04/28] unused imports --- src/rustbook/build.rs | 1 - src/rustbook/test.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 12eb156873e8b..f2ab68ddee0f0 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}; diff --git a/src/rustbook/test.rs b/src/rustbook/test.rs index 19c640ec7947e..18a746f10aad7 100644 --- a/src/rustbook/test.rs +++ b/src/rustbook/test.rs @@ -17,7 +17,6 @@ use error::Error; use term::Term; use book; use std::old_io::{Command, File}; -use std::os; use std::env; struct Test; From ac3a39015c7fb88fb0119fab568430edb8e4ddf4 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 18 Feb 2015 23:27:32 +0200 Subject: [PATCH 05/28] rustbook: no-longer-used feature gate --- src/rustbook/main.rs | 1 - 1 file changed, 1 deletion(-) 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)] From bb22c100db4b9f2c11aa0dbb78a5728087190dc6 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Feb 2015 17:59:47 -0800 Subject: [PATCH 06/28] borrowck/README.md: Remove most references to &const --- src/librustc_borrowck/borrowck/README.md | 33 +++++++----------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index c5a3042892271..d8e4466d62705 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -64,7 +64,7 @@ Here is the formal grammar for the types we'll consider: ```text TY = () | S<'LT...> | Box | & 'LT MQ TY -MQ = mut | imm | const +MQ = mut | imm ``` Most of these types should be pretty self explanatory. Here `S` is a @@ -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: @@ -275,15 +275,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 +303,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 @@ -466,15 +464,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 @@ -641,19 +636,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 @@ -855,6 +837,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: From 0c1fc1ca7b3b4c67e362e89e4cec33854d1e7de6 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Feb 2015 18:07:03 -0800 Subject: [PATCH 07/28] borrowck/README.md: Clarify MUTABILITY and ALIASABLE --- src/librustc_borrowck/borrowck/README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index d8e4466d62705..9eb1576e75771 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -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 @@ -321,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 From 160cf962e7efaca024202421e58a5c83f0d1cbe8 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Feb 2015 18:08:35 -0800 Subject: [PATCH 08/28] borrowck/README.md: Remove SCOPE (mostly unused) Only one case is used in the text. All of them are pretty straightforward, so I don't think the code needs an explicit link to the README. --- src/librustc_borrowck/borrowck/README.md | 36 +------------------ .../borrowck/gather_loans/lifetime.rs | 2 -- 2 files changed, 1 insertion(+), 37 deletions(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index 9eb1576e75771..619301f17dd37 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -375,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 @@ -416,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 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 From ac6cab088791c497726ccdec24f6f97e709d5a62 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Feb 2015 19:25:37 -0800 Subject: [PATCH 09/28] borrowck/README.md: Fix display of code on GitHub --- src/librustc_borrowck/borrowck/README.md | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index 619301f17dd37..42694a9c8d0a1 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -53,7 +53,7 @@ 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 +```rust struct S { f: uint } ``` @@ -82,13 +82,13 @@ SD = struct S<'LT...> { (f: TY)... } Now, imagine we had a program like this: -```text +```rust struct Foo { f: uint, g: uint } ... 'a: { - let mut x: Box = ...; - let y = &mut (*x).f; - x = ...; + let mut x: Box = ...; + let y = &mut (*x).f; + x = ...; } ``` @@ -507,7 +507,7 @@ 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: -``` +```rust fn foo(point: &'a Point) -> &'static f32 { &point.x // Error } @@ -517,7 +517,7 @@ 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: -``` +```rust fn foo(point: &'a &'b mut Point) -> &'b f32 { &point.x // Error } @@ -536,7 +536,7 @@ 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: -``` +```rust fn foo(point: &'a &'b Point) -> &'b f32 { &point.x // OK } @@ -558,7 +558,7 @@ 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: -``` +```rust fn get_1<'a>() -> &'a int { let x = 1; &x @@ -578,7 +578,7 @@ 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: -``` +```rust fn inc_and_get<'a>(p: &'a mut Point) -> &'a int { p.x += 1; &p.x @@ -631,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) @@ -659,7 +659,7 @@ 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` @@ -679,7 +679,7 @@ 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) { @@ -700,7 +700,7 @@ 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) { @@ -718,7 +718,7 @@ 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) { @@ -741,7 +741,7 @@ 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) { @@ -757,7 +757,7 @@ 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) { let t1 = t0; @@ -830,7 +830,7 @@ moves/uninitializations of the variable that is being used. Let's look at a simple example: -``` +```rust fn foo(a: Box) { let b: Box; // Gen bit 0. From f051e1323807b93fcb0d128a29dcdd0a0349bcf8 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Feb 2015 19:34:55 -0800 Subject: [PATCH 10/28] Fix references to doc.rs throughout the code --- src/librustc/middle/infer/higher_ranked/mod.rs | 7 ++++--- src/librustc/middle/infer/region_inference/mod.rs | 2 +- src/librustc/middle/region.rs | 2 +- src/librustc/middle/traits/coherence.rs | 2 +- src/librustc/middle/traits/select.rs | 7 ++++--- src/librustc_borrowck/borrowck/fragments.rs | 2 +- src/librustc_borrowck/borrowck/gather_loans/mod.rs | 4 ++-- src/librustc_borrowck/borrowck/mod.rs | 6 +++--- src/librustc_borrowck/borrowck/move_data.rs | 6 +++--- src/librustc_trans/trans/datum.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/libstd/collections/hash/map.rs | 2 +- .../borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs | 2 +- src/test/compile-fail/borrowck-move-mut-base-ptr.rs | 2 +- .../compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs | 2 +- src/test/compile-fail/borrowck-swap-mut-base-ptr.rs | 2 +- src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs | 2 +- 17 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index 4469e27a5b05a..ea59446c6d5be 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 5cdfdcc7c9b6c..0a4556e0fd22b 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 2f0462ab8c338..380f5d46799fa 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 3a7522cafee90..60db9c3867a44 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::SelectionContext; use super::{Obligation, ObligationCause}; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 061557eb7dccd..ffbd247ab83a6 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>) @@ -1656,7 +1657,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_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index bee1ada28e314..06ef0e02603e7 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/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 4e308c5809f45..577994c9a0bc7 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 93d97a054a4b3..4cfd43df58f96 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/trans/datum.rs b/src/librustc_trans/trans/datum.rs index f4a5ba98b6767..3975c4bbb8ee0 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 ffbc8ad020ab7..3c8604045a416 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 1b9f8b9901723..9f72199c1b320 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -204,7 +204,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/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) { From 1597f915c55f5a5db3b76d9859ba8618c83b8c98 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Feb 2015 20:46:21 -0800 Subject: [PATCH 11/28] borrowck/README.md: Normalize types in examples --- src/librustc_borrowck/borrowck/README.md | 74 ++++++++++++------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index 42694a9c8d0a1..08f0897e7617e 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -54,7 +54,7 @@ and `*LV` is a pointer dereference. There is no auto-deref or other niceties. This means that if you have a type like: ```rust -struct S { f: uint } +struct S { f: i32 } ``` and a variable `a: Box`, then the rust expression `a.f` would correspond @@ -63,7 +63,7 @@ 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 +TY = i32 | bool | S<'LT...> | Box | & 'LT MQ TY MQ = mut | imm ``` @@ -83,7 +83,7 @@ SD = struct S<'LT...> { (f: TY)... } Now, imagine we had a program like this: ```rust -struct Foo { f: uint, g: uint } +struct Foo { f: i32, g: i32 } ... 'a: { let mut x: Box = ...; @@ -508,7 +508,7 @@ of the `&Ty` pointer. In simple cases, this clause is redundant, since the `LIFETIME()` function will already enforce the required rule: ```rust -fn foo(point: &'a Point) -> &'static f32 { +fn foo(point: &'a Point) -> &'static i32 { &point.x // Error } ``` @@ -518,7 +518,7 @@ but also by the basic `LIFETIME()` check. However, in more advanced examples involving multiple nested pointers, clause (1) is needed: ```rust -fn foo(point: &'a &'b mut Point) -> &'b f32 { +fn foo(point: &'a &'b mut Point) -> &'b i32 { &point.x // Error } ``` @@ -537,7 +537,7 @@ As a final twist, consider the case of two nested *immutable* pointers, rather than a mutable pointer within an immutable one: ```rust -fn foo(point: &'a &'b Point) -> &'b f32 { +fn foo(point: &'a &'b Point) -> &'b i32 { &point.x // OK } ``` @@ -559,7 +559,7 @@ create a borrowed pointer that outlives the memory it points at. So `LIFETIME` prevents a function like this: ```rust -fn get_1<'a>() -> &'a int { +fn get_1<'a>() -> &'a i32 { let x = 1; &x } @@ -579,7 +579,7 @@ mutate it. This distinction is important for type checking functions like this one: ```rust -fn inc_and_get<'a>(p: &'a mut Point) -> &'a int { +fn inc_and_get<'a>(p: &'a mut Point) -> &'a i32 { p.x += 1; &p.x } @@ -661,8 +661,8 @@ 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` } @@ -681,9 +681,9 @@ 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` } @@ -702,9 +702,9 @@ 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; } @@ -720,21 +720,21 @@ 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. @@ -743,12 +743,12 @@ 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. } ``` @@ -759,9 +759,9 @@ 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 } ``` @@ -831,8 +831,8 @@ moves/uninitializations of the variable that is being used. Let's look at a simple example: ```rust -fn foo(a: Box) { - let b: Box; // Gen bit 0. +fn foo(a: Box) { + let b: Box; // Gen bit 0. if cond { // Bits: 0 use(&*a); @@ -846,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 @@ -977,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) { @@ -1091,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] } ``` @@ -1107,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 { @@ -1122,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. From 96be55376ecdc13b0e711fe9398c70cd932af166 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 19 Feb 2015 18:39:38 -0800 Subject: [PATCH 12/28] book: Minor clarifications about strings --- src/doc/trpl/crates-and-modules.md | 2 +- src/doc/trpl/more-strings.md | 9 +++++---- src/doc/trpl/strings.md | 6 ++++-- 3 files changed, 10 insertions(+), 7 deletions(-) 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/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/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 From fcc21b36a360ed7d5e9e19950bff6fcc5f40c833 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 20 Feb 2015 11:41:39 -0800 Subject: [PATCH 13/28] docs: Explain static dispatch advantage more clearly --- src/doc/trpl/static-and-dynamic-dispatch.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/trpl/static-and-dynamic-dispatch.md b/src/doc/trpl/static-and-dynamic-dispatch.md index 9421dac7bf65d..84d05c63e8f52 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 “optimise” code to become slower. For example, functions inlined too eagerly will bloat the instruction cache From eceab2963d731544e9a13d25a224b6a6364c5eee Mon Sep 17 00:00:00 2001 From: York Xiang Date: Sat, 21 Feb 2015 05:08:05 +0800 Subject: [PATCH 14/28] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6a73730d351c..ec56d3a1cd573 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,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 From b4dc9fd72bc0f5730a3fcdfd01d6fd3611093201 Mon Sep 17 00:00:00 2001 From: Florian Hartwig Date: Sat, 21 Feb 2015 20:36:44 +0100 Subject: [PATCH 15/28] Remove last traces of BitV and BitVSet from documentation --- src/libcollections/bit.rs | 2 +- src/libstd/collections/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 11c576eab1525..7ff34ef395531 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/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: From aa6604ac68429643ff1a3bb148dadc54d9ccc9af Mon Sep 17 00:00:00 2001 From: Tiago Nobrega Date: Sat, 21 Feb 2015 22:07:42 -0200 Subject: [PATCH 16/28] Fix small typo in reference to code of conduct Update from straight line to reference-style link. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4656dd415bbd..71b20cb0946c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ links to the major sections: If you have questions, please make a post on [internals.rust-lang.org][internals] or hop on [#rust-internals][pound-rust-internals]. -As a reminder, all contributors are expected to follow our [Code of Conduct](coc). +As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. [pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals [internals]: http://internals.rust-lang.org From c2a2b1050799609658ab9662bf93842bba6631ba Mon Sep 17 00:00:00 2001 From: GlacJAY Date: Sun, 22 Feb 2015 11:38:35 +0800 Subject: [PATCH 17/28] shift int/uint tests around to avoid code repetition --- src/libstd/num/mod.rs | 66 +++++++++++++++++++++++++++++++++++ src/libstd/num/uint_macros.rs | 62 -------------------------------- 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index c94c164983329..10768723c716f 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); - } } ) } From 928341e18890c0fec910a0dc92ef7f36e01a8d65 Mon Sep 17 00:00:00 2001 From: Alexander Chernyakhovsky Date: Sun, 22 Feb 2015 00:25:12 -0500 Subject: [PATCH 18/28] Include tuple indexing in the Reference. The Rust Reference should include the tuple indexing (using a number as a field) notation; currently it is only available on http://doc.rust-lang.org/std/primitive.tuple.html and not easily searchable. --- src/doc/reference.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index e6ff29799f4c6..07e5d50f481de 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3554,7 +3554,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 +3564,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 From 24fa6be7c66f9d2eaa18cb512e01a818201a6aae Mon Sep 17 00:00:00 2001 From: Kevin Yap Date: Sat, 21 Feb 2015 14:46:06 -0800 Subject: [PATCH 19/28] Miscellaneous README changes - Various grammatical changes. - Use triple-backtick syntax and sh highlighting for code blocks. - Fix indentation of code block in step 2 of "Building on Windows". - Use title case for "Getting Help" subheading. --- README.md | 75 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 33 deletions(-) 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 From c5a3cbb45ba162d24556fc1a091f8a2ac1ea6d76 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Sun, 22 Feb 2015 08:52:07 -0500 Subject: [PATCH 20/28] Fix typos in CStr docs --- src/libstd/ffi/c_str.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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() From a49914845780760ab19108a9aab0cb7e1fd61381 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 22 Feb 2015 17:13:41 +0100 Subject: [PATCH 21/28] Fix another occurrence of #22243 --- src/librustc/util/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 => { From d7c02c39e5cc759eb8aacb1f96ad23a7777b68fb Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Fri, 13 Feb 2015 09:28:10 -0500 Subject: [PATCH 22/28] Link from literals to their representation Fixes #22152 --- src/doc/reference.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/reference.md b/src/doc/reference.md index 9c51f6bad6fee..01e4f80eaf0f1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -518,6 +518,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`. From 27f357106e5a0cc9d2fa98c079f5f3f4ecf30f04 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Wed, 18 Feb 2015 18:56:35 -0500 Subject: [PATCH 23/28] Improve documentation for libcollections/str --- src/libcollections/str.rs | 714 +++++++++++++++++++++++--------------- 1 file changed, 440 insertions(+), 274 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 2d4dc2bcf30d3..0b393ab1b5e78 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")] @@ -164,8 +159,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> { @@ -254,8 +250,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> { @@ -352,7 +349,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> { @@ -427,23 +425,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")] @@ -517,32 +513,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(&self, pat: &str) -> 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", reason = "might get removed in favour of a more generic contains()")] @@ -550,13 +542,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")] @@ -564,12 +556,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")] @@ -578,47 +571,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(&self, pat: P) -> Split

{ 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"]); /// @@ -628,72 +640,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(&self, count: usize, pat: P) -> SplitN

{ 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"]); /// ``` #[unstable(feature = "collections", reason = "might get removed")] fn split_terminator(&self, pat: P) -> SplitTerminator

{ 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(&self, count: usize, pat: P) -> RSplitN

{ 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)]); /// @@ -709,11 +738,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", ""]); /// @@ -726,15 +755,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")] @@ -742,15 +781,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")] @@ -776,26 +825,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), "老虎"); /// ``` @@ -805,22 +853,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")] @@ -828,9 +888,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")); @@ -840,19 +900,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")] @@ -860,19 +925,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")] @@ -880,19 +950,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")] @@ -900,17 +974,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 `老` @@ -929,19 +1004,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"; @@ -967,28 +1044,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. /// @@ -998,50 +1060,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")] @@ -1049,27 +1150,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")] @@ -1077,27 +1190,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")] @@ -1105,20 +1229,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)); @@ -1130,21 +1249,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"); /// ``` @@ -1156,11 +1278,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(); /// @@ -1174,11 +1298,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 { @@ -1192,13 +1322,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] @@ -1206,9 +1336,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()); @@ -1219,12 +1349,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] @@ -1233,23 +1372,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", @@ -1258,14 +1400,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", @@ -1274,15 +1417,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", @@ -1291,34 +1436,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[]) From 6f9b91d429bb816cff98213c77fcf03ac0cfd4aa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 19 Feb 2015 16:10:35 +1300 Subject: [PATCH 24/28] save-analysis: handle type defs in struct patterns --- src/librustc_trans/save/mod.rs | 47 +++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 28dcbe3ae86b2..5fa37465cd656 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1002,28 +1002,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, _) => { From 6154c88ddcbe7ffacbf72a9acf508a377bbb96a7 Mon Sep 17 00:00:00 2001 From: Jessy Diamond Exum Date: Fri, 13 Feb 2015 12:13:28 -0800 Subject: [PATCH 25/28] Update intro.md to fix thread spawning example Closes #22419 Fixed example threaded code in intro doc never printing results. Threads were created with Thread::spawn instead of Thread::scoped. --- src/doc/intro.md | 64 +++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) 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(); } ``` From 04b0a3a0a6648474006c610b580f90b9097e3461 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Feb 2015 12:15:11 +1300 Subject: [PATCH 26/28] save-analysis: fix impls on primitive types --- src/librustc_trans/save/mod.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 28dcbe3ae86b2..a1d63ec0265fe 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. From 72eaf2c30e846b3d14c520c0c7638b2b16bf8c73 Mon Sep 17 00:00:00 2001 From: Alexander Bliskovsky Date: Fri, 20 Feb 2015 21:30:43 -0500 Subject: [PATCH 27/28] Switch to &vector notation in the iterators chapter. --- src/doc/trpl/iterators.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 45c08af04f877..943dbad35d774 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? Because we asked it to with `&`. If we had not had the +`&`, `nums` would have been moved into the `for` loop and consumed, +and we we would no longer be able to access `nums` afterward. 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]; @@ -242,6 +242,9 @@ for num in nums.iter() { } ``` +Sometimes you need this functionality, but since for loops operate on the +`IntoIterator` trait, calling `.iter()` is rarely necessary. + These two basic iterators should serve you well. There are some more advanced iterators, including ones that are infinite. Like `count`: From 9f2b0671f88b2cc6bb73575db47d265dbb246e34 Mon Sep 17 00:00:00 2001 From: Alexander Bliskovsky Date: Sun, 22 Feb 2015 20:06:25 -0500 Subject: [PATCH 28/28] Fixed erroneous statements in iterators.md. --- src/doc/trpl/iterators.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 943dbad35d774..33dc1ba07ca86 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -91,11 +91,11 @@ for num in &nums { ``` Now we're explicitly dereferencing `num`. Why does `&nums` give us -references? Because we asked it to with `&`. If we had not had the -`&`, `nums` would have been moved into the `for` loop and consumed, -and we we would no longer be able to access `nums` afterward. 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. +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. @@ -242,9 +242,6 @@ for num in nums.iter() { } ``` -Sometimes you need this functionality, but since for loops operate on the -`IntoIterator` trait, calling `.iter()` is rarely necessary. - These two basic iterators should serve you well. There are some more advanced iterators, including ones that are infinite. Like `count`: