Auto merge of #27265 - steveklabnik:rollup, r=steveklabnik

- Successful merges: #27137, #27145, #27177, #27193, #27212, #27220, #27229, #27235, #27238, #27244, #27251
- Failed merges:
This commit is contained in:
bors 2015-07-24 19:04:31 +00:00
commit 82d40cb2ba
14 changed files with 409 additions and 38 deletions

View File

@ -1636,6 +1636,10 @@ The type of a function declared in an extern block is `extern "abi" fn(A1, ...,
An) -> R`, where `A1...An` are the declared types of its arguments and `R` is
the declared return type.
It is valid to add the `link` attribute on an empty extern block. You can use
this to satisfy the linking requirements of extern blocks elsewhere in your code
(including upstream crates) instead of adding the attribute to each extern block.
## Visibility and Privacy
These two terms are often used interchangeably, and what they are attempting to

View File

@ -63,7 +63,7 @@
* [No stdlib](no-stdlib.md)
* [Intrinsics](intrinsics.md)
* [Lang items](lang-items.md)
* [Link args](link-args.md)
* [Advanced linking](advanced-linking.md)
* [Benchmark Tests](benchmark-tests.md)
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
* [Slice Patterns](slice-patterns.md)

View File

@ -0,0 +1,151 @@
% Advanced Linking
The common cases of linking with Rust have been covered earlier in this book,
but supporting the range of linking possibilities made available by other
languages is important for Rust to achieve seamless interaction with native
libraries.
# Link args
There is one other way to tell `rustc` how to customize linking, and that is via
the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:
``` no_run
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
```
Note that this feature is currently hidden behind the `feature(link_args)` gate
because this is not a sanctioned way of performing linking. Right now `rustc`
shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future `rustc` may use
LLVM directly to link native libraries, in which case `link_args` will have no
meaning. You can achieve the same effect as the `link-args` attribute with the
`-C link-args` argument to `rustc`.
It is highly recommended to *not* use this attribute, and rather use the more
formal `#[link(...)]` attribute on `extern` blocks instead.
# Static linking
Static linking refers to the process of creating output that contain all
required libraries and so don't need libraries installed on every system where
you want to use your compiled project. Pure-Rust dependencies are statically
linked by default so you can use created binaries and libraries without
installing the Rust everywhere. By contrast, native libraries
(e.g. `libc` and `libm`) usually dynamically linked, but it is possible to
change this and statically link them as well.
Linking is a very platform dependent topic — on some platforms, static linking
may not be possible at all! This section assumes some basic familiarity with
linking on your platform of choice.
## Linux
By default, all Rust programs on Linux will link to the system `libc` along with
a number of other libraries. Let's look at an example on a 64-bit Linux machine
with GCC and `glibc` (by far the most common `libc` on Linux):
``` text
$ cat example.rs
fn main() {}
$ rustc example.rs
$ ldd example
linux-vdso.so.1 => (0x00007ffd565fd000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000)
```
Dynamic linking on Linux can be undesirable if you wish to use new library
features on old systems or target systems which do not have the required
dependencies for your program to run.
Static linking is supported via an alternative `libc`, `musl` - this must be
enabled at Rust compile-time with some prerequisites available. You can compile
your own version of Rust with `musl` enabled and install it into a custom
directory with the instructions below:
```text
$ mkdir musldist
$ PREFIX=$(pwd)/musldist
$
$ # Build musl
$ wget http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
[...]
$ tar xf musl-1.1.10.tar.gz
$ cd musl-1.1.10/
musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
[...]
musl-1.1.10 $ make
[...]
musl-1.1.10 $ make install
[...]
musl-1.1.10 $ cd ..
$ du -h musldist/lib/libc.a
2.2M musldist/lib/libc.a
$
$ # Build libunwind.a
$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz
$ tar xf llvm-3.6.1.src.tar.xz
$ cd llvm-3.6.1.src/projects/
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind
llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt
llvm-3.6.1.src/projects $ mkdir libunwind/build
llvm-3.6.1.src/projects $ cd libunwind/build
llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
llvm-3.6.1.src/projects/libunwind/build $ make
llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
llvm-3.6.1.src/projects/libunwind/build $ cd cd ../../../../
$ du -h musldist/lib/libunwind.a
164K musldist/lib/libunwind.a
$
$ # Build musl-enabled rust
$ git clone https://github.com/rust-lang/rust.git muslrust
$ cd muslrust
muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
muslrust $ make
muslrust $ make install
muslrust $ cd ..
$ du -h musldist/bin/rustc
12K musldist/bin/rustc
```
You now have a build of a `musl`-enabled Rust! Because we've installed it to a
custom prefix we need to make sure our system can the binaries and appropriate
libraries when we try and run it:
```text
$ export PATH=$PREFIX/bin:$PATH
$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
```
Let's try it out!
```text
$ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
$ rustc --target=x86_64-unknown-linux-musl example.rs
$ ldd example
not a dynamic executable
$ ./example
hi!
thread '<main>' panicked at 'failed', example.rs:1
```
Success! This binary can be copied to almost any Linux machine with the same
machine architecture and run without issues.
`cargo build` also permits the `--target` option so you should be able to build
your crates as normal. However, you may need to recompile your native libraries
against `musl` before they can be linked against.

