Skip to content

Commit 82d40cb

Browse files
committed
Auto merge of #27265 - steveklabnik:rollup, r=steveklabnik
- Successful merges: #27137, #27145, #27177, #27193, #27212, #27220, #27229, #27235, #27238, #27244, #27251 - Failed merges:
2 parents 5e6b534 + 427238c commit 82d40cb

File tree

14 files changed

+409
-38
lines changed

14 files changed

+409
-38
lines changed

src/doc/reference.md

+4
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,10 @@ The type of a function declared in an extern block is `extern "abi" fn(A1, ...,
16361636
An) -> R`, where `A1...An` are the declared types of its arguments and `R` is
16371637
the declared return type.
16381638

1639+
It is valid to add the `link` attribute on an empty extern block. You can use
1640+
this to satisfy the linking requirements of extern blocks elsewhere in your code
1641+
(including upstream crates) instead of adding the attribute to each extern block.
1642+
16391643
## Visibility and Privacy
16401644

16411645
These two terms are often used interchangeably, and what they are attempting to

src/doc/trpl/SUMMARY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
* [No stdlib](no-stdlib.md)
6464
* [Intrinsics](intrinsics.md)
6565
* [Lang items](lang-items.md)
66-
* [Link args](link-args.md)
66+
* [Advanced linking](advanced-linking.md)
6767
* [Benchmark Tests](benchmark-tests.md)
6868
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
6969
* [Slice Patterns](slice-patterns.md)

src/doc/trpl/advanced-linking.md

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
% Advanced Linking
2+
3+
The common cases of linking with Rust have been covered earlier in this book,
4+
but supporting the range of linking possibilities made available by other
5+
languages is important for Rust to achieve seamless interaction with native
6+
libraries.
7+
8+
# Link args
9+
10+
There is one other way to tell `rustc` how to customize linking, and that is via
11+
the `link_args` attribute. This attribute is applied to `extern` blocks and
12+
specifies raw flags which need to get passed to the linker when producing an
13+
artifact. An example usage would be:
14+
15+
``` no_run
16+
#![feature(link_args)]
17+
18+
#[link_args = "-foo -bar -baz"]
19+
extern {}
20+
# fn main() {}
21+
```
22+
23+
Note that this feature is currently hidden behind the `feature(link_args)` gate
24+
because this is not a sanctioned way of performing linking. Right now `rustc`
25+
shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
26+
so it makes sense to provide extra command line
27+
arguments, but this will not always be the case. In the future `rustc` may use
28+
LLVM directly to link native libraries, in which case `link_args` will have no
29+
meaning. You can achieve the same effect as the `link-args` attribute with the
30+
`-C link-args` argument to `rustc`.
31+
32+
It is highly recommended to *not* use this attribute, and rather use the more
33+
formal `#[link(...)]` attribute on `extern` blocks instead.
34+
35+
# Static linking
36+
37+
Static linking refers to the process of creating output that contain all
38+
required libraries and so don't need libraries installed on every system where
39+
you want to use your compiled project. Pure-Rust dependencies are statically
40+
linked by default so you can use created binaries and libraries without
41+
installing the Rust everywhere. By contrast, native libraries
42+
(e.g. `libc` and `libm`) usually dynamically linked, but it is possible to
43+
change this and statically link them as well.
44+
45+
Linking is a very platform dependent topic — on some platforms, static linking
46+
may not be possible at all! This section assumes some basic familiarity with
47+
linking on your platform of choice.
48+
49+
## Linux
50+
51+
By default, all Rust programs on Linux will link to the system `libc` along with
52+
a number of other libraries. Let's look at an example on a 64-bit Linux machine
53+
with GCC and `glibc` (by far the most common `libc` on Linux):
54+
55+
``` text
56+
$ cat example.rs
57+
fn main() {}
58+
$ rustc example.rs
59+
$ ldd example
60+
linux-vdso.so.1 => (0x00007ffd565fd000)
61+
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000)
62+
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000)
63+
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000)
64+
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000)
65+
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000)
66+
/lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000)
67+
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000)
68+
```
69+
70+
Dynamic linking on Linux can be undesirable if you wish to use new library
71+
features on old systems or target systems which do not have the required
72+
dependencies for your program to run.
73+
74+
Static linking is supported via an alternative `libc`, `musl` - this must be
75+
enabled at Rust compile-time with some prerequisites available. You can compile
76+
your own version of Rust with `musl` enabled and install it into a custom
77+
directory with the instructions below:
78+
79+
```text
80+
$ mkdir musldist
81+
$ PREFIX=$(pwd)/musldist
82+
$
83+
$ # Build musl
84+
$ wget http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
85+
[...]
86+
$ tar xf musl-1.1.10.tar.gz
87+
$ cd musl-1.1.10/
88+
musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
89+
[...]
90+
musl-1.1.10 $ make
91+
[...]
92+
musl-1.1.10 $ make install
93+
[...]
94+
musl-1.1.10 $ cd ..
95+
$ du -h musldist/lib/libc.a
96+
2.2M musldist/lib/libc.a
97+
$
98+
$ # Build libunwind.a
99+
$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz
100+
$ tar xf llvm-3.6.1.src.tar.xz
101+
$ cd llvm-3.6.1.src/projects/
102+
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi
103+
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind
104+
llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt
105+
llvm-3.6.1.src/projects $ mkdir libunwind/build
106+
llvm-3.6.1.src/projects $ cd libunwind/build
107+
llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
108+
llvm-3.6.1.src/projects/libunwind/build $ make
109+
llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
110+
llvm-3.6.1.src/projects/libunwind/build $ cd cd ../../../../
111+
$ du -h musldist/lib/libunwind.a
112+
164K musldist/lib/libunwind.a
113+
$
114+
$ # Build musl-enabled rust
115+
$ git clone https://github.com/rust-lang/rust.git muslrust
116+
$ cd muslrust
117+
muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
118+
muslrust $ make
119+
muslrust $ make install
120+
muslrust $ cd ..
121+
$ du -h musldist/bin/rustc
122+
12K musldist/bin/rustc
123+
```
124+
125+
You now have a build of a `musl`-enabled Rust! Because we've installed it to a
126+
custom prefix we need to make sure our system can the binaries and appropriate
127+
libraries when we try and run it:
128+
129+
```text
130+
$ export PATH=$PREFIX/bin:$PATH
131+
$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
132+
```
133+
134+
Let's try it out!
135+
136+
```text
137+
$ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
138+
$ rustc --target=x86_64-unknown-linux-musl example.rs
139+
$ ldd example
140+
not a dynamic executable
141+
$ ./example
142+
hi!
143+
thread '<main>' panicked at 'failed', example.rs:1
144+
```
145+
146+
Success! This binary can be copied to almost any Linux machine with the same
147+
machine architecture and run without issues.
148+
149+
`cargo build` also permits the `--target` option so you should be able to build
150+
your crates as normal. However, you may need to recompile your native libraries
151+
against `musl` before they can be linked against.

