diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index 161c4ce90b24..983af4a0efe7 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -411,8 +411,9 @@ fn factory() -> &(Fn(i32) -> i32) { ``` Right. Because we have a reference, we need to give it a lifetime. But -our `factory()` function takes no arguments, so elision doesn’t kick in -here. What lifetime can we choose? `'static`: +our `factory()` function takes no arguments, so +[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what +choices do we have? Try `'static`: ```rust,ignore fn factory() -> &'static (Fn(i32) -> i32) { @@ -432,7 +433,7 @@ But we get another error: ```text error: mismatched types: expected `&'static core::ops::Fn(i32) -> i32`, - found `[closure :7:9: 7:20]` + found `[closure@:7:9: 7:20]` (expected &-ptr, found closure) [E0308] |x| x + num @@ -441,21 +442,17 @@ error: mismatched types: ``` This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`, -we have a `[closure :7:9: 7:20]`. Wait, what? +we have a `[closure@:7:9: 7:20]`. Wait, what? Because each closure generates its own environment `struct` and implementation of `Fn` and friends, these types are anonymous. They exist just solely for -this closure. So Rust shows them as `closure `, rather than some +this closure. So Rust shows them as `closure@`, rather than some autogenerated name. -But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before, -closures borrow their environment. And in this case, our environment is based -on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime -of the stack frame. So if we returned this closure, the function call would be -over, the stack frame would go away, and our closure is capturing an environment -of garbage memory! - -So what to do? This _almost_ works: +The error also points out that the return type is expected to be a reference, +but what we are trying to return is not. Further, we cannot directly assign a +`'static` lifetime to an object. So we'll take a different approach and return +a "trait object" by `Box`ing up the `Fn`. This _almost_ works: ```rust,ignore fn factory() -> Box i32> { @@ -471,7 +468,7 @@ assert_eq!(6, answer); # } ``` -We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem: +There’s just one last problem: ```text error: closure may outlive the current function, but it borrows `num`, @@ -480,8 +477,12 @@ Box::new(|x| x + num) ^~~~~~~~~~~ ``` -We still have a reference to the parent stack frame. With one last fix, we can -make this work: +Well, as we discussed before, closures borrow their environment. And in this +case, our environment is based on a stack-allocated `5`, the `num` variable +binding. So the borrow has a lifetime of the stack frame. So if we returned +this closure, the function call would be over, the stack frame would go away, +and our closure is capturing an environment of garbage memory! With one last +fix, we can make this work: ```rust fn factory() -> Box i32> { diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index 62270cb45b5e..fb2fc83e0626 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -349,9 +349,9 @@ fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is fn get_mut(&mut self) -> &mut T; // elided fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded -fn args(&mut self, args: &[T]) -> &mut Command // elided -fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded +fn args(&mut self, args: &[T]) -> &mut Command; // elided +fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded fn new(buf: &mut [u8]) -> BufWriter; // elided -fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded +fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded ``` diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 48d003c2cffb..193b8d6d620d 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -434,6 +434,11 @@ pub fn replace(dest: &mut T, mut src: T) -> T { /// While this does call the argument's implementation of `Drop`, it will not /// release any borrows, as borrows are based on lexical scope. /// +/// This effectively does nothing for +/// [types which implement `Copy`](../../book/ownership.html#copy-types), +/// e.g. integers. Such values are copied and _then_ moved into the function, +/// so the value persists after this function call. +/// /// # Examples /// /// Basic usage: @@ -486,6 +491,21 @@ pub fn replace(dest: &mut T, mut src: T) -> T { /// let borrow = x.borrow(); /// println!("{}", *borrow); /// ``` +/// +/// Integers and other types implementing `Copy` are unaffected by `drop()` +/// +/// ``` +/// #[derive(Copy, Clone)] +/// struct Foo(u8); +/// +/// let x = 1; +/// let y = Foo(2); +/// drop(x); // a copy of `x` is moved and dropped +/// drop(y); // a copy of `y` is moved and dropped +/// +/// println!("x: {}, y: {}", x, y.0); // still available +/// ``` +/// #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn drop(_x: T) { } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 5518bacb019e..a4ccc975d56b 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1410,7 +1410,7 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} // Free functions // -/// Converts a pointer to A into a slice of length 1 (without copying). +/// Converts a reference to A into a slice of length 1 (without copying). #[unstable(feature = "ref_slice", issue = "27774")] pub fn ref_slice(s: &A) -> &[A] { unsafe { @@ -1418,7 +1418,7 @@ pub fn ref_slice(s: &A) -> &[A] { } } -/// Converts a pointer to A into a slice of length 1 (without copying). +/// Converts a reference to A into a slice of length 1 (without copying). #[unstable(feature = "ref_slice", issue = "27774")] pub fn mut_ref_slice(s: &mut A) -> &mut [A] { unsafe { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 69ebcb1ab7e1..456e89d47212 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -115,8 +115,8 @@ impl Utf8Error { /// Returns the index in the given string up to which valid UTF-8 was /// verified. /// - /// Starting at the index provided, but not necessarily at it precisely, an - /// invalid UTF-8 encoding sequence was found. + /// It is the maximum index such that `from_utf8(input[..index])` + /// would return `Some(_)`. #[unstable(feature = "utf8_error", reason = "method just added", issue = "27734")] pub fn valid_up_to(&self) -> usize { self.valid_up_to } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a07d21add8db..a88ddb997f61 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -98,7 +98,7 @@ macro_rules! print { ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); } -/// Macro for printing to the standard output. +/// Macro for printing to the standard output, with a newline. /// /// Use the `format!` syntax to write data to the standard output. /// See `std::fmt` for more information.