View File

@ -1,25 +0,0 @@
% Link args
There is one other way to tell rustc how to customize linking, and that is via
the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:
``` no_run
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
```
Note that this feature is currently hidden behind the `feature(link_args)` gate
because this is not a sanctioned way of performing linking. Right now rustc
shells out to the system linker, so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future rustc may use
LLVM directly to link native libraries, in which case `link_args` will have no
meaning.
It is highly recommended to *not* use this attribute, and rather use the more
formal `#[link(...)]` attribute on `extern` blocks instead.

View File

@ -88,6 +88,24 @@ for x in 0..10 {
}
```
You may also encounter situations where you have nested loops and need to
specify which one your `break` or `continue` statement is for. Like most
other languages, by default a `break` or `continue` will apply to innermost
loop. In a sitation where you would like to a `break` or `continue` for one
of the outer loops, you can use labels to specify which loop the `break` or
`continue` statement applies to. This will only print when both `x` and `y` are
odd:
```rust
'outer: for x in 0..10 {
'inner: for y in 0..10 {
if x % 2 == 0 { continue 'outer; } // continues the loop over x
if y % 2 == 0 { continue 'inner; } // continues the loop over y
println!("x: {}, y: {}", x, y);
}
}
```
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
[for]: for-loops.html

View File

@ -1057,6 +1057,10 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
/// The `Deref` trait is used to specify the functionality of dereferencing
/// operations like `*v`.
///
/// `Deref` also enables ['`Deref` coercions'][coercions].
///
/// [coercions]: ../../book/deref-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible via dereferencing the
@ -1111,6 +1115,10 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
/// The `DerefMut` trait is used to specify the functionality of dereferencing
/// mutably like `*v = 1;`
///
/// `DerefMut` also enables ['`Deref` coercions'][coercions].
///
/// [coercions]: ../../book/deref-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable via dereferencing the

View File

@ -967,6 +967,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
Some(def::DefVariant(enum_def, variant_def, _)) => {
(lookup_variant_by_id(tcx, enum_def, variant_def), None)
}
Some(def::DefStruct(_)) => {
return Ok(ConstVal::Struct(e.id))
}
_ => (None, None)
};
let const_expr = match const_expr {

View File

@ -20,9 +20,7 @@ pub fn opts() -> TargetOptions {
linker_is_gnu: true,
has_rpath: true,
position_independent_executables: true,
pre_link_args: vec!(
),
archive_format: "bsd".to_string(),
archive_format: "gnu".to_string(),
.. Default::default()
}

View File

@ -12,6 +12,56 @@
register_long_diagnostics! {
E0373: r##"
This error occurs when an attempt is made to use data captured by a closure,
when that data may no longer exist. It's most commonly seen when attempting to
return a closure:
```
fn foo() -> Box<Fn(u32) -> u32> {
let x = 0u32;
Box::new(|y| x + y)
}
```
Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
closed-over data by reference. This means that once `foo()` returns, `x` no
longer exists. An attempt to access `x` within the closure would thus be unsafe.
Another situation where this might be encountered is when spawning threads:
```
fn foo() {
let x = 0u32;
let y = 1u32;
let thr = std::thread::spawn(|| {
x + y
});
}
```
Since our new thread runs in parallel, the stack frame containing `x` and `y`
may well have disappeared by the time we try to use them. Even if we call
`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
stack frame won't disappear), we will not succeed: the compiler cannot prove
that this behaviour is safe, and so won't let us do it.
The solution to this problem is usually to switch to using a `move` closure.
This approach moves (or copies, where possible) data into the closure, rather
than taking references to it. For example:
```
fn foo() -> Box<Fn(u32) -> u32> {
let x = 0u32;
Box::new(move |y| x + y)
}
```
Now that the closure has its own copy of the data, there's no need to worry
about safety.
"##,
E0381: r##"
It is not allowed to use or capture an uninitialized variable. For example:
@ -28,7 +78,6 @@ used.
}
register_diagnostics! {
E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn
E0382, // use of partially/collaterally moved value
E0383, // partial reinitialization of uninitialized structure
E0384, // reassignment of immutable variable

View File

@ -426,6 +426,57 @@ use something_which_doesnt_exist;
Please verify you didn't misspell the import's name.
"##,
E0437: r##"
Trait impls can only implement associated types that are members of the trait in
question. This error indicates that you attempted to implement an associated
type whose name does not match the name of any associated type in the trait.
Here is an example that demonstrates the error:
```
trait Foo {}
impl Foo for i32 {
type Bar = bool;
}
```
The solution to this problem is to remove the extraneous associated type:
```
trait Foo {}
impl Foo for i32 {}
```
"##,
E0438: r##"
Trait impls can only implement associated constants that are members of the
trait in question. This error indicates that you attempted to implement an
associated constant whose name does not match the name of any associated
constant in the trait.
Here is an example that demonstrates the error:
```
#![feature(associated_consts)]
trait Foo {}
impl Foo for i32 {
const BAR: bool = true;
}
```
The solution to this problem is to remove the extraneous associated constant:
```
trait Foo {}
impl Foo for i32 {}
```
"##
}
register_diagnostics! {
@ -468,6 +519,4 @@ register_diagnostics! {
E0432, // unresolved import
E0434, // can't capture dynamic environment in a fn item
E0435, // attempt to use a non-constant value in a constant
E0437, // type is not a member of trait
E0438, // const is not a member of trait
}

View File

@ -1316,6 +1316,45 @@ fn main() {
```
"##,
E0120: r##"
An attempt was made to implement Drop on a trait, which is not allowed: only
structs and enums can implement Drop. An example causing this error:
```
trait MyTrait {}
impl Drop for MyTrait {
fn drop(&mut self) {}
}
```
A workaround for this problem is to wrap the trait up in a struct, and implement
Drop on that. An example is shown below:
```
trait MyTrait {}
struct MyWrapper<T: MyTrait> { foo: T }
impl <T: MyTrait> Drop for MyWrapper<T> {
fn drop(&mut self) {}
}
```
Alternatively, wrapping trait objects requires something like the following:
```
trait MyTrait {}
//or Box<MyTrait>, if you wanted an owned trait object
struct MyWrapper<'a> { foo: &'a MyTrait }
impl <'a> Drop for MyWrapper<'a> {
fn drop(&mut self) {}
}
```
"##,
E0121: r##"
In order to be consistent with Rust's lack of global type inference, type
placeholders are disallowed by design in item signatures.
@ -1895,6 +1934,62 @@ type Foo = Trait<Bar=i32>; // ok!
```
"##,
E0223: r##"
An attempt was made to retrieve an associated type, but the type was ambiguous.
For example:
```
trait MyTrait {type X; }
fn main() {
let foo: MyTrait::X;
}
```
The problem here is that we're attempting to take the type of X from MyTrait.
Unfortunately, the type of X is not defined, because it's only made concrete in
implementations of the trait. A working version of this code might look like:
```
trait MyTrait {type X; }
struct MyStruct;
impl MyTrait for MyStruct {
type X = u32;
}
fn main() {
let foo: <MyStruct as MyTrait>::X;
}
```
This syntax specifies that we want the X type from MyTrait, as made concrete in
MyStruct. The reason that we cannot simply use `MyStruct::X` is that MyStruct
might implement two different traits with identically-named associated types.
This syntax allows disambiguation between the two.
"##,
E0225: r##"
You attempted to use multiple types as bounds for a closure or trait object.
Rust does not currently support this. A simple example that causes this error:
```
fn main() {
let _: Box<std::io::Read+std::io::Write>;
}
```
Builtin traits are an exception to this rule: it's possible to have bounds of
one non-builtin type, plus any number of builtin types. For example, the
following compiles correctly:
```
fn main() {
let _: Box<std::io::Read+Copy+Sync>;
}
```
"##,
E0232: r##"
The attribute must have a value. Erroneous code example:
@ -2195,7 +2290,6 @@ register_diagnostics! {
E0103,
E0104,
E0118,
E0120,
E0122,
E0123,
E0127,
@ -2233,9 +2327,7 @@ register_diagnostics! {
E0221, // ambiguous associated type in bounds
//E0222, // Error code E0045 (variadic function must have C calling
// convention) duplicate
E0223, // ambiguous associated type
E0224, // at least one non-builtin train is required for an object type
E0225, // only the builtin traits can be used as closure or object bounds
E0226, // only a single explicit lifetime bound is permitted
E0227, // ambiguous lifetime bound, explicit lifetime bound required
E0228, // explicit lifetime bound required

View File

@ -434,9 +434,9 @@ pub fn panicking() -> bool {
/// Invokes a closure, capturing the cause of panic if one occurs.
///
/// This function will return `Ok(())` if the closure does not panic, and will
/// return `Err(cause)` if the closure panics. The `cause` returned is the
/// object with which panic was originally invoked.
/// This function will return `Ok` with the closure's result if the closure
/// does not panic, and will return `Err(cause)` if the closure panics. The
/// `cause` returned is the object with which panic was originally invoked.
///
/// It is currently undefined behavior to unwind from Rust code into foreign
/// code, so this function is particularly useful when Rust is called from

View File

@ -1,4 +1,7 @@
S 2015-07-17 d4432b3
bitrig-x86_64 af77768e0eb0f4c7ec5a8e36047a08053b54b230
freebsd-i386 b049325e5b2efe5f4884f3dafda448c1dac49b4f
freebsd-x86_64 a59e397188dbfe67456a6301df5ca13c7e238ab9
linux-i386 93f6216a35d3bed3cedf244c9aff4cd716336bd9
linux-x86_64 d8f4967fc71a153c925faecf95a7feadf7e463a4
macos-i386 29852c4d4b5a851f16d627856a279cae5bf9bd01

View File

@ -0,0 +1,21 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct S;
fn main() {
let b = [0; S];
//~^ ERROR mismatched types
//~| expected `usize`
//~| found `S`
//~| expected usize
//~| found struct `S`
//~| ERROR expected positive integer for repeat count, found struct
}