src/doc/trpl/link-args.md

-25
This file was deleted.

src/doc/trpl/while-loops.md

+18
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,24 @@ for x in 0..10 {
8888
}
8989
```
9090

91+
You may also encounter situations where you have nested loops and need to
92+
specify which one your `break` or `continue` statement is for. Like most
93+
other languages, by default a `break` or `continue` will apply to innermost
94+
loop. In a sitation where you would like to a `break` or `continue` for one
95+
of the outer loops, you can use labels to specify which loop the `break` or
96+
`continue` statement applies to. This will only print when both `x` and `y` are
97+
odd:
98+
99+
```rust
100+
'outer: for x in 0..10 {
101+
'inner: for y in 0..10 {
102+
if x % 2 == 0 { continue 'outer; } // continues the loop over x
103+
if y % 2 == 0 { continue 'inner; } // continues the loop over y
104+
println!("x: {}, y: {}", x, y);
105+
}
106+
}
107+
```
108+
91109
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
92110

93111
[for]: for-loops.html

src/libcore/ops.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,10 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
10571057
/// The `Deref` trait is used to specify the functionality of dereferencing
10581058
/// operations like `*v`.
10591059
///
1060+
/// `Deref` also enables ['`Deref` coercions'][coercions].
1061+
///
1062+
/// [coercions]: ../../book/deref-coercions.html
1063+
///
10601064
/// # Examples
10611065
///
10621066
/// 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 {
11111115
/// The `DerefMut` trait is used to specify the functionality of dereferencing
11121116
/// mutably like `*v = 1;`
11131117
///
1118+
/// `DerefMut` also enables ['`Deref` coercions'][coercions].
1119+
///
1120+
/// [coercions]: ../../book/deref-coercions.html
1121+
///
11141122
/// # Examples
11151123
///
11161124
/// A struct with a single field which is modifiable via dereferencing the

src/librustc/middle/const_eval.rs

+3
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
967967
Some(def::DefVariant(enum_def, variant_def, _)) => {
968968
(lookup_variant_by_id(tcx, enum_def, variant_def), None)
969969
}
970+
Some(def::DefStruct(_)) => {
971+
return Ok(ConstVal::Struct(e.id))
972+
}
970973
_ => (None, None)
971974
};
972975
let const_expr = match const_expr {

src/librustc_back/target/bitrig_base.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ pub fn opts() -> TargetOptions {
2020
linker_is_gnu: true,
2121
has_rpath: true,
2222
position_independent_executables: true,
23-
pre_link_args: vec!(
24-
),
25-
archive_format: "bsd".to_string(),
23+
archive_format: "gnu".to_string(),
2624

2725
.. Default::default()
2826
}

src/librustc_borrowck/diagnostics.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,56 @@
1212

1313
register_long_diagnostics! {
1414

15+
E0373: r##"
16+
This error occurs when an attempt is made to use data captured by a closure,
17+
when that data may no longer exist. It's most commonly seen when attempting to
18+
return a closure:
19+
20+
```
21+
fn foo() -> Box<Fn(u32) -> u32> {
22+
let x = 0u32;
23+
Box::new(|y| x + y)
24+
}
25+
```
26+
27+
Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
28+
closed-over data by reference. This means that once `foo()` returns, `x` no
29+
longer exists. An attempt to access `x` within the closure would thus be unsafe.
30+
31+
Another situation where this might be encountered is when spawning threads:
32+
33+
```
34+
fn foo() {
35+
let x = 0u32;
36+
let y = 1u32;
37+
38+
let thr = std::thread::spawn(|| {
39+
x + y
40+
});
41+
}
42+
```
43+
44+
Since our new thread runs in parallel, the stack frame containing `x` and `y`
45+
may well have disappeared by the time we try to use them. Even if we call
46+
`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
47+
stack frame won't disappear), we will not succeed: the compiler cannot prove
48+
that this behaviour is safe, and so won't let us do it.
49+
50+
The solution to this problem is usually to switch to using a `move` closure.
51+
This approach moves (or copies, where possible) data into the closure, rather
52+
than taking references to it. For example:
53+
54+
```
55+
fn foo() -> Box<Fn(u32) -> u32> {
56+
let x = 0u32;
57+
Box::new(move |y| x + y)
58+
}
59+
```
60+
61+
Now that the closure has its own copy of the data, there's no need to worry
62+
about safety.
63+
"##,
64+
1565
E0381: r##"
1666
It is not allowed to use or capture an uninitialized variable. For example:
1767
@@ -28,7 +78,6 @@ used.
2878
}
2979

