Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #28665

Merged
merged 13 commits into from
Sep 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions src/doc/trpl/closures.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand All @@ -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> {
Expand All @@ -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`,
Expand All @@ -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> {
Expand Down
6 changes: 3 additions & 3 deletions src/doc/trpl/lifetimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
4 changes: 2 additions & 2 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,15 +1410,15 @@ 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 {
from_raw_parts(s, 1)
}
}

/// 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 {
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
15 changes: 3 additions & 12 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use back::archive;
use metadata::csearch;
use middle::dependency_format::Linkage;
use session::Session;
use session::config::DebugInfoLevel::{NoDebugInfo, LimitedDebugInfo, FullDebugInfo};
use session::config::CrateTypeDylib;
use session::config;
use syntax::ast;
Expand Down Expand Up @@ -281,17 +280,9 @@ impl<'a> Linker for MsvcLinker<'a> {
}

fn debuginfo(&mut self) {
match self.sess.opts.debuginfo {
NoDebugInfo => {
// Do nothing if debuginfo is disabled
},
LimitedDebugInfo |
FullDebugInfo => {
// This will cause the Microsoft linker to generate a PDB file
// from the CodeView line tables in the object files.
self.cmd.arg("/DEBUG");
}
}
// This will cause the Microsoft linker to generate a PDB file
// from the CodeView line tables in the object files.
self.cmd.arg("/DEBUG");
}

fn whole_archives(&mut self) {
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 6 additions & 2 deletions src/test/run-make/output-type-permutations/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ all:
$(call REMOVE_RLIBS,bar)
$(call REMOVE_DYLIBS,bar)
rm $(TMPDIR)/libbar.a
rm -f $(TMPDIR)/bar.{exp,lib}
rm -f $(TMPDIR)/bar.{exp,lib,pdb}
# Check that $(TMPDIR) is empty.
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]

$(RUSTC) foo.rs --crate-type=bin
rm $(TMPDIR)/$(call BIN,bar)
rm -f $(TMPDIR)/bar.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]

$(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link
Expand All @@ -19,6 +20,7 @@ all:
rm $(TMPDIR)/bar.s
rm $(TMPDIR)/bar.o
rm $(TMPDIR)/$(call BIN,bar)
rm -f $(TMPDIR)/bar.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]

$(RUSTC) foo.rs --emit=asm -o $(TMPDIR)/foo
Expand All @@ -39,6 +41,7 @@ all:

$(RUSTC) foo.rs --emit=link -o $(TMPDIR)/$(call BIN,foo)
rm $(TMPDIR)/$(call BIN,foo)
rm -f $(TMPDIR)/foo.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]

$(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo
Expand All @@ -47,7 +50,7 @@ all:

$(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo)
rm $(TMPDIR)/$(call BIN,foo)
rm -f $(TMPDIR)/foo.{exp,lib}
rm -f $(TMPDIR)/foo.{exp,lib,pdb}
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]

$(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
Expand All @@ -56,6 +59,7 @@ all:

$(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo)
rm $(TMPDIR)/$(call BIN,foo)
rm -f $(TMPDIR)/foo.pdb
[ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]

$(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link --crate-type=staticlib
Expand Down