Auto merge of #28665 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #28319, #28588, #28637, #28652, #28654, #28655 - Failed merges: #28621
This commit is contained in:
commit
69f27c856b
6 changed files with 45 additions and 24 deletions
|
|
@ -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 <anon>:7:9: 7:20]`
|
||||
found `[closure@<anon>: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 <anon>:7:9: 7:20]`. Wait, what?
|
||||
we have a `[closure@<anon>: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 <anon>`, rather than some
|
||||
this closure. So Rust shows them as `closure@<anon>`, 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<Fn(i32) -> 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<Fn(i32) -> i32> {
|
||||
|
|
|
|||
|
|
@ -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<T:ToCStr>(&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<T:ToCStr>(&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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -434,6 +434,11 @@ pub fn replace<T>(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<T>(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<T>(_x: T) { }
|
||||
|
|
|
|||
|
|
@ -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<A>(s: &A) -> &[A] {
|
||||
unsafe {
|
||||
|
|
@ -1418,7 +1418,7 @@ pub fn ref_slice<A>(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<A>(s: &mut A) -> &mut [A] {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue