about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/reference.md4
-rw-r--r--src/doc/trpl/SUMMARY.md2
-rw-r--r--src/doc/trpl/advanced-linking.md151
-rw-r--r--src/doc/trpl/link-args.md25
-rw-r--r--src/doc/trpl/while-loops.md18
-rw-r--r--src/libcore/ops.rs8
-rw-r--r--src/librustc/middle/const_eval.rs3
-rw-r--r--src/librustc_back/target/bitrig_base.rs4
-rw-r--r--src/librustc_borrowck/diagnostics.rs51
-rw-r--r--src/librustc_resolve/diagnostics.rs53
-rw-r--r--src/librustc_typeck/diagnostics.rs98
-rw-r--r--src/libstd/thread/mod.rs6
-rw-r--r--src/snapshots.txt3
-rw-r--r--src/test/compile-fail/issue-27008.rs21
14 files changed, 409 insertions, 38 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index a37e1c14668..26fd2fd8d20 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -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
diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md
index ca3381ffba4..f1e51591aea 100644
--- a/src/doc/trpl/SUMMARY.md
+++ b/src/doc/trpl/SUMMARY.md
@@ -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)
diff --git a/src/doc/trpl/advanced-linking.md b/src/doc/trpl/advanced-linking.md
new file mode 100644
index 00000000000..6d370433542
--- /dev/null
+++ b/src/doc/trpl/advanced-linking.md
@@ -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.
diff --git a/src/doc/trpl/link-args.md b/src/doc/trpl/link-args.md
deleted file mode 100644
index cdaef6cd9b5..00000000000
--- a/src/doc/trpl/link-args.md
+++ /dev/null
@@ -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.
-
diff --git a/src/doc/trpl/while-loops.md b/src/doc/trpl/while-loops.md
index 0f5c3c64a4b..124ebc7d69d 100644
--- a/src/doc/trpl/while-loops.md
+++ b/src/doc/trpl/while-loops.md
@@ -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
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 2ea42011a5c..c1cf2230ac4 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -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
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 9e2bcbaec8a..a349dab0f72 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -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 {
diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_back/target/bitrig_base.rs
index 9f6a1f1e530..ddb32f4625b 100644
--- a/src/librustc_back/target/bitrig_base.rs
+++ b/src/librustc_back/target/bitrig_base.rs
@@ -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()
     }
diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs
index 3e7cfe3ee7f..4f90a287cb9 100644
--- a/src/librustc_borrowck/diagnostics.rs
+++ b/src/librustc_borrowck/diagnostics.rs
@@ -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
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 5a941c757fc..9f8a5c90d4e 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -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
 }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index f865de522b2..73ee3bbbe5b 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -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
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 3299c848ba7..20fcd309a6b 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -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
diff --git a/src/snapshots.txt b/src/snapshots.txt
index cb5790b34f4..5c3e55e2862 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -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
diff --git a/src/test/compile-fail/issue-27008.rs b/src/test/compile-fail/issue-27008.rs
new file mode 100644
index 00000000000..2a4b98563ab
--- /dev/null
+++ b/src/test/compile-fail/issue-27008.rs
@@ -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
+}