From 14a7f4dedcdc25c2c1abf36addc52c8a48cdb7f9 Mon Sep 17 00:00:00 2001 From: Knight Date: Wed, 27 Jul 2016 03:01:48 +0800 Subject: [PATCH 01/23] Fix #35031 --- src/libcollections/fmt.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index c5312d0d9bb..be0ef85d6b1 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -434,37 +434,31 @@ //! in this case, if one uses the format string `{:.*}`, then the `` part refers //! to the *value* to print, and the `precision` must come in the input preceding ``. //! -//! For example, these: +//! For example, the following calls all print the same thing `Hello x is 0.01000`: //! //! ``` -//! // Hello {arg 0 (x)} is {arg 1 (0.01) with precision specified inline (5)} +//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)} //! println!("Hello {0} is {1:.5}", "x", 0.01); //! -//! // Hello {arg 1 (x)} is {arg 2 (0.01) with precision specified in arg 0 (5)} +//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)} //! println!("Hello {1} is {2:.0$}", 5, "x", 0.01); //! -//! // Hello {arg 0 (x)} is {arg 2 (0.01) with precision specified in arg 1 (5)} +//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} //! println!("Hello {0} is {2:.1$}", "x", 5, 0.01); //! -//! // Hello {next arg (x)} is {second of next two args (0.01) with precision +//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision //! // specified in first of next two args (5)} //! println!("Hello {} is {:.*}", "x", 5, 0.01); //! -//! // Hello {next arg (x)} is {arg 2 (0.01) with precision +//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision //! // specified in its predecessor (5)} //! println!("Hello {} is {2:.*}", "x", 5, 0.01); //! -//! // Hello {next arg (x)} is {arg "number" (0.01) with precision specified +//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified //! // in arg "prec" (5)} //! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); //! ``` //! -//! All print the same thing: -//! -//! ```text -//! Hello x is 0.01000 -//! ``` -//! //! While these: //! //! ``` From ec8518e4fbde1b578137883cc7c4fe6805723a3f Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Tue, 26 Jul 2016 18:53:47 -0700 Subject: [PATCH 02/23] Fix typos --- src/libpanic_unwind/dwarf/eh.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs index 1e9e9e30f5c..2284a9bbb73 100644 --- a/src/libpanic_unwind/dwarf/eh.rs +++ b/src/libpanic_unwind/dwarf/eh.rs @@ -108,7 +108,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction { } } } - // Ip is not present in the table. This should not hapen... but it does: issie #35011. + // Ip is not present in the table. This should not happen... but it does: issue #35011. // So rather than returning EHAction::Terminate, we do this. EHAction::None } else { From a72767970adbe3600d1b66eff118ba4dd732c804 Mon Sep 17 00:00:00 2001 From: "Panashe M. Fundira" Date: Wed, 27 Jul 2016 13:12:35 -0400 Subject: [PATCH 03/23] Update docs for assert! and debug_assert! --- src/libcore/macros.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 43868d124a2..e3207a0a86c 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -32,8 +32,19 @@ macro_rules! panic { /// Ensure that a boolean expression is `true` at runtime. /// -/// This will invoke the `panic!` macro if the provided expression cannot be -/// evaluated to `true` at runtime. +/// This will ensure the termination of the program if the provided expression +/// cannot be evaluated to `true` at runtime by means of an unrecoverable error +/// (not necessarily a `panic!`, can also be an `abort`). +/// +/// Assertions are always checked in both debug and release builds, and cannot +/// be disabled. +/// +/// Unsafe code relies on `assert!` to enforce run-time invariants that, if +/// violated could lead to unsafety. +/// +/// Other use-cases of `assert!` include +/// [testing](https://doc.rust-lang.org/book/testing.html) and enforcing +/// run-time invariants in safe code (whose violation cannot result in unsafety). /// /// This macro has a second version, where a custom panic message can be provided. /// @@ -123,6 +134,13 @@ macro_rules! assert_eq { /// expensive to be present in a release build but may be helpful during /// development. /// +/// An unchecked assertion allows a program in an inconsistent state to keep +/// running, which might have unexpected consequences but does not introduce +/// unsafety as long as this only happens in safe code. The performance cost +/// of assertions, is however, not measurable in general. Replacing `assert!` +/// with `debug_assert!` is thus only encourage after thorough profiling, and +/// more importantly, only in safe code! +/// /// # Examples /// /// ``` From 032ea41e99b39f6af2aa26c0ba049d0d215d8ebb Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 13:22:38 -0400 Subject: [PATCH 04/23] book/ffi: nullable pointer, libc cleanups Expand the "nullable pointer optimization" section with a code example. Change examples to use std::os::raw instead of libc, when applicable. --- src/doc/book/ffi.md | 67 +++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 3cbe5d60267..873d078f053 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -461,12 +461,11 @@ global state. In order to access these variables, you declare them in `extern` blocks with the `static` keyword: ```rust,no_run -# #![feature(libc)] -extern crate libc; +use std::os::raw::c_int; #[link(name = "readline")] extern { - static rl_readline_version: libc::c_int; + static rl_readline_version: c_int; } fn main() { @@ -480,15 +479,14 @@ interface. To do this, statics can be declared with `mut` so we can mutate them. ```rust,no_run -# #![feature(libc)] -extern crate libc; use std::ffi::CString; +use std::os::raw::c_char; use std::ptr; #[link(name = "readline")] extern { - static mut rl_prompt: *const libc::c_char; + static mut rl_prompt: *const c_char; } fn main() { @@ -513,14 +511,13 @@ calling foreign functions. Some foreign functions, most notably the Windows API, conventions. Rust provides a way to tell the compiler which convention to use: ```rust -# #![feature(libc)] -extern crate libc; +use std::os::raw::c_int; #[cfg(all(target_os = "win32", target_arch = "x86"))] #[link(name = "kernel32")] #[allow(non_snake_case)] extern "stdcall" { - fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int; + fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> c_int; } # fn main() { } ``` @@ -575,16 +572,45 @@ against `libc` and `libm` by default. # The "nullable pointer optimization" -Certain types are defined to not be NULL. This includes references (`&T`, -`&mut T`), boxes (`Box`), and function pointers (`extern "abi" fn()`). -When interfacing with C, pointers that might be NULL are often used. -As a special case, a generic `enum` that contains exactly two variants, one of +Certain Rust types are defined to never be `null`. This includes references (`&T`, +`&mut T`), boxes (`Box`), and function pointers (`extern "abi" fn()`). When +interfacing with C, pointers that might be `null` are often used, which would seem to +require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types. +However, the language provides a workaround. + +As a special case, an `enum` that contains exactly two variants, one of which contains no data and the other containing a single field, is eligible for the "nullable pointer optimization". When such an enum is instantiated -with one of the non-nullable types, it is represented as a single pointer, -and the non-data variant is represented as the NULL pointer. So -`Option c_int>` is how one represents a nullable -function pointer using the C ABI. +with one of the non-nullable types listed above, it is represented as a single pointer, +and the non-data variant is represented as the null pointer. This is called an +"optimization", but unlike other optimizations it is guaranteed to apply to +eligible types. + +The most common type that takes advantage of the nullable pointer optimization is `Option`, +where `None` corresponds to `null`. So `Option c_int>` is a correct way +to represent a nullable function pointer using the C ABI (corresponding to the C type +`int (*)(int)`). (However, generics are not required to get the optimization. A simple +`enum NullableIntRef { Int(Box), NotInt }` is also represented as a single pointer.) + +Here is an example: + +```rust +use std::os::raw::c_int; + +/// This fairly useless function receives a function pointer and an integer +/// from C, and returns the result of calling the function with the integer. +/// In case no function is provided, it squares the integer by default. +#[no_mangle] +pub extern fn apply(process: Option c_int>, int: c_int) -> c_int { + match process { + Some(f) => unsafe { f(int) }, + None => int * int + } +} +# fn main() {} +``` + +No `tranmsute` required! # Calling Rust code from C @@ -642,12 +668,11 @@ void bar(void *arg); We can represent this in Rust with the `c_void` type: ```rust -# #![feature(libc)] -extern crate libc; +use std::os::raw::c_void; extern "C" { - pub fn foo(arg: *mut libc::c_void); - pub fn bar(arg: *mut libc::c_void); + pub fn foo(arg: *mut c_void); + pub fn bar(arg: *mut c_void); } # fn main() {} ``` From 48ce20653a470f2d4734fb0ee4a89905da23b15c Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 15:05:22 -0400 Subject: [PATCH 05/23] generics-agnostic description --- src/doc/book/ffi.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 873d078f053..590c23e8929 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -578,19 +578,17 @@ interfacing with C, pointers that might be `null` are often used, which would se require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types. However, the language provides a workaround. -As a special case, an `enum` that contains exactly two variants, one of -which contains no data and the other containing a single field, is eligible -for the "nullable pointer optimization". When such an enum is instantiated -with one of the non-nullable types listed above, it is represented as a single pointer, -and the non-data variant is represented as the null pointer. This is called an -"optimization", but unlike other optimizations it is guaranteed to apply to +As a special case, an `enum` is eligible for the "nullable pointer optimization" if it +contains exactly two variants, one of which contains no data and the other contains +a single field of one of the non-nullable types listed above. This means it is represented +as a single pointer, and the non-data variant is represented as the null pointer. This is +called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible types. The most common type that takes advantage of the nullable pointer optimization is `Option`, where `None` corresponds to `null`. So `Option c_int>` is a correct way to represent a nullable function pointer using the C ABI (corresponding to the C type -`int (*)(int)`). (However, generics are not required to get the optimization. A simple -`enum NullableIntRef { Int(Box), NotInt }` is also represented as a single pointer.) +`int (*)(int)`). Here is an example: From cc2fc48dec9ae582ebba9761185afc5e21bf47b6 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 16:13:20 -0400 Subject: [PATCH 06/23] expand nullable pointer example --- src/doc/book/ffi.md | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 590c23e8929..fb8896da86d 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -590,22 +590,42 @@ where `None` corresponds to `null`. So `Option c_int>` i to represent a nullable function pointer using the C ABI (corresponding to the C type `int (*)(int)`). -Here is an example: +Here is a contrived example. Let's say some C library has a facility for registering a +callback, which gets called in certain situations. The callback is passed a function pointer +and an integer and it is supposed to run the function with the integer as a parameter. So +we have function pointers flying across the FFI interface in both directions. ```rust use std::os::raw::c_int; +extern "C" { + /// Register the callback. + fn register(Option c_int>, c_int) -> c_int>); +} + /// This fairly useless function receives a function pointer and an integer /// from C, and returns the result of calling the function with the integer. /// In case no function is provided, it squares the integer by default. -#[no_mangle] -pub extern fn apply(process: Option c_int>, int: c_int) -> c_int { +extern "C" fn apply(process: Option c_int>, int: c_int) -> c_int { match process { Some(f) => unsafe { f(int) }, None => int * int } } -# fn main() {} + +fn main() { + unsafe { + register(Some(apply)); + } +} +``` + +And the code on the C side looks like this: + +```c +void register(void (*f)(void (*)(int), int)) { + ... +} ``` No `tranmsute` required! From 84366b6f281614f61381962e2e46b73bb471c737 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 17:47:18 -0400 Subject: [PATCH 07/23] recursion --- src/doc/book/ffi.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index fb8896da86d..5a2ec86c12f 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -580,10 +580,10 @@ However, the language provides a workaround. As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains exactly two variants, one of which contains no data and the other contains -a single field of one of the non-nullable types listed above. This means it is represented -as a single pointer, and the non-data variant is represented as the null pointer. This is -called an "optimization", but unlike other optimizations it is guaranteed to apply to -eligible types. +a single field of one of the non-nullable types listed above (or a struct containing such a type). +This means it is represented as a single pointer, and the non-data variant is represented as a +null pointer. This is called an "optimization", but unlike other optimizations it is guaranteed +to apply to eligible types. The most common type that takes advantage of the nullable pointer optimization is `Option`, where `None` corresponds to `null`. So `Option c_int>` is a correct way From 0016af5f13702feb92f6323417fb9fe495e964d0 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 17:54:39 -0400 Subject: [PATCH 08/23] not just a single field --- src/doc/book/ffi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 5a2ec86c12f..07b8d8e0da8 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -580,7 +580,7 @@ However, the language provides a workaround. As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains exactly two variants, one of which contains no data and the other contains -a single field of one of the non-nullable types listed above (or a struct containing such a type). +a field of one of the non-nullable types listed above (or a struct containing such a type). This means it is represented as a single pointer, and the non-data variant is represented as a null pointer. This is called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible types. From 1cceca8dfdda4a8bf3daa6a8c23adf7f23acd81a Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 18:00:07 -0400 Subject: [PATCH 09/23] foreign function interface interface --- src/doc/book/ffi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 07b8d8e0da8..4a55db38d38 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -593,7 +593,7 @@ to represent a nullable function pointer using the C ABI (corresponding to the C Here is a contrived example. Let's say some C library has a facility for registering a callback, which gets called in certain situations. The callback is passed a function pointer and an integer and it is supposed to run the function with the integer as a parameter. So -we have function pointers flying across the FFI interface in both directions. +we have function pointers flying across the FFI boundary in both directions. ```rust use std::os::raw::c_int; From fae33352721c4b4d6fbdc66520043ae721121d77 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 21:10:12 -0400 Subject: [PATCH 10/23] extern fns require named parameters Not sure the example is going to stay, but I can try to pass Travis for the bragging rights. --- src/doc/book/ffi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 4a55db38d38..74c99273fa2 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -600,7 +600,7 @@ use std::os::raw::c_int; extern "C" { /// Register the callback. - fn register(Option c_int>, c_int) -> c_int>); + fn register(cb: Option c_int>, c_int) -> c_int>); } /// This fairly useless function receives a function pointer and an integer From 5276b2967060d749e20674a08a2438a24f0f7b07 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 13 Jun 2016 21:38:04 -0400 Subject: [PATCH 11/23] change confusing wording about discriminant --- src/doc/book/ffi.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 74c99273fa2..e63516e58cc 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -581,9 +581,9 @@ However, the language provides a workaround. As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains exactly two variants, one of which contains no data and the other contains a field of one of the non-nullable types listed above (or a struct containing such a type). -This means it is represented as a single pointer, and the non-data variant is represented as a -null pointer. This is called an "optimization", but unlike other optimizations it is guaranteed -to apply to eligible types. +This means no extra space is required for a discriminant; rather, the empty variant is represented +by putting a `null` value into the non-nullable field. This is called an "optimization", but unlike +other optimizations it is guaranteed to apply to eligible types. The most common type that takes advantage of the nullable pointer optimization is `Option`, where `None` corresponds to `null`. So `Option c_int>` is a correct way From 54ecc210ec720e93c6e493e6fc3e7464cd22002f Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 14 Jun 2016 15:53:55 -0400 Subject: [PATCH 12/23] hack to make example compile --- src/doc/book/ffi.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index e63516e58cc..e1b9789a314 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -598,17 +598,21 @@ we have function pointers flying across the FFI boundary in both directions. ```rust use std::os::raw::c_int; +# #[cfg(hidden)] extern "C" { /// Register the callback. fn register(cb: Option c_int>, c_int) -> c_int>); } +# unsafe fn register(_: Option c_int>, +# c_int) -> c_int>) +# {} /// This fairly useless function receives a function pointer and an integer /// from C, and returns the result of calling the function with the integer. /// In case no function is provided, it squares the integer by default. extern "C" fn apply(process: Option c_int>, int: c_int) -> c_int { match process { - Some(f) => unsafe { f(int) }, + Some(f) => f(int), None => int * int } } From 8e7abea93e84af6060ce6eeb530eb82fed3cff60 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 27 Jul 2016 13:51:48 -0400 Subject: [PATCH 13/23] revert libc changes --- src/doc/book/ffi.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index e1b9789a314..983bd46a0c9 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -461,11 +461,12 @@ global state. In order to access these variables, you declare them in `extern` blocks with the `static` keyword: ```rust,no_run -use std::os::raw::c_int; +# #![feature(libc)] +extern crate libc; #[link(name = "readline")] extern { - static rl_readline_version: c_int; + static rl_readline_version: libc::c_int; } fn main() { @@ -479,14 +480,15 @@ interface. To do this, statics can be declared with `mut` so we can mutate them. ```rust,no_run +# #![feature(libc)] +extern crate libc; use std::ffi::CString; -use std::os::raw::c_char; use std::ptr; #[link(name = "readline")] extern { - static mut rl_prompt: *const c_char; + static mut rl_prompt: *const libc::c_char; } fn main() { @@ -511,13 +513,14 @@ calling foreign functions. Some foreign functions, most notably the Windows API, conventions. Rust provides a way to tell the compiler which convention to use: ```rust -use std::os::raw::c_int; +# #![feature(libc)] +extern crate libc; #[cfg(all(target_os = "win32", target_arch = "x86"))] #[link(name = "kernel32")] #[allow(non_snake_case)] extern "stdcall" { - fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> c_int; + fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int; } # fn main() { } ``` @@ -690,11 +693,12 @@ void bar(void *arg); We can represent this in Rust with the `c_void` type: ```rust -use std::os::raw::c_void; +# #![feature(libc)] +extern crate libc; extern "C" { - pub fn foo(arg: *mut c_void); - pub fn bar(arg: *mut c_void); + pub fn foo(arg: *mut libc::c_void); + pub fn bar(arg: *mut libc::c_void); } # fn main() {} ``` From 1319b293c67f0fa8e9504c692898d2cee1866a9a Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 27 Jul 2016 13:52:13 -0400 Subject: [PATCH 14/23] fix typo --- src/doc/book/ffi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 983bd46a0c9..f9c50f0399a 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -635,7 +635,7 @@ void register(void (*f)(void (*)(int), int)) { } ``` -No `tranmsute` required! +No `transmute` required! # Calling Rust code from C From 29546dd06d733d065fc497902bbcecbbb06ce621 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 27 Jul 2016 13:57:14 -0400 Subject: [PATCH 15/23] remove claim about searching through nested fields for the nullable type, even though that is how it works --- src/doc/book/ffi.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index f9c50f0399a..ca104ff29ac 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -581,12 +581,12 @@ interfacing with C, pointers that might be `null` are often used, which would se require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types. However, the language provides a workaround. -As a special case, an `enum` is eligible for the "nullable pointer optimization" if it -contains exactly two variants, one of which contains no data and the other contains -a field of one of the non-nullable types listed above (or a struct containing such a type). -This means no extra space is required for a discriminant; rather, the empty variant is represented -by putting a `null` value into the non-nullable field. This is called an "optimization", but unlike -other optimizations it is guaranteed to apply to eligible types. +As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains +exactly two variants, one of which contains no data and the other contains a field of one of the +non-nullable types listed above. This means no extra space is required for a discriminant; rather, +the empty variant is represented by putting a `null` value into the non-nullable field. This is +called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible +types. The most common type that takes advantage of the nullable pointer optimization is `Option`, where `None` corresponds to `null`. So `Option c_int>` is a correct way @@ -599,7 +599,9 @@ and an integer and it is supposed to run the function with the integer as a para we have function pointers flying across the FFI boundary in both directions. ```rust -use std::os::raw::c_int; +# #![feature(libc)] +extern crate libc; +use libc::c_int; # #[cfg(hidden)] extern "C" { From 91acc3977bdb62b52698b488c63070adbf29af30 Mon Sep 17 00:00:00 2001 From: "Panashe M. Fundira" Date: Wed, 27 Jul 2016 15:01:43 -0400 Subject: [PATCH 16/23] Correct minor typo in debug_assert doc --- src/libcore/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index e3207a0a86c..c8606b0f163 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -138,7 +138,7 @@ macro_rules! assert_eq { /// running, which might have unexpected consequences but does not introduce /// unsafety as long as this only happens in safe code. The performance cost /// of assertions, is however, not measurable in general. Replacing `assert!` -/// with `debug_assert!` is thus only encourage after thorough profiling, and +/// with `debug_assert!` is thus only encouraged after thorough profiling, and /// more importantly, only in safe code! /// /// # Examples From 8760b1dd264bfd4f00a772e3229d02b9bb0e25f4 Mon Sep 17 00:00:00 2001 From: "Panashe M. Fundira" Date: Wed, 27 Jul 2016 15:03:23 -0400 Subject: [PATCH 17/23] Revert section about panic! in assert! doc --- src/libcore/macros.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index c8606b0f163..260d974e45d 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -32,9 +32,8 @@ macro_rules! panic { /// Ensure that a boolean expression is `true` at runtime. /// -/// This will ensure the termination of the program if the provided expression -/// cannot be evaluated to `true` at runtime by means of an unrecoverable error -/// (not necessarily a `panic!`, can also be an `abort`). +/// This will invoke the `panic!` macro if the provided expression cannot be +/// evaluated to `true` at runtime. /// /// Assertions are always checked in both debug and release builds, and cannot /// be disabled. From 9a7367b96035ab1ff7593f929c852181de1bcbfb Mon Sep 17 00:00:00 2001 From: "Panashe M. Fundira" Date: Wed, 27 Jul 2016 15:16:11 -0400 Subject: [PATCH 18/23] Mention debug_assert! in assert! doc --- src/libcore/macros.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 260d974e45d..b0c79a3a885 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -36,7 +36,8 @@ macro_rules! panic { /// evaluated to `true` at runtime. /// /// Assertions are always checked in both debug and release builds, and cannot -/// be disabled. +/// be disabled. See `debug_assert!` for assertions that are not enabled in +/// release builds by default. /// /// Unsafe code relies on `assert!` to enforce run-time invariants that, if /// violated could lead to unsafety. From 52c50ba276ffbdbe9c1a56e4f0b7d424f6bc22cc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Jul 2016 02:53:34 +0200 Subject: [PATCH 19/23] Add doc examples for std::fs::Metadata --- src/libstd/fs.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 48753ccf1c3..38fd93501a5 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -694,6 +694,23 @@ impl Metadata { /// /// This field may not be available on all platforms, and will return an /// `Err` on platforms where it is not available. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// + /// if let Ok(time) = metadata.modified() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn modified(&self) -> io::Result { self.0.modified().map(FromInner::from_inner) @@ -712,6 +729,23 @@ impl Metadata { /// /// This field may not be available on all platforms, and will return an /// `Err` on platforms where it is not available. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// + /// if let Ok(time) = metadata.accessed() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn accessed(&self) -> io::Result { self.0.accessed().map(FromInner::from_inner) @@ -726,6 +760,23 @@ impl Metadata { /// /// This field may not be available on all platforms, and will return an /// `Err` on platforms where it is not available. + /// + /// # Examples + /// + /// ``` + /// # fn foo() -> std::io::Result<()> { + /// use std::fs; + /// + /// let metadata = try!(fs::metadata("foo.txt")); + /// + /// if let Ok(time) = metadata.created() { + /// println!("{:?}", time); + /// } else { + /// println!("Not supported on this platform"); + /// } + /// # Ok(()) + /// # } + /// ``` #[stable(feature = "fs_time", since = "1.10.0")] pub fn created(&self) -> io::Result { self.0.created().map(FromInner::from_inner) From 8d3f20f9061273b215a7d86f8783f1ae66f9b3ae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Jul 2016 12:55:58 +0200 Subject: [PATCH 20/23] Add doc examples for std::fs::unix::OpenOptionsExt --- src/libstd/sys/unix/ext/fs.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 54340773a42..1e0dc3c833e 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -63,6 +63,18 @@ pub trait OpenOptionsExt { /// If no `mode` is set, the default of `0o666` will be used. /// The operating system masks out bits with the systems `umask`, to produce /// the final permissions. + /// + /// # Examples + /// + /// ```rust,ignore + /// extern crate libc; + /// use std::fs::OpenOptions; + /// use std::os::unix::fs::OpenOptionsExt; + /// + /// let mut options = OpenOptions::new(); + /// options.mode(0o644); // Give read/write for owner and read for others. + /// let file = options.open("foo.txt"); + /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&mut self, mode: u32) -> &mut Self; From 123bf1e95d05282dc32d9a2403859dd827d84309 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Jul 2016 13:04:24 +0200 Subject: [PATCH 21/23] Add OpenOptionsExt doc examples --- src/libstd/sys/unix/ext/fs.rs | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 1e0dc3c833e..77587918ac9 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -25,15 +25,53 @@ use sys::platform::fs::MetadataExt as UnixMetadataExt; pub trait PermissionsExt { /// Returns the underlying raw `mode_t` bits that are the standard Unix /// permissions for this file. + /// + /// # Examples + /// + /// ```rust,ignore + /// use std::fs::File; + /// use std::os::unix::fs::PermissionsExt; + /// + /// let f = try!(File::create("foo.txt")); + /// let metadata = try!(f.metadata()); + /// let permissions = metadata.permissions(); + /// + /// println!("permissions: {}", permissions.mode()); + /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; /// Sets the underlying raw bits for this set of permissions. + /// + /// # Examples + /// + /// ```rust,ignore + /// use std::fs::File; + /// use std::os::unix::fs::PermissionsExt; + /// + /// let f = try!(File::create("foo.txt")); + /// let metadata = try!(f.metadata()); + /// let mut permissions = metadata.permissions(); + /// + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); /// Creates a new instance of `Permissions` from the given set of Unix /// permission bits. + /// + /// # Examples + /// + /// ```rust,ignore + /// use std::fs::Permissions; + /// use std::os::unix::fs::PermissionsExt; + /// + /// // Read/write for owner and read for others. + /// let permissions = Permissions::from_mode(0o644); + /// assert_eq!(permissions.mode(), 0o644); + /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn from_mode(mode: u32) -> Self; } From f98c55d933d24a806cee85bb0239682b39a23e32 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 26 Jul 2016 22:52:56 -0400 Subject: [PATCH 22/23] Add documentation example for `str::Chars::as_str`. --- src/libcore/str/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a32c9da9815..fdcadd43a0f 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -459,6 +459,19 @@ impl<'a> Chars<'a> { /// /// This has the same lifetime as the original slice, and so the /// iterator can continue to be used while this exists. + /// + /// # Examples + /// + /// ``` + /// let mut chars = "abc".chars(); + /// + /// assert_eq!(chars.as_str(), "abc"); + /// chars.next(); + /// assert_eq!(chars.as_str(), "bc"); + /// chars.next(); + /// chars.next(); + /// assert_eq!(chars.as_str(), ""); + /// ``` #[stable(feature = "iter_to_slice", since = "1.4.0")] #[inline] pub fn as_str(&self) -> &'a str { From 3563e400cc834bece5064e57ad698163865687d7 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 28 Jul 2016 19:02:25 -0700 Subject: [PATCH 23/23] Try to clear up some awkward wording --- src/doc/book/closures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index 666d0946ecc..24fcf886ef0 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -291,9 +291,9 @@ isn’t interesting. The next part is: # some_closure(1) } ``` -Because `Fn` is a trait, we can bound our generic with it. In this case, our -closure takes a `i32` as an argument and returns an `i32`, and so the generic -bound we use is `Fn(i32) -> i32`. +Because `Fn` is a trait, we can use it as a bound for our generic type. In +this case, our closure takes a `i32` as an argument and returns an `i32`, and +so the generic bound we use is `Fn(i32) -> i32`. There’s one other key point here: because we’re bounding a generic with a trait, this will get monomorphized, and therefore, we’ll be doing static