about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/book/closures.md6
-rw-r--r--src/doc/book/ffi.md73
-rw-r--r--src/libcollections/fmt.rs20
-rw-r--r--src/libcore/macros.rs18
-rw-r--r--src/libcore/str/mod.rs13
-rw-r--r--src/libpanic_unwind/dwarf/eh.rs2
-rw-r--r--src/libstd/fs.rs51
-rw-r--r--src/libstd/sys/unix/ext/fs.rs50
8 files changed, 206 insertions, 27 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
diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md
index 3cbe5d60267..ca104ff29ac 100644
--- a/src/doc/book/ffi.md
+++ b/src/doc/book/ffi.md
@@ -575,16 +575,69 @@ 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<T>`), 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
-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<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
-function pointer using the C ABI.
+Certain Rust types are defined to never be `null`. This includes references (`&T`,
+`&mut T`), boxes (`Box<T>`), 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` 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<T>`,
+where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
+to represent a nullable function pointer using the C ABI (corresponding to the C type
+`int (*)(int)`).
+
+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 boundary in both directions.
+
+```rust
+# #![feature(libc)]
+extern crate libc;
+use libc::c_int;
+
+# #[cfg(hidden)]
+extern "C" {
+    /// Register the callback.
+    fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
+}
+# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> 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<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
+    match process {
+        Some(f) => f(int),
+        None    => int * int
+    }
+}
+
+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 `transmute` required!
 
 # Calling Rust code from C
 
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 `{<arg>:<spec>.*}`, then the `<arg>` part refers
 //!    to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
 //!
-//! 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:
 //!
 //! ```
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 43868d124a2..b0c79a3a885 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -35,6 +35,17 @@ macro_rules! panic {
 /// 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. 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.
+///
+/// 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.
 ///
 /// # Examples
@@ -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 encouraged after thorough profiling, and
+/// more importantly, only in safe code!
+///
 /// # Examples
 ///
 /// ```
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 {
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 {
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<SystemTime> {
         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<SystemTime> {
         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<SystemTime> {
         self.0.created().map(FromInner::from_inner)
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 54340773a42..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;
 }
@@ -63,6 +101,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;