Skip to content

Rollup of 11 pull requests #27265

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

Merged
merged 28 commits into from
Jul 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e6c058e
Rename 'link-args' to 'advanced-linking', add intro
aidanhs May 21, 2015
e5c1884
Note possiblities of empty extern blocks (based on #12575)
aidanhs May 21, 2015
7af865b
Static linking
aidanhs May 21, 2015
dd3ac90
Add long diagnostics for E0223 and E0225
AlisdairO Jul 22, 2015
a8a49fb
musl static linking not glibc
aidanhs Jun 15, 2015
b6a0d9e
Additional notes to link-args
aidanhs Jun 15, 2015
c80bff0
Added how to use labels to break nested loops to trpl.
echochamber Jul 21, 2015
cf8a163
add diagnostics for E0437 and E0438
apasel422 Jul 22, 2015
a700546
Fix `thread::catch_panic` documentation to mention its return value o…
tbu- Jul 23, 2015
38c5af8
Add long diagnostics for E0373
AlisdairO Jul 23, 2015
e668175
Add diagnostics for E0120
AlisdairO Jul 22, 2015
a319d32
Link Deref{,Mut} to TRPL on coercions.
steveklabnik Jul 23, 2015
01cb16d
fixes #27124 for bitrig
Jul 19, 2015
8ffbde4
review feedback fixes
Jul 23, 2015
b208bd9
switching to gnu archive format per review request
Jul 23, 2015
39c7a93
adds snapshots for bitrig and freebsd
Jul 23, 2015
e981311
eval_const_expr_partial now returns ConstVal::Struct instead of None …
Detegr Jul 23, 2015
bc51e80
Rollup merge of #27137 - dhuseby:fixing_bitrig_linking, r=alexcrichton
steveklabnik Jul 24, 2015
3fa9090
Rollup merge of #27145 - apasel422:diagnostic-407-437-438, r=Manishearth
steveklabnik Jul 24, 2015
e490ba9
Rollup merge of #27177 - echochamber:master, r=steveklabnik
steveklabnik Jul 24, 2015
43edc1c
Rollup merge of #27193 - aidanhs:aphs-advanced-linking-doc, r=stevekl…
steveklabnik Jul 24, 2015
fafb1fa
Rollup merge of #27212 - AlisdairO:diagnostics225, r=Manishearth
steveklabnik Jul 24, 2015
a75c21f
Rollup merge of #27220 - AlisdairO:diagnostics120, r=Manishearth
steveklabnik Jul 24, 2015
a160203
Rollup merge of #27229 - AlisdairO:diagnostics371, r=Manishearth
steveklabnik Jul 24, 2015
8b6b6c6
Rollup merge of #27235 - tbu-:pr_catch_panic_doc, r=steveklabnik
steveklabnik Jul 24, 2015
47c9c49
Rollup merge of #27238 - steveklabnik:gh26927, r=huonw
steveklabnik Jul 24, 2015
628654b
Rollup merge of #27244 - Detegr:master, r=eddyb
steveklabnik Jul 24, 2015
427238c
Rollup merge of #27251 - dhuseby:adding_snapshots, r=alexcrichton
steveklabnik Jul 24, 2015
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
4 changes: 4 additions & 0 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/doc/trpl/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
151 changes: 151 additions & 0 deletions src/doc/trpl/advanced-linking.md
Original file line number Diff line number Diff line change
@@ -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.
25 changes: 0 additions & 25 deletions src/doc/trpl/link-args.md

This file was deleted.

18 changes: 18 additions & 0 deletions src/doc/trpl/while-loops.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 8 additions & 0 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_back/target/bitrig_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
51 changes: 50 additions & 1 deletion src/librustc_borrowck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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
Expand Down
53 changes: 51 additions & 2 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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! {
Expand Down Expand Up @@ -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
}
Loading