3080
register_diagnostics! {
31-
E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn
3281
E0382, // use of partially/collaterally moved value
3382
E0383, // partial reinitialization of uninitialized structure
3483
E0384, // reassignment of immutable variable

src/librustc_resolve/diagnostics.rs

+51-2
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,57 @@ use something_which_doesnt_exist;
426426
Please verify you didn't misspell the import's name.
427427
"##,
428428

429+
E0437: r##"
430+
Trait impls can only implement associated types that are members of the trait in
431+
question. This error indicates that you attempted to implement an associated
432+
type whose name does not match the name of any associated type in the trait.
433+
434+
Here is an example that demonstrates the error:
435+
436+
```
437+
trait Foo {}
438+
439+
impl Foo for i32 {
440+
type Bar = bool;
441+
}
442+
```
443+
444+
The solution to this problem is to remove the extraneous associated type:
445+
446+
```
447+
trait Foo {}
448+
449+
impl Foo for i32 {}
450+
```
451+
"##,
452+
453+
E0438: r##"
454+
Trait impls can only implement associated constants that are members of the
455+
trait in question. This error indicates that you attempted to implement an
456+
associated constant whose name does not match the name of any associated
457+
constant in the trait.
458+
459+
Here is an example that demonstrates the error:
460+
461+
```
462+
#![feature(associated_consts)]
463+
464+
trait Foo {}
465+
466+
impl Foo for i32 {
467+
const BAR: bool = true;
468+
}
469+
```
470+
471+
The solution to this problem is to remove the extraneous associated constant:
472+
473+
```
474+
trait Foo {}
475+
476+
impl Foo for i32 {}
477+
```
478+
"##
479+
429480
}
430481

431482
register_diagnostics! {
@@ -468,6 +519,4 @@ register_diagnostics! {
468519
E0432, // unresolved import
469520
E0434, // can't capture dynamic environment in a fn item
470521
E0435, // attempt to use a non-constant value in a constant
471-
E0437, // type is not a member of trait
472-
E0438, // const is not a member of trait
473522
}

0 commit comments

Comments
 (0)