diff --git a/src/doc/reference.md b/src/doc/reference.md index a37e1c146681e..26fd2fd8d20d6 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 ca3381ffba465..f1e51591aea0e 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 0000000000000..6d37043354282 --- /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 '
' 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 cdaef6cd9b510..0000000000000 --- 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 0f5c3c64a4b17..124ebc7d69ddc 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 2ea42011a5cf2..c1cf2230ac476 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1057,6 +1057,10 @@ impl fmt::Debug for RangeTo { /// 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 9e2bcbaec8a6c..a349dab0f72ea 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 9f6a1f1e53007..ddb32f4625b58 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 3e7cfe3ee7f88..4f90a287cb999 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 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 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 5a941c757fc6d..9f8a5c90d4e1c 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 f865de522b28a..73ee3bbbe5b01 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 { foo: T } + +impl Drop for MyWrapper { + fn drop(&mut self) {} +} + +``` + +Alternatively, wrapping trait objects requires something like the following: + +``` +trait MyTrait {} + +//or Box, 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; // 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: ::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; +} +``` + +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; +} +``` +"##, + 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 3299c848ba724..20fcd309a6bef 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 cb5790b34f4d3..5c3e55e286232 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 0000000000000..2a4b98563ab9f --- /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 or the MIT license +// , 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 +}