diff options
| author | Steve Klabnik <steve@steveklabnik.com> | 2017-02-15 20:27:58 -0500 |
|---|---|---|
| committer | Steve Klabnik <steve@steveklabnik.com> | 2017-02-21 21:12:55 -0500 |
| commit | 6fb2545f77b722a8cde5cb87b289cd8b87643a7a (patch) | |
| tree | 5fb9f767e37887c746d1a67d60a1a094f2814b7f /src/doc | |
| parent | aba4bf60f5129af31ef7271e3499dadaadd2071d (diff) | |
| download | rust-6fb2545f77b722a8cde5cb87b289cd8b87643a7a.tar.gz rust-6fb2545f77b722a8cde5cb87b289cd8b87643a7a.zip | |
TRPL Nightly -> Unstable Book
Port the chapters from TRPL's "Nightly Rust" section to the Unstable Book, and remove it from TRPL.
Diffstat (limited to 'src/doc')
104 files changed, 1261 insertions, 1093 deletions
diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md index 74b9b7fa5b2..c3763cdf9d6 100644 --- a/src/doc/book/src/SUMMARY.md +++ b/src/doc/book/src/SUMMARY.md @@ -55,18 +55,6 @@ * [Release Channels](release-channels.md) * [Using Rust without the standard library](using-rust-without-the-standard-library.md) * [Procedural Macros (and custom derive)](procedural-macros.md) -* [Nightly Rust](nightly-rust.md) - * [Compiler Plugins](compiler-plugins.md) - * [Inline Assembly](inline-assembly.md) - * [No stdlib](no-stdlib.md) - * [Intrinsics](intrinsics.md) - * [Lang items](lang-items.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) - * [Associated Constants](associated-constants.md) - * [Custom Allocators](custom-allocators.md) * [Glossary](glossary.md) * [Syntax Index](syntax-index.md) * [Bibliography](bibliography.md) diff --git a/src/doc/book/src/advanced-linking.md b/src/doc/book/src/advanced-linking.md deleted file mode 100644 index a882d6d2ebe..00000000000 --- a/src/doc/book/src/advanced-linking.md +++ /dev/null @@ -1,145 +0,0 @@ -# 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: - -```rust,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 contains all -required libraries and so doesn'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 Rust everywhere. By contrast, native libraries -(e.g. `libc` and `libm`) are usually dynamically linked, but it is possible to -change this and statically link them as well. - -Linking is a very platform-dependent topic, and static linking may not even be -possible on some platforms! 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`](http://www.musl-libc.org). 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 -$ curl -O 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 -$ curl -O http://llvm.org/releases/3.7.0/llvm-3.7.0.src.tar.xz -$ tar xf llvm-3.7.0.src.tar.xz -$ cd llvm-3.7.0.src/projects/ -llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libunwind-3.7.0.src.tar.xz | tar xJf - -llvm-3.7.0.src/projects $ mv libunwind-3.7.0.src libunwind -llvm-3.7.0.src/projects $ mkdir libunwind/build -llvm-3.7.0.src/projects $ cd libunwind/build -llvm-3.7.0.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 .. -llvm-3.7.0.src/projects/libunwind/build $ make -llvm-3.7.0.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/ -llvm-3.7.0.src/projects/libunwind/build $ 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 find 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/book/src/associated-constants.md b/src/doc/book/src/associated-constants.md deleted file mode 100644 index 61bad3d3948..00000000000 --- a/src/doc/book/src/associated-constants.md +++ /dev/null @@ -1,79 +0,0 @@ -# Associated Constants - -With the `associated_consts` feature, you can define constants like this: - -```rust -#![feature(associated_consts)] - -trait Foo { - const ID: i32; -} - -impl Foo for i32 { - const ID: i32 = 1; -} - -fn main() { - assert_eq!(1, i32::ID); -} -``` - -Any implementor of `Foo` will have to define `ID`. Without the definition: - -```rust,ignore -#![feature(associated_consts)] - -trait Foo { - const ID: i32; -} - -impl Foo for i32 { -} -``` - -gives - -```text -error: not all trait items implemented, missing: `ID` [E0046] - impl Foo for i32 { - } -``` - -A default value can be implemented as well: - -```rust -#![feature(associated_consts)] - -trait Foo { - const ID: i32 = 1; -} - -impl Foo for i32 { -} - -impl Foo for i64 { - const ID: i32 = 5; -} - -fn main() { - assert_eq!(1, i32::ID); - assert_eq!(5, i64::ID); -} -``` - -As you can see, when implementing `Foo`, you can leave it unimplemented, as -with `i32`. It will then use the default value. But, as in `i64`, we can also -add our own definition. - -Associated constants don’t have to be associated with a trait. An `impl` block -for a `struct` or an `enum` works fine too: - -```rust -#![feature(associated_consts)] - -struct Foo; - -impl Foo { - const FOO: u32 = 3; -} -``` diff --git a/src/doc/book/src/box-syntax-and-patterns.md b/src/doc/book/src/box-syntax-and-patterns.md deleted file mode 100644 index f03e881f474..00000000000 --- a/src/doc/book/src/box-syntax-and-patterns.md +++ /dev/null @@ -1,100 +0,0 @@ -# Box Syntax and Patterns - -Currently the only stable way to create a `Box` is via the `Box::new` method. -Also it is not possible in stable Rust to destructure a `Box` in a match -pattern. The unstable `box` keyword can be used to both create and destructure -a `Box`. An example usage would be: - -```rust -#![feature(box_syntax, box_patterns)] - -fn main() { - let b = Some(box 5); - match b { - Some(box n) if n < 0 => { - println!("Box contains negative number {}", n); - }, - Some(box n) if n >= 0 => { - println!("Box contains non-negative number {}", n); - }, - None => { - println!("No box"); - }, - _ => unreachable!() - } -} -``` - -Note that these features are currently hidden behind the `box_syntax` (box -creation) and `box_patterns` (destructuring and pattern matching) gates -because the syntax may still change in the future. - -# Returning Pointers - -In many languages with pointers, you'd return a pointer from a function -so as to avoid copying a large data structure. For example: - -```rust -struct BigStruct { - one: i32, - two: i32, - // Etc. - one_hundred: i32, -} - -fn foo(x: Box<BigStruct>) -> Box<BigStruct> { - Box::new(*x) -} - -fn main() { - let x = Box::new(BigStruct { - one: 1, - two: 2, - one_hundred: 100, - }); - - let y = foo(x); -} -``` - -The idea is that by passing around a box, you're only copying a pointer, rather -than the hundred `i32`s that make up the `BigStruct`. - -This is an antipattern in Rust. Instead, write this: - -```rust -#![feature(box_syntax)] - -struct BigStruct { - one: i32, - two: i32, - // Etc. - one_hundred: i32, -} - -fn foo(x: Box<BigStruct>) -> BigStruct { - *x -} - -fn main() { - let x = Box::new(BigStruct { - one: 1, - two: 2, - one_hundred: 100, - }); - - let y: Box<BigStruct> = box foo(x); -} -``` - -This gives you flexibility without sacrificing performance. - -You may think that this gives us terrible performance: return a value and then -immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is -smarter than that. There is no copy in this code. `main` allocates enough room -for the `box`, passes a pointer to that memory into `foo` as `x`, and then -`foo` writes the value straight into the `Box<T>`. - -This is important enough that it bears repeating: pointers are not for -optimizing returning values from your code. Allow the caller to choose how they -want to use your output. diff --git a/src/doc/book/src/custom-allocators.md b/src/doc/book/src/custom-allocators.md deleted file mode 100644 index 154b5f0f4e2..00000000000 --- a/src/doc/book/src/custom-allocators.md +++ /dev/null @@ -1,171 +0,0 @@ -# Custom Allocators - -Allocating memory isn't always the easiest thing to do, and while Rust generally -takes care of this by default it often becomes necessary to customize how -allocation occurs. The compiler and standard library currently allow switching -out the default global allocator in use at compile time. The design is currently -spelled out in [RFC 1183][rfc] but this will walk you through how to get your -own allocator up and running. - -[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1183-swap-out-jemalloc.md - -# Default Allocator - -The compiler currently ships two default allocators: `alloc_system` and -`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators -are normal Rust crates and contain an implementation of the routines to -allocate and deallocate memory. The standard library is not compiled assuming -either one, and the compiler will decide which allocator is in use at -compile-time depending on the type of output artifact being produced. - -Binaries generated by the compiler will use `alloc_jemalloc` by default (where -available). In this situation the compiler "controls the world" in the sense of -it has power over the final link. Primarily this means that the allocator -decision can be left up the compiler. - -Dynamic and static libraries, however, will use `alloc_system` by default. Here -Rust is typically a 'guest' in another application or another world where it -cannot authoritatively decide what allocator is in use. As a result it resorts -back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing -memory. - -# Switching Allocators - -Although the compiler's default choices may work most of the time, it's often -necessary to tweak certain aspects. Overriding the compiler's decision about -which allocator is in use is done simply by linking to the desired allocator: - -```rust,no_run -#![feature(alloc_system)] - -extern crate alloc_system; - -fn main() { - let a = Box::new(4); // Allocates from the system allocator. - println!("{}", a); -} -``` - -In this example the binary generated will not link to jemalloc by default but -instead use the system allocator. Conversely to generate a dynamic library which -uses jemalloc by default one would write: - -```rust,ignore -#![feature(alloc_jemalloc)] -#![crate_type = "dylib"] - -extern crate alloc_jemalloc; - -pub fn foo() { - let a = Box::new(4); // Allocates from jemalloc. - println!("{}", a); -} -# fn main() {} -``` - -# Writing a custom allocator - -Sometimes even the choices of jemalloc vs the system allocator aren't enough and -an entirely new custom allocator is required. In this you'll write your own -crate which implements the allocator API (e.g. the same as `alloc_system` or -`alloc_jemalloc`). As an example, let's take a look at a simplified and -annotated version of `alloc_system` - -```rust,no_run -# // Only needed for rustdoc --test down below. -# #![feature(lang_items)] -// The compiler needs to be instructed that this crate is an allocator in order -// to realize that when this is linked in another allocator like jemalloc should -// not be linked in. -#![feature(allocator)] -#![allocator] - -// Allocators are not allowed to depend on the standard library which in turn -// requires an allocator in order to avoid circular dependencies. This crate, -// however, can use all of libcore. -#![no_std] - -// Let's give a unique name to our custom allocator: -#![crate_name = "my_allocator"] -#![crate_type = "rlib"] - -// Our system allocator will use the in-tree libc crate for FFI bindings. Note -// that currently the external (crates.io) libc cannot be used because it links -// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why -// this specifically requires the in-tree version. -#![feature(libc)] -extern crate libc; - -// Listed below are the five allocation functions currently required by custom -// allocators. Their signatures and symbol names are not currently typechecked -// by the compiler, but this is a future extension and are required to match -// what is found below. -// -// Note that the standard `malloc` and `realloc` functions do not provide a way -// to communicate alignment so this implementation would need to be improved -// with respect to alignment in that aspect. - -#[no_mangle] -pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 { - unsafe { libc::malloc(size as libc::size_t) as *mut u8 } -} - -#[no_mangle] -pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { - unsafe { libc::free(ptr as *mut libc::c_void) } -} - -#[no_mangle] -pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize, - _align: usize) -> *mut u8 { - unsafe { - libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 - } -} - -#[no_mangle] -pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize, - _size: usize, _align: usize) -> usize { - old_size // This api is not supported by libc. -} - -#[no_mangle] -pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize { - size -} - -# // Only needed to get rustdoc to test this: -# fn main() {} -# #[lang = "panic_fmt"] fn panic_fmt() {} -# #[lang = "eh_personality"] fn eh_personality() {} -# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} -# #[no_mangle] pub extern fn rust_eh_register_frames () {} -# #[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` - -After we compile this crate, it can be used as follows: - -```rust,ignore -extern crate my_allocator; - -fn main() { - let a = Box::new(8); // Allocates memory via our custom allocator crate. - println!("{}", a); -} -``` - -# Custom allocator limitations - -There are a few restrictions when working with custom allocators which may cause -compiler errors: - -* Any one artifact may only be linked to at most one allocator. Binaries, - dylibs, and staticlibs must link to exactly one allocator, and if none have - been explicitly chosen the compiler will choose one. On the other hand rlibs - do not need to link to an allocator (but still can). - -* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the - `liballoc` crate currently) and an `#[allocator]` crate cannot transitively - depend on a crate which needs an allocator (e.g. circular dependencies are not - allowed). This basically means that allocators must restrict themselves to - libcore currently. diff --git a/src/doc/book/src/inline-assembly.md b/src/doc/book/src/inline-assembly.md deleted file mode 100644 index 4262289acbf..00000000000 --- a/src/doc/book/src/inline-assembly.md +++ /dev/null @@ -1,184 +0,0 @@ -# Inline Assembly - -For extremely low-level manipulations and performance reasons, one -might wish to control the CPU directly. Rust supports using inline -assembly to do this via the `asm!` macro. - -```rust,ignore -asm!(assembly template - : output operands - : input operands - : clobbers - : options - ); -``` - -Any use of `asm` is feature gated (requires `#![feature(asm)]` on the -crate to allow) and of course requires an `unsafe` block. - -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. - -## Assembly template - -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) - -```rust -#![feature(asm)] - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn foo() { - unsafe { - asm!("NOP"); - } -} - -// Other platforms: -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn foo() { /* ... */ } - -fn main() { - // ... - foo(); - // ... -} -``` - -(The `feature(asm)` and `#[cfg]`s are omitted from now on.) - -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: - -```rust -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -asm!("xor %eax, %eax" - : - : - : "eax" - ); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -Whitespace also doesn't matter: - -```rust -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -asm!("xor %eax, %eax" ::: "eax"); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -## Operands - -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable lvalues, or not yet assigned: - -```rust -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn add(a: i32, b: i32) -> i32 { - let c: i32; - unsafe { - asm!("add $2, $0" - : "=r"(c) - : "0"(a), "r"(b) - ); - } - c -} -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn add(a: i32, b: i32) -> i32 { a + b } - -fn main() { - assert_eq!(add(3, 14159), 14162) -} -``` - -If you would like to use real operands in this position, however, -you are required to put curly braces `{}` around the register that -you want, and you are required to put the specific size of the -operand. This is useful for very low level programming, where -which register you use is important: - -```rust -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# unsafe fn read_byte_in(port: u16) -> u8 { -let result: u8; -asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port)); -result -# } -``` - -## Clobbers - -Some instructions modify registers which might otherwise have held -different values so we use the clobbers list to indicate to the -compiler not to assume any values loaded into those registers will -stay valid. - -```rust -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -// Put the value 0x200 in eax: -asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -Input and output registers need not be listed since that information -is already communicated by the given constraints. Otherwise, any other -registers used either implicitly or explicitly should be listed. - -If the assembly changes the condition code register `cc` should be -specified as one of the clobbers. Similarly, if the assembly modifies -memory, `memory` should also be specified. - -## Options - -The last section, `options` is specific to Rust. The format is comma -separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to -specify some extra info about the inline assembly: - -Current valid options are: - -1. *volatile* - specifying this is analogous to - `__asm__ __volatile__ (...)` in gcc/clang. -2. *alignstack* - certain instructions expect the stack to be - aligned a certain way (i.e. SSE) and specifying this indicates to - the compiler to insert its usual stack alignment code -3. *intel* - use intel syntax instead of the default AT&T. - -```rust -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { -let result: i32; -unsafe { - asm!("mov eax, 2" : "={eax}"(result) : : : "intel") -} -println!("eax is currently {}", result); -# } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` - -## More Information - -The current implementation of the `asm!` macro is a direct binding to [LLVM's -inline assembler expressions][llvm-docs], so be sure to check out [their -documentation as well][llvm-docs] for more information about clobbers, -constraints, etc. - -[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions diff --git a/src/doc/book/src/intrinsics.md b/src/doc/book/src/intrinsics.md deleted file mode 100644 index e1edce3e80f..00000000000 --- a/src/doc/book/src/intrinsics.md +++ /dev/null @@ -1,25 +0,0 @@ -# Intrinsics - -> **Note**: intrinsics will forever have an unstable interface, it is -> recommended to use the stable interfaces of libcore rather than intrinsics -> directly. - -These are imported as if they were FFI functions, with the special -`rust-intrinsic` ABI. For example, if one was in a freestanding -context, but wished to be able to `transmute` between types, and -perform efficient pointer arithmetic, one would import those functions -via a declaration like - -```rust -#![feature(intrinsics)] -# fn main() {} - -extern "rust-intrinsic" { - fn transmute<T, U>(x: T) -> U; - - fn offset<T>(dst: *const T, offset: isize) -> *const T; -} -``` - -As with any other FFI functions, these are always `unsafe` to call. - diff --git a/src/doc/book/src/lang-items.md b/src/doc/book/src/lang-items.md deleted file mode 100644 index 9bd64d38179..00000000000 --- a/src/doc/book/src/lang-items.md +++ /dev/null @@ -1,84 +0,0 @@ -# Lang items - -> **Note**: lang items are often provided by crates in the Rust distribution, -> and lang items themselves have an unstable interface. It is recommended to use -> officially distributed crates instead of defining your own lang items. - -The `rustc` compiler has certain pluggable operations, that is, -functionality that isn't hard-coded into the language, but is -implemented in libraries, with a special marker to tell the compiler -it exists. The marker is the attribute `#[lang = "..."]` and there are -various different values of `...`, i.e. various different 'lang -items'. - -For example, `Box` pointers require two lang items, one for allocation -and one for deallocation. A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: - -```rust,ignore -#![feature(lang_items, box_syntax, start, libc, core_intrinsics)] -#![no_std] -use core::intrinsics; - -extern crate libc; - -#[lang = "owned_box"] -pub struct Box<T>(*mut T); - -#[lang = "exchange_malloc"] -unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; - - // Check if `malloc` failed: - if p as usize == 0 { - intrinsics::abort(); - } - - p -} - -#[lang = "exchange_free"] -unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { - libc::free(ptr as *mut libc::c_void) -} - -#[lang = "box_free"] -unsafe fn box_free<T: ?Sized>(ptr: *mut T) { - deallocate(ptr as *mut u8, ::core::mem::size_of_val(&*ptr), ::core::mem::align_of_val(&*ptr)); -} - -#[start] -fn main(argc: isize, argv: *const *const u8) -> isize { - let x = box 1; - - 0 -} - -#[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } } -# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} -# #[no_mangle] pub extern fn rust_eh_register_frames () {} -# #[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` - -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. - -Other features provided by lang items include: - -- overloadable operators via traits: the traits corresponding to the - `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all - marked with lang items; those specific four are `eq`, `ord`, - `deref`, and `add` respectively. -- stack unwinding and general failure; the `eh_personality`, - `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items. -- the traits in `std::marker` used to indicate types of - various kinds; lang items `send`, `sync` and `copy`. -- the marker types and variance indicators found in - `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, etc. - -Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define functions for `exchange_malloc` -and `exchange_free`. `rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. diff --git a/src/doc/book/src/nightly-rust.md b/src/doc/book/src/nightly-rust.md deleted file mode 100644 index 5dfaa9e0fa8..00000000000 --- a/src/doc/book/src/nightly-rust.md +++ /dev/null @@ -1,100 +0,0 @@ -# Nightly Rust - -Rust provides three distribution channels for Rust: nightly, beta, and stable. -Unstable features are only available on nightly Rust. For more details on this -process, see [Stability as a deliverable][stability]. - -[stability]: http://blog.rust-lang.org/2014/10/30/Stability.html - -To install nightly Rust, you can use [rustup.rs][rustup]: - -[rustup]: https://rustup.rs - -```bash -$ curl https://sh.rustup.rs -sSf | sh -$ rustup install nightly -``` - -If you're concerned about the [potential insecurity][insecurity] of using `curl -| sh`, please keep reading and see our disclaimer below. And feel free to -use a two-step version of the installation and examine our installation script: - -```bash -$ curl https://sh.rustup.rs -sSf -o rustup.sh -$ sh rustup.sh -$ rustup install nightly -``` - -[insecurity]: http://curlpipesh.tumblr.com - -If you're on Windows, please download the [rustup installer][installer] -and run it. - -[installer]: https://win.rustup.rs - -## Uninstalling - -If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay. -Not every programming language is great for everyone. Just run the uninstall -command: - -```bash -$ rustup self uninstall -``` - -Some people, and somewhat rightfully so, get very upset when we tell you to -`curl | sh`. Basically, when you do this, you are trusting that the good -people who maintain Rust aren't going to hack your computer and do bad things. -That's a good instinct! If you're one of those people, please check out the -documentation on [building Rust from Source][from-source], or [the official -binary downloads][install-page]. - -[from-source]: https://github.com/rust-lang/rust#building-from-source -[install-page]: https://www.rust-lang.org/install.html - -Oh, we should also mention the officially supported platforms: - -* Windows (7+) -* Linux (2.6.18 or later, various distributions), x86 and x86-64 -* OSX 10.7 (Lion) or greater, x86 and x86-64 - -We extensively test Rust on these platforms, and a few others, too, like -Android. But these are the ones most likely to work, as they have the most -testing. - -Finally, a comment about Windows. Rust considers Windows to be a first-class -platform upon release, but if we're honest, the Windows experience isn't as -integrated as the Linux/OS X experience is. We're working on it! If anything -does not work, it is a bug. Please let us know if that happens. Each and every -commit is tested against Windows like any other platform. - -If you've got Rust installed, you can open up a shell, and type this: - -```bash -$ rustc --version -``` - -You should see the version number, commit hash, commit date and build date: - -```bash -rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06) -``` - -If you did, Rust has been installed successfully! Congrats! - -This installer also installs a copy of the documentation locally, so you can -read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. -On Windows, it's in a `share/doc` directory, inside wherever you installed Rust -to. - -If not, there are a number of places where you can get help. The easiest is -[the #rust IRC channel on irc.mozilla.org][irc], which you can access through -[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans -(a silly nickname we call ourselves), and we can help you out. Other great -resources include [the users forum][users], and [Stack Overflow][stackoverflow]. - -[irc]: irc://irc.mozilla.org/#rust -[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust -[users]: https://users.rust-lang.org/ -[stackoverflow]: http://stackoverflow.com/questions/tagged/rust - diff --git a/src/doc/book/src/no-stdlib.md b/src/doc/book/src/no-stdlib.md deleted file mode 100644 index dcb0fbc8005..00000000000 --- a/src/doc/book/src/no-stdlib.md +++ /dev/null @@ -1,145 +0,0 @@ -# No stdlib - -Rust’s standard library provides a lot of useful functionality, but assumes -support for various features of its host system: threads, networking, heap -allocation, and others. There are systems that do not have these features, -however, and Rust can work with those too! To do so, we tell Rust that we -don’t want to use the standard library via an attribute: `#![no_std]`. - -> Note: This feature is technically stable, but there are some caveats. For -> one, you can build a `#![no_std]` _library_ on stable, but not a _binary_. -> For details on libraries without the standard library, see [the chapter on -> `#![no_std]`](using-rust-without-the-standard-library.html) - -Obviously there's more to life than just libraries: one can use -`#[no_std]` with an executable. - -### Using libc - -In order to build a `#[no_std]` executable we will need libc as a dependency. We can specify -this using our `Cargo.toml` file: - -```toml -[dependencies] -libc = { version = "0.2.14", default-features = false } -``` - -Note that the default features have been disabled. This is a critical step - -**the default features of libc include the standard library and so must be -disabled.** - -### Writing an executable without stdlib - -Controlling the entry point is possible in two ways: the `#[start]` attribute, -or overriding the default shim for the C `main` function with your own. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: - -```rust,ignore -#![feature(lang_items, core_intrinsics)] -#![feature(start)] -#![no_std] -use core::intrinsics; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - -#[lang = "panic_fmt"] -#[no_mangle] -pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, - _file: &'static str, - _line: u32) -> ! { - unsafe { intrinsics::abort() } -} -``` - -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: - -```rust,ignore -#![feature(lang_items, core_intrinsics)] -#![feature(start)] -#![no_std] -#![no_main] -use core::intrinsics; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - -#[lang = "panic_fmt"] -#[no_mangle] -pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, - _file: &'static str, - _line: u32) -> ! { - unsafe { intrinsics::abort() } -} -``` - -## More about the language items - -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. - -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. - -[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs - -The second function, `rust_begin_panic`, is also used by the failure mechanisms of the -compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_fmt`, the symbol name is -`rust_begin_panic`. - -A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume` -flag is set in the options of the compilation target. It allows customizing the -process of resuming unwind at the end of the landing pads. The language item's name -is `eh_unwind_resume`. diff --git a/src/doc/book/src/slice-patterns.md b/src/doc/book/src/slice-patterns.md deleted file mode 100644 index 3f7398dde5e..00000000000 --- a/src/doc/book/src/slice-patterns.md +++ /dev/null @@ -1,42 +0,0 @@ -# Slice patterns - -If you want to match against a slice or array, you can use `&` with the -`slice_patterns` feature: - -```rust -#![feature(slice_patterns)] - -fn main() { - let v = vec!["match_this", "1"]; - - match &v[..] { - &["match_this", second] => println!("The second element is {}", second), - _ => {}, - } -} -``` - -The `advanced_slice_patterns` gate lets you use `..` to indicate any number of -elements inside a pattern matching a slice. This wildcard can only be used once -for a given array. If there's an identifier before the `..`, the result of the -slice will be bound to that name. For example: - -```rust -#![feature(advanced_slice_patterns, slice_patterns)] - -fn is_symmetric(list: &[u32]) -> bool { - match list { - &[] | &[_] => true, - &[x, ref inside.., y] if x == y => is_symmetric(inside), - _ => false - } -} - -fn main() { - let sym = &[0, 1, 4, 2, 4, 1, 0]; - assert!(is_symmetric(sym)); - - let not_sym = &[0, 1, 7, 2, 4, 1, 0]; - assert!(!is_symmetric(not_sym)); -} -``` diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index b0bd28828fa..ee8ae9a9839 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -1,6 +1,9 @@ [The Unstable Book](the-unstable-book.md) - [asm](asm.md) +- [alloc_system](alloc-system.md) +- [alloc_jemalloc](alloc-jemalloc.md) +- [test](test.md) - [concat_idents](concat-idents.md) - [link_args](link-args.md) - [log_syntax](log-syntax.md) diff --git a/src/doc/unstable-book/src/abi-msp430-interrupt.md b/src/doc/unstable-book/src/abi-msp430-interrupt.md index 4d925e73686..9b2c7f29897 100644 --- a/src/doc/unstable-book/src/abi-msp430-interrupt.md +++ b/src/doc/unstable-book/src/abi-msp430-interrupt.md @@ -3,3 +3,5 @@ The tracking issue for this feature is: [#38487] [#38487]: https://github.com/rust-lang/rust/issues/38487 + +------------------------ diff --git a/src/doc/unstable-book/src/abi-ptx.md b/src/doc/unstable-book/src/abi-ptx.md index 6695cb0f33c..9c1b8868ace 100644 --- a/src/doc/unstable-book/src/abi-ptx.md +++ b/src/doc/unstable-book/src/abi-ptx.md @@ -2,3 +2,4 @@ The tracking issue for this feature is: None. +------------------------ diff --git a/src/doc/unstable-book/src/abi-sysv64.md b/src/doc/unstable-book/src/abi-sysv64.md index 2415c8b8d19..27f61d56342 100644 --- a/src/doc/unstable-book/src/abi-sysv64.md +++ b/src/doc/unstable-book/src/abi-sysv64.md @@ -4,5 +4,4 @@ The tracking issue for this feature is: [#36167] [#36167]: https://github.com/rust-lang/rust/issues/36167 - - +------------------------ diff --git a/src/doc/unstable-book/src/abi-unadjusted.md b/src/doc/unstable-book/src/abi-unadjusted.md index 2a941d95632..2e3113abdbf 100644 --- a/src/doc/unstable-book/src/abi-unadjusted.md +++ b/src/doc/unstable-book/src/abi-unadjusted.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: none. +------------------------ + diff --git a/src/doc/unstable-book/src/abi-vectorcall.md b/src/doc/unstable-book/src/abi-vectorcall.md index da9d830c4dc..3e36b1569fd 100644 --- a/src/doc/unstable-book/src/abi-vectorcall.md +++ b/src/doc/unstable-book/src/abi-vectorcall.md @@ -2,4 +2,6 @@ The tracking issue for this feature is: none. +------------------------ + diff --git a/src/doc/unstable-book/src/advanced-slice-patterns.md b/src/doc/unstable-book/src/advanced-slice-patterns.md index b0eee4bc0b8..30d22ca8208 100644 --- a/src/doc/unstable-book/src/advanced-slice-patterns.md +++ b/src/doc/unstable-book/src/advanced-slice-patterns.md @@ -4,5 +4,32 @@ The tracking issue for this feature is: [#23121] [#23121]: https://github.com/rust-lang/rust/issues/23121 +See also [`slice_patterns`](slice-patterns.html). +------------------------ + +The `advanced_slice_patterns` gate lets you use `..` to indicate any number of +elements inside a pattern matching a slice. This wildcard can only be used once +for a given array. If there's an identifier before the `..`, the result of the +slice will be bound to that name. For example: + +```rust +#![feature(advanced_slice_patterns, slice_patterns)] + +fn is_symmetric(list: &[u32]) -> bool { + match list { + &[] | &[_] => true, + &[x, ref inside.., y] if x == y => is_symmetric(inside), + _ => false + } +} + +fn main() { + let sym = &[0, 1, 4, 2, 4, 1, 0]; + assert!(is_symmetric(sym)); + + let not_sym = &[0, 1, 7, 2, 4, 1, 0]; + assert!(!is_symmetric(not_sym)); +} +``` diff --git a/src/doc/unstable-book/src/alloc-jemalloc.md b/src/doc/unstable-book/src/alloc-jemalloc.md new file mode 100644 index 00000000000..47c44ddc374 --- /dev/null +++ b/src/doc/unstable-book/src/alloc-jemalloc.md @@ -0,0 +1,62 @@ +# `alloc_jemalloc` + +The tracking issue for this feature is: [#33082] + +[#33082]: https://github.com/rust-lang/rust/issues/33082 + +See also [`alloc_system`](alloc-system.md). + +------------------------ + +The compiler currently ships two default allocators: `alloc_system` and +`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators +are normal Rust crates and contain an implementation of the routines to +allocate and deallocate memory. The standard library is not compiled assuming +either one, and the compiler will decide which allocator is in use at +compile-time depending on the type of output artifact being produced. + +Binaries generated by the compiler will use `alloc_jemalloc` by default (where +available). In this situation the compiler "controls the world" in the sense of +it has power over the final link. Primarily this means that the allocator +decision can be left up the compiler. + +Dynamic and static libraries, however, will use `alloc_system` by default. Here +Rust is typically a 'guest' in another application or another world where it +cannot authoritatively decide what allocator is in use. As a result it resorts +back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing +memory. + +# Switching Allocators + +Although the compiler's default choices may work most of the time, it's often +necessary to tweak certain aspects. Overriding the compiler's decision about +which allocator is in use is done simply by linking to the desired allocator: + +```rust,no_run +#![feature(alloc_system)] + +extern crate alloc_system; + +fn main() { + let a = Box::new(4); // Allocates from the system allocator. + println!("{}", a); +} +``` + +In this example the binary generated will not link to jemalloc by default but +instead use the system allocator. Conversely to generate a dynamic library which +uses jemalloc by default one would write: + +```rust,ignore +#![feature(alloc_jemalloc)] +#![crate_type = "dylib"] + +extern crate alloc_jemalloc; + +pub fn foo() { + let a = Box::new(4); // Allocates from jemalloc. + println!("{}", a); +} +# fn main() {} +``` + diff --git a/src/doc/unstable-book/src/alloc-system.md b/src/doc/unstable-book/src/alloc-system.md new file mode 100644 index 00000000000..f7d648c3759 --- /dev/null +++ b/src/doc/unstable-book/src/alloc-system.md @@ -0,0 +1,62 @@ +# `alloc_system` + +The tracking issue for this feature is: [#33082] + +[#33082]: https://github.com/rust-lang/rust/issues/33082 + +See also [`alloc_jemalloc`](alloc-jemalloc.md). + +------------------------ + +The compiler currently ships two default allocators: `alloc_system` and +`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators +are normal Rust crates and contain an implementation of the routines to +allocate and deallocate memory. The standard library is not compiled assuming +either one, and the compiler will decide which allocator is in use at +compile-time depending on the type of output artifact being produced. + +Binaries generated by the compiler will use `alloc_jemalloc` by default (where +available). In this situation the compiler "controls the world" in the sense of +it has power over the final link. Primarily this means that the allocator +decision can be left up the compiler. + +Dynamic and static libraries, however, will use `alloc_system` by default. Here +Rust is typically a 'guest' in another application or another world where it +cannot authoritatively decide what allocator is in use. As a result it resorts +back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing +memory. + +# Switching Allocators + +Although the compiler's default choices may work most of the time, it's often +necessary to tweak certain aspects. Overriding the compiler's decision about +which allocator is in use is done simply by linking to the desired allocator: + +```rust,no_run +#![feature(alloc_system)] + +extern crate alloc_system; + +fn main() { + let a = Box::new(4); // Allocates from the system allocator. + println!("{}", a); +} +``` + +In this example the binary generated will not link to jemalloc by default but +instead use the system allocator. Conversely to generate a dynamic library which +uses jemalloc by default one would write: + +```rust,ignore +#![feature(alloc_jemalloc)] +#![crate_type = "dylib"] + +extern crate alloc_jemalloc; + +pub fn foo() { + let a = Box::new(4); // Allocates from jemalloc. + println!("{}", a); +} +# fn main() {} +``` + diff --git a/src/doc/unstable-book/src/allocator.md b/src/doc/unstable-book/src/allocator.md index 777efa217d1..7261641698f 100644 --- a/src/doc/unstable-book/src/allocator.md +++ b/src/doc/unstable-book/src/allocator.md @@ -4,5 +4,111 @@ The tracking issue for this feature is: [#27389] [#27389]: https://github.com/rust-lang/rust/issues/27389 +------------------------ + +Sometimes even the choices of jemalloc vs the system allocator aren't enough and +an entirely new custom allocator is required. In this you'll write your own +crate which implements the allocator API (e.g. the same as `alloc_system` or +`alloc_jemalloc`). As an example, let's take a look at a simplified and +annotated version of `alloc_system` + +```rust,no_run +# // Only needed for rustdoc --test down below. +# #![feature(lang_items)] +// The compiler needs to be instructed that this crate is an allocator in order +// to realize that when this is linked in another allocator like jemalloc should +// not be linked in. +#![feature(allocator)] +#![allocator] + +// Allocators are not allowed to depend on the standard library which in turn +// requires an allocator in order to avoid circular dependencies. This crate, +// however, can use all of libcore. +#![no_std] + +// Let's give a unique name to our custom allocator: +#![crate_name = "my_allocator"] +#![crate_type = "rlib"] + +// Our system allocator will use the in-tree libc crate for FFI bindings. Note +// that currently the external (crates.io) libc cannot be used because it links +// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why +// this specifically requires the in-tree version. +#![feature(libc)] +extern crate libc; + +// Listed below are the five allocation functions currently required by custom +// allocators. Their signatures and symbol names are not currently typechecked +// by the compiler, but this is a future extension and are required to match +// what is found below. +// +// Note that the standard `malloc` and `realloc` functions do not provide a way +// to communicate alignment so this implementation would need to be improved +// with respect to alignment in that aspect. + +#[no_mangle] +pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 { + unsafe { libc::malloc(size as libc::size_t) as *mut u8 } +} + +#[no_mangle] +pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { + unsafe { libc::free(ptr as *mut libc::c_void) } +} + +#[no_mangle] +pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize, + _align: usize) -> *mut u8 { + unsafe { + libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 + } +} + +#[no_mangle] +pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize, + _size: usize, _align: usize) -> usize { + old_size // This api is not supported by libc. +} + +#[no_mangle] +pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize { + size +} + +# // Only needed to get rustdoc to test this: +# fn main() {} +# #[lang = "panic_fmt"] fn panic_fmt() {} +# #[lang = "eh_personality"] fn eh_personality() {} +# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} +# #[no_mangle] pub extern fn rust_eh_register_frames () {} +# #[no_mangle] pub extern fn rust_eh_unregister_frames () {} +``` + +After we compile this crate, it can be used as follows: + +```rust,ignore +extern crate my_allocator; + +fn main() { + let a = Box::new(8); // Allocates memory via our custom allocator crate. + println!("{}", a); +} +``` + +## Custom allocator limitations + +There are a few restrictions when working with custom allocators which may cause +compiler errors: + +* Any one artifact may only be linked to at most one allocator. Binaries, + dylibs, and staticlibs must link to exactly one allocator, and if none have + been explicitly chosen the compiler will choose one. On the other hand rlibs + do not need to link to an allocator (but still can). + +* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the + `liballoc` crate currently) and an `#[allocator]` crate cannot transitively + depend on a crate which needs an allocator (e.g. circular dependencies are not + allowed). This basically means that allocators must restrict themselves to + libcore currently. diff --git a/src/doc/unstable-book/src/allow-internal-unstable.md b/src/doc/unstable-book/src/allow-internal-unstable.md index fe88dfb3f01..74709ad5aeb 100644 --- a/src/doc/unstable-book/src/allow-internal-unstable.md +++ b/src/doc/unstable-book/src/allow-internal-unstable.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/asm.md b/src/doc/unstable-book/src/asm.md index d3939b701d2..032d9d81240 100644 --- a/src/doc/unstable-book/src/asm.md +++ b/src/doc/unstable-book/src/asm.md @@ -4,5 +4,188 @@ The tracking issue for this feature is: [#29722] [#29722]: https://github.com/rust-lang/rust/issues/29722 +------------------------ +For extremely low-level manipulations and performance reasons, one +might wish to control the CPU directly. Rust supports using inline +assembly to do this via the `asm!` macro. + +```rust,ignore +asm!(assembly template + : output operands + : input operands + : clobbers + : options + ); +``` + +Any use of `asm` is feature gated (requires `#![feature(asm)]` on the +crate to allow) and of course requires an `unsafe` block. + +> **Note**: the examples here are given in x86/x86-64 assembly, but +> all platforms are supported. + +## Assembly template + +The `assembly template` is the only required parameter and must be a +literal string (i.e. `""`) + +```rust +#![feature(asm)] + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn foo() { + unsafe { + asm!("NOP"); + } +} + +// Other platforms: +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +fn foo() { /* ... */ } + +fn main() { + // ... + foo(); + // ... +} +``` + +(The `feature(asm)` and `#[cfg]`s are omitted from now on.) + +Output operands, input operands, clobbers and options are all optional +but you must add the right number of `:` if you skip them: + +```rust +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { unsafe { +asm!("xor %eax, %eax" + : + : + : "eax" + ); +# } } +# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +# fn main() {} +``` + +Whitespace also doesn't matter: + +```rust +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { unsafe { +asm!("xor %eax, %eax" ::: "eax"); +# } } +# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +# fn main() {} +``` + +## Operands + +Input and output operands follow the same format: `: +"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand +expressions must be mutable lvalues, or not yet assigned: + +```rust +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn add(a: i32, b: i32) -> i32 { + let c: i32; + unsafe { + asm!("add $2, $0" + : "=r"(c) + : "0"(a), "r"(b) + ); + } + c +} +# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +# fn add(a: i32, b: i32) -> i32 { a + b } + +fn main() { + assert_eq!(add(3, 14159), 14162) +} +``` + +If you would like to use real operands in this position, however, +you are required to put curly braces `{}` around the register that +you want, and you are required to put the specific size of the +operand. This is useful for very low level programming, where +which register you use is important: + +```rust +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# unsafe fn read_byte_in(port: u16) -> u8 { +let result: u8; +asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port)); +result +# } +``` + +## Clobbers + +Some instructions modify registers which might otherwise have held +different values so we use the clobbers list to indicate to the +compiler not to assume any values loaded into those registers will +stay valid. + +```rust +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { unsafe { +// Put the value 0x200 in eax: +asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); +# } } +# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +# fn main() {} +``` + +Input and output registers need not be listed since that information +is already communicated by the given constraints. Otherwise, any other +registers used either implicitly or explicitly should be listed. + +If the assembly changes the condition code register `cc` should be +specified as one of the clobbers. Similarly, if the assembly modifies +memory, `memory` should also be specified. + +## Options + +The last section, `options` is specific to Rust. The format is comma +separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to +specify some extra info about the inline assembly: + +Current valid options are: + +1. *volatile* - specifying this is analogous to + `__asm__ __volatile__ (...)` in gcc/clang. +2. *alignstack* - certain instructions expect the stack to be + aligned a certain way (i.e. SSE) and specifying this indicates to + the compiler to insert its usual stack alignment code +3. *intel* - use intel syntax instead of the default AT&T. + +```rust +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { +let result: i32; +unsafe { + asm!("mov eax, 2" : "={eax}"(result) : : : "intel") +} +println!("eax is currently {}", result); +# } +# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +# fn main() {} +``` + +## More Information + +The current implementation of the `asm!` macro is a direct binding to [LLVM's +inline assembler expressions][llvm-docs], so be sure to check out [their +documentation as well][llvm-docs] for more information about clobbers, +constraints, etc. + +[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions diff --git a/src/doc/unstable-book/src/associated-consts.md b/src/doc/unstable-book/src/associated-consts.md index fbd4585cc7d..d661108e7d9 100644 --- a/src/doc/unstable-book/src/associated-consts.md +++ b/src/doc/unstable-book/src/associated-consts.md @@ -4,5 +4,82 @@ The tracking issue for this feature is: [#29646] [#29646]: https://github.com/rust-lang/rust/issues/29646 +------------------------ +With the `associated_consts` feature, you can define constants like this: +```rust +#![feature(associated_consts)] + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, i32::ID); +} +``` + +Any implementor of `Foo` will have to define `ID`. Without the definition: + +```rust,ignore +#![feature(associated_consts)] + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { +} +``` + +gives + +```text +error: not all trait items implemented, missing: `ID` [E0046] + impl Foo for i32 { + } +``` + +A default value can be implemented as well: + +```rust +#![feature(associated_consts)] + +trait Foo { + const ID: i32 = 1; +} + +impl Foo for i32 { +} + +impl Foo for i64 { + const ID: i32 = 5; +} + +fn main() { + assert_eq!(1, i32::ID); + assert_eq!(5, i64::ID); +} +``` + +As you can see, when implementing `Foo`, you can leave it unimplemented, as +with `i32`. It will then use the default value. But, as in `i64`, we can also +add our own definition. + +Associated constants don’t have to be associated with a trait. An `impl` block +for a `struct` or an `enum` works fine too: + +```rust +#![feature(associated_consts)] + +struct Foo; + +impl Foo { + const FOO: u32 = 3; +} +``` diff --git a/src/doc/unstable-book/src/associated-type-defaults.md b/src/doc/unstable-book/src/associated-type-defaults.md index 6a44da41e5f..56cc8a5b306 100644 --- a/src/doc/unstable-book/src/associated-type-defaults.md +++ b/src/doc/unstable-book/src/associated-type-defaults.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29661] [#29661]: https://github.com/rust-lang/rust/issues/29661 +------------------------ + diff --git a/src/doc/unstable-book/src/attr-literals.md b/src/doc/unstable-book/src/attr-literals.md index 013191ce017..67eee214a4f 100644 --- a/src/doc/unstable-book/src/attr-literals.md +++ b/src/doc/unstable-book/src/attr-literals.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34981] [#34981]: https://github.com/rust-lang/rust/issues/34981 +------------------------ + diff --git a/src/doc/unstable-book/src/box-patterns.md b/src/doc/unstable-book/src/box-patterns.md index 27c434f7d27..86346364a71 100644 --- a/src/doc/unstable-book/src/box-patterns.md +++ b/src/doc/unstable-book/src/box-patterns.md @@ -4,5 +4,29 @@ The tracking issue for this feature is: [#29641] [#29641]: https://github.com/rust-lang/rust/issues/29641 +See also [`box_syntax`](box-syntax.html) +------------------------ +Box patterns let you match on `Box<T>`s: + + +```rust +#![feature(box_patterns)] + +fn main() { + let b = Some(Box::new(5)); + match b { + Some(box n) if n < 0 => { + println!("Box contains negative number {}", n); + }, + Some(box n) if n >= 0 => { + println!("Box contains non-negative number {}", n); + }, + None => { + println!("No box"); + }, + _ => unreachable!() + } +} +``` diff --git a/src/doc/unstable-book/src/box-syntax.md b/src/doc/unstable-book/src/box-syntax.md index 881d0140473..47aade0d045 100644 --- a/src/doc/unstable-book/src/box-syntax.md +++ b/src/doc/unstable-book/src/box-syntax.md @@ -4,5 +4,19 @@ The tracking issue for this feature is: [#27779] [#27779]: https://github.com/rust-lang/rust/issues/27779 +See also [`box_patterns`](box-patterns.html) +------------------------ +Currently the only stable way to create a `Box` is via the `Box::new` method. +Also it is not possible in stable Rust to destructure a `Box` in a match +pattern. The unstable `box` keyword can be used to create a `Box`. An example +usage would be: + +```rust +#![feature(box_syntax)] + +fn main() { + let b = box 5; +} +``` diff --git a/src/doc/unstable-book/src/cfg-target-feature.md b/src/doc/unstable-book/src/cfg-target-feature.md index 930104acc12..ddd88bdc2cb 100644 --- a/src/doc/unstable-book/src/cfg-target-feature.md +++ b/src/doc/unstable-book/src/cfg-target-feature.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29717] [#29717]: https://github.com/rust-lang/rust/issues/29717 +------------------------ + diff --git a/src/doc/unstable-book/src/cfg-target-has-atomic.md b/src/doc/unstable-book/src/cfg-target-has-atomic.md index 36a0ab0aef7..7496e42e1cd 100644 --- a/src/doc/unstable-book/src/cfg-target-has-atomic.md +++ b/src/doc/unstable-book/src/cfg-target-has-atomic.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32976] [#32976]: https://github.com/rust-lang/rust/issues/32976 +------------------------ + diff --git a/src/doc/unstable-book/src/cfg-target-thread-local.md b/src/doc/unstable-book/src/cfg-target-thread-local.md index 7f139a733cc..a5adb38db3d 100644 --- a/src/doc/unstable-book/src/cfg-target-thread-local.md +++ b/src/doc/unstable-book/src/cfg-target-thread-local.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29594] [#29594]: https://github.com/rust-lang/rust/issues/29594 +------------------------ + diff --git a/src/doc/unstable-book/src/cfg-target-vendor.md b/src/doc/unstable-book/src/cfg-target-vendor.md index 930104acc12..ddd88bdc2cb 100644 --- a/src/doc/unstable-book/src/cfg-target-vendor.md +++ b/src/doc/unstable-book/src/cfg-target-vendor.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29717] [#29717]: https://github.com/rust-lang/rust/issues/29717 +------------------------ + diff --git a/src/doc/unstable-book/src/compiler-builtins.md b/src/doc/unstable-book/src/compiler-builtins.md index 886bd31a0e3..3ec3cba257a 100644 --- a/src/doc/unstable-book/src/compiler-builtins.md +++ b/src/doc/unstable-book/src/compiler-builtins.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/concat-idents.md b/src/doc/unstable-book/src/concat-idents.md index e8edc12d663..c9a48293dba 100644 --- a/src/doc/unstable-book/src/concat-idents.md +++ b/src/doc/unstable-book/src/concat-idents.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29599] [#29599]: https://github.com/rust-lang/rust/issues/29599 +------------------------ + diff --git a/src/doc/unstable-book/src/conservative-impl-trait.md b/src/doc/unstable-book/src/conservative-impl-trait.md index 91221aa45b7..7d8bda439bd 100644 --- a/src/doc/unstable-book/src/conservative-impl-trait.md +++ b/src/doc/unstable-book/src/conservative-impl-trait.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34511] [#34511]: https://github.com/rust-lang/rust/issues/34511 +------------------------ + diff --git a/src/doc/unstable-book/src/const-fn.md b/src/doc/unstable-book/src/const-fn.md index 4bd0933f7be..9b7942c408a 100644 --- a/src/doc/unstable-book/src/const-fn.md +++ b/src/doc/unstable-book/src/const-fn.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#24111] [#24111]: https://github.com/rust-lang/rust/issues/24111 +------------------------ + diff --git a/src/doc/unstable-book/src/const-indexing.md b/src/doc/unstable-book/src/const-indexing.md index 30e093befd0..bd92b0b1b47 100644 --- a/src/doc/unstable-book/src/const-indexing.md +++ b/src/doc/unstable-book/src/const-indexing.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29947] [#29947]: https://github.com/rust-lang/rust/issues/29947 +------------------------ + diff --git a/src/doc/unstable-book/src/custom-attribute.md b/src/doc/unstable-book/src/custom-attribute.md index 0080bb79a9e..838f09670d2 100644 --- a/src/doc/unstable-book/src/custom-attribute.md +++ b/src/doc/unstable-book/src/custom-attribute.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29642] [#29642]: https://github.com/rust-lang/rust/issues/29642 +------------------------ + diff --git a/src/doc/unstable-book/src/custom-derive.md b/src/doc/unstable-book/src/custom-derive.md index 999cb7bf521..d5fdd2b708b 100644 --- a/src/doc/unstable-book/src/custom-derive.md +++ b/src/doc/unstable-book/src/custom-derive.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29644] [#29644]: https://github.com/rust-lang/rust/issues/29644 +------------------------ + diff --git a/src/doc/unstable-book/src/default-type-parameter-fallback.md b/src/doc/unstable-book/src/default-type-parameter-fallback.md index 373d18b7ffb..fd16dbf8985 100644 --- a/src/doc/unstable-book/src/default-type-parameter-fallback.md +++ b/src/doc/unstable-book/src/default-type-parameter-fallback.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27336] [#27336]: https://github.com/rust-lang/rust/issues/27336 +------------------------ + diff --git a/src/doc/unstable-book/src/drop-types-in-const.md b/src/doc/unstable-book/src/drop-types-in-const.md index 4b535dfc1da..b3367d0df44 100644 --- a/src/doc/unstable-book/src/drop-types-in-const.md +++ b/src/doc/unstable-book/src/drop-types-in-const.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#33156] [#33156]: https://github.com/rust-lang/rust/issues/33156 +------------------------ + diff --git a/src/doc/unstable-book/src/dropck-eyepatch.md b/src/doc/unstable-book/src/dropck-eyepatch.md index 2f1e5936c06..2f189e9b645 100644 --- a/src/doc/unstable-book/src/dropck-eyepatch.md +++ b/src/doc/unstable-book/src/dropck-eyepatch.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34761] [#34761]: https://github.com/rust-lang/rust/issues/34761 +------------------------ + diff --git a/src/doc/unstable-book/src/dropck-parametricity.md b/src/doc/unstable-book/src/dropck-parametricity.md index c00cd4c5cf6..c5ae721954b 100644 --- a/src/doc/unstable-book/src/dropck-parametricity.md +++ b/src/doc/unstable-book/src/dropck-parametricity.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#28498] [#28498]: https://github.com/rust-lang/rust/issues/28498 +------------------------ + diff --git a/src/doc/unstable-book/src/exclusive-range-pattern.md b/src/doc/unstable-book/src/exclusive-range-pattern.md index 05b8db99bb7..b669ce83132 100644 --- a/src/doc/unstable-book/src/exclusive-range-pattern.md +++ b/src/doc/unstable-book/src/exclusive-range-pattern.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37854] [#37854]: https://github.com/rust-lang/rust/issues/37854 +------------------------ + diff --git a/src/doc/unstable-book/src/field-init-shorthand.md b/src/doc/unstable-book/src/field-init-shorthand.md index 20b3d17b085..e737dbaa4ec 100644 --- a/src/doc/unstable-book/src/field-init-shorthand.md +++ b/src/doc/unstable-book/src/field-init-shorthand.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37340] [#37340]: https://github.com/rust-lang/rust/issues/37340 +------------------------ + diff --git a/src/doc/unstable-book/src/fundamental.md b/src/doc/unstable-book/src/fundamental.md index 2ab978cb648..a068dadf95d 100644 --- a/src/doc/unstable-book/src/fundamental.md +++ b/src/doc/unstable-book/src/fundamental.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29635] [#29635]: https://github.com/rust-lang/rust/issues/29635 +------------------------ + diff --git a/src/doc/unstable-book/src/generic-param-attrs.md b/src/doc/unstable-book/src/generic-param-attrs.md index 7c75231a655..ba49c850e4d 100644 --- a/src/doc/unstable-book/src/generic-param-attrs.md +++ b/src/doc/unstable-book/src/generic-param-attrs.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34761] [#34761]: https://github.com/rust-lang/rust/issues/34761 +------------------------ + diff --git a/src/doc/unstable-book/src/i128-type.md b/src/doc/unstable-book/src/i128-type.md index f3f32176546..ffcf45feb2a 100644 --- a/src/doc/unstable-book/src/i128-type.md +++ b/src/doc/unstable-book/src/i128-type.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35118] [#35118]: https://github.com/rust-lang/rust/issues/35118 +------------------------ + diff --git a/src/doc/unstable-book/src/inclusive-range-syntax.md b/src/doc/unstable-book/src/inclusive-range-syntax.md index f7f29f474ae..74d85536399 100644 --- a/src/doc/unstable-book/src/inclusive-range-syntax.md +++ b/src/doc/unstable-book/src/inclusive-range-syntax.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#28237] [#28237]: https://github.com/rust-lang/rust/issues/28237 +------------------------ + diff --git a/src/doc/unstable-book/src/intrinsics.md b/src/doc/unstable-book/src/intrinsics.md index 65331da8567..bc35c2a0305 100644 --- a/src/doc/unstable-book/src/intrinsics.md +++ b/src/doc/unstable-book/src/intrinsics.md @@ -1,3 +1,30 @@ # `intrinsics` The tracking issue for this feature is: None. + +Intrinsics are never intended to be stable directly, but intrinsics are often +exported in some sort of stable manner. Prefer using the stable interfaces to +the intrinsic directly when you can. + +------------------------ + + +These are imported as if they were FFI functions, with the special +`rust-intrinsic` ABI. For example, if one was in a freestanding +context, but wished to be able to `transmute` between types, and +perform efficient pointer arithmetic, one would import those functions +via a declaration like + +```rust +#![feature(intrinsics)] +# fn main() {} + +extern "rust-intrinsic" { + fn transmute<T, U>(x: T) -> U; + + fn offset<T>(dst: *const T, offset: isize) -> *const T; +} +``` + +As with any other FFI functions, these are always `unsafe` to call. + diff --git a/src/doc/unstable-book/src/lang-items.md b/src/doc/unstable-book/src/lang-items.md index de8ff6b076b..375b8bd6b82 100644 --- a/src/doc/unstable-book/src/lang-items.md +++ b/src/doc/unstable-book/src/lang-items.md @@ -2,3 +2,218 @@ The tracking issue for this feature is: None. +------------------------ + +The `rustc` compiler has certain pluggable operations, that is, +functionality that isn't hard-coded into the language, but is +implemented in libraries, with a special marker to tell the compiler +it exists. The marker is the attribute `#[lang = "..."]` and there are +various different values of `...`, i.e. various different 'lang +items'. + +For example, `Box` pointers require two lang items, one for allocation +and one for deallocation. A freestanding program that uses the `Box` +sugar for dynamic allocations via `malloc` and `free`: + +```rust,ignore +#![feature(lang_items, box_syntax, start, libc, core_intrinsics)] +#![no_std] +use core::intrinsics; + +extern crate libc; + +#[lang = "owned_box"] +pub struct Box<T>(*mut T); + +#[lang = "exchange_malloc"] +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + let p = libc::malloc(size as libc::size_t) as *mut u8; + + // Check if `malloc` failed: + if p as usize == 0 { + intrinsics::abort(); + } + + p +} + +#[lang = "exchange_free"] +unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { + libc::free(ptr as *mut libc::c_void) +} + +#[lang = "box_free"] +unsafe fn box_free<T: ?Sized>(ptr: *mut T) { + deallocate(ptr as *mut u8, ::core::mem::size_of_val(&*ptr), ::core::mem::align_of_val(&*ptr)); +} + +#[start] +fn main(argc: isize, argv: *const *const u8) -> isize { + let x = box 1; + + 0 +} + +#[lang = "eh_personality"] extern fn rust_eh_personality() {} +#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } } +# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} +# #[no_mangle] pub extern fn rust_eh_register_frames () {} +# #[no_mangle] pub extern fn rust_eh_unregister_frames () {} +``` + +Note the use of `abort`: the `exchange_malloc` lang item is assumed to +return a valid pointer, and so needs to do the check internally. + +Other features provided by lang items include: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `ord`, + `deref`, and `add` respectively. +- stack unwinding and general failure; the `eh_personality`, + `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items. +- the traits in `std::marker` used to indicate types of + various kinds; lang items `send`, `sync` and `copy`. +- the marker types and variance indicators found in + `std::marker`; lang items `covariant_type`, + `contravariant_lifetime`, etc. + +Lang items are loaded lazily by the compiler; e.g. if one never uses +`Box` then there is no need to define functions for `exchange_malloc` +and `exchange_free`. `rustc` will emit an error when an item is needed +but not found in the current crate or any that it depends on. + +Most lang items are defined by `libcore`, but if you're trying to build +an executable without the standard library, you'll run into the need +for lang items. The rest of this page focuses on this use-case, even though +lang items are a bit broader than that. + +### Using libc + +In order to build a `#[no_std]` executable we will need libc as a dependency. +We can specify this using our `Cargo.toml` file: + +```toml +[dependencies] +libc = { version = "0.2.14", default-features = false } +``` + +Note that the default features have been disabled. This is a critical step - +**the default features of libc include the standard library and so must be +disabled.** + +### Writing an executable without stdlib + +Controlling the entry point is possible in two ways: the `#[start]` attribute, +or overriding the default shim for the C `main` function with your own. + +The function marked `#[start]` is passed the command line parameters +in the same format as C: + +```rust,ignore +#![feature(lang_items, core_intrinsics)] +#![feature(start)] +#![no_std] +use core::intrinsics; + +// Pull in the system libc library for what crt0.o likely requires. +extern crate libc; + +// Entry point for this program. +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +// These functions are used by the compiler, but not +// for a bare-bones hello world. These are normally +// provided by libstd. +#[lang = "eh_personality"] +#[no_mangle] +pub extern fn rust_eh_personality() { +} + +// This function may be needed based on the compilation target. +#[lang = "eh_unwind_resume"] +#[no_mangle] +pub extern fn rust_eh_unwind_resume() { +} + +#[lang = "panic_fmt"] +#[no_mangle] +pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, + _file: &'static str, + _line: u32) -> ! { + unsafe { intrinsics::abort() } +} +``` + +To override the compiler-inserted `main` shim, one has to disable it +with `#![no_main]` and then create the appropriate symbol with the +correct ABI and the correct name, which requires overriding the +compiler's name mangling too: + +```rust,ignore +#![feature(lang_items, core_intrinsics)] +#![feature(start)] +#![no_std] +#![no_main] +use core::intrinsics; + +// Pull in the system libc library for what crt0.o likely requires. +extern crate libc; + +// Entry point for this program. +#[no_mangle] // ensure that this symbol is called `main` in the output +pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { + 0 +} + +// These functions are used by the compiler, but not +// for a bare-bones hello world. These are normally +// provided by libstd. +#[lang = "eh_personality"] +#[no_mangle] +pub extern fn rust_eh_personality() { +} + +// This function may be needed based on the compilation target. +#[lang = "eh_unwind_resume"] +#[no_mangle] +pub extern fn rust_eh_unwind_resume() { +} + +#[lang = "panic_fmt"] +#[no_mangle] +pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, + _file: &'static str, + _line: u32) -> ! { + unsafe { intrinsics::abort() } +} +``` + +## More about the language items + +The compiler currently makes a few assumptions about symbols which are +available in the executable to call. Normally these functions are provided by +the standard library, but without it you must define your own. These symbols +are called "language items", and they each have an internal name, and then a +signature that an implementation must conform to. + +The first of these functions, `rust_eh_personality`, is used by the failure +mechanisms of the compiler. This is often mapped to GCC's personality function +(see the [libstd implementation][unwind] for more information), but crates +which do not trigger a panic can be assured that this function is never +called. The language item's name is `eh_personality`. + +[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs + +The second function, `rust_begin_panic`, is also used by the failure mechanisms of the +compiler. When a panic happens, this controls the message that's displayed on +the screen. While the language item's name is `panic_fmt`, the symbol name is +`rust_begin_panic`. + +A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume` +flag is set in the options of the compilation target. It allows customizing the +process of resuming unwind at the end of the landing pads. The language item's name +is `eh_unwind_resume`. diff --git a/src/doc/unstable-book/src/link-args.md b/src/doc/unstable-book/src/link-args.md index a887242f1aa..2507197661a 100644 --- a/src/doc/unstable-book/src/link-args.md +++ b/src/doc/unstable-book/src/link-args.md @@ -4,5 +4,29 @@ The tracking issue for this feature is: [#29596] [#29596]: https://github.com/rust-lang/rust/issues/29596 +------------------------ +You can 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: +```rust,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. diff --git a/src/doc/unstable-book/src/link-cfg.md b/src/doc/unstable-book/src/link-cfg.md index 4d6dd259efe..7393d0628e4 100644 --- a/src/doc/unstable-book/src/link-cfg.md +++ b/src/doc/unstable-book/src/link-cfg.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37406] [#37406]: https://github.com/rust-lang/rust/issues/37406 +------------------------ + diff --git a/src/doc/unstable-book/src/link-llvm-intrinsics.md b/src/doc/unstable-book/src/link-llvm-intrinsics.md index aee4e0a40d5..ba639cb57fc 100644 --- a/src/doc/unstable-book/src/link-llvm-intrinsics.md +++ b/src/doc/unstable-book/src/link-llvm-intrinsics.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29602] [#29602]: https://github.com/rust-lang/rust/issues/29602 +------------------------ + diff --git a/src/doc/unstable-book/src/linkage.md b/src/doc/unstable-book/src/linkage.md index 3deac364d75..5773d28a00e 100644 --- a/src/doc/unstable-book/src/linkage.md +++ b/src/doc/unstable-book/src/linkage.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29603] [#29603]: https://github.com/rust-lang/rust/issues/29603 +------------------------ + diff --git a/src/doc/unstable-book/src/log-syntax.md b/src/doc/unstable-book/src/log-syntax.md index f61bb49b78c..b13f5ccfd91 100644 --- a/src/doc/unstable-book/src/log-syntax.md +++ b/src/doc/unstable-book/src/log-syntax.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29598] [#29598]: https://github.com/rust-lang/rust/issues/29598 +------------------------ + diff --git a/src/doc/unstable-book/src/loop-break-value.md b/src/doc/unstable-book/src/loop-break-value.md index 16c0618cbe0..54d6e62ce4c 100644 --- a/src/doc/unstable-book/src/loop-break-value.md +++ b/src/doc/unstable-book/src/loop-break-value.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37339] [#37339]: https://github.com/rust-lang/rust/issues/37339 +------------------------ + diff --git a/src/doc/unstable-book/src/macro-reexport.md b/src/doc/unstable-book/src/macro-reexport.md index 0ba5a56fc47..32ffa3b4c31 100644 --- a/src/doc/unstable-book/src/macro-reexport.md +++ b/src/doc/unstable-book/src/macro-reexport.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29638] [#29638]: https://github.com/rust-lang/rust/issues/29638 +------------------------ + diff --git a/src/doc/unstable-book/src/main.md b/src/doc/unstable-book/src/main.md index 795db9bd1ab..579aabfff88 100644 --- a/src/doc/unstable-book/src/main.md +++ b/src/doc/unstable-book/src/main.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29634] [#29634]: https://github.com/rust-lang/rust/issues/29634 +------------------------ + diff --git a/src/doc/unstable-book/src/naked-functions.md b/src/doc/unstable-book/src/naked-functions.md index 896a83237a5..e56ce4770aa 100644 --- a/src/doc/unstable-book/src/naked-functions.md +++ b/src/doc/unstable-book/src/naked-functions.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32408] [#32408]: https://github.com/rust-lang/rust/issues/32408 +------------------------ + diff --git a/src/doc/unstable-book/src/needs-allocator.md b/src/doc/unstable-book/src/needs-allocator.md index 14fb4b3782f..22aa10b2183 100644 --- a/src/doc/unstable-book/src/needs-allocator.md +++ b/src/doc/unstable-book/src/needs-allocator.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27389] [#27389]: https://github.com/rust-lang/rust/issues/27389 +------------------------ + diff --git a/src/doc/unstable-book/src/needs-panic-runtime.md b/src/doc/unstable-book/src/needs-panic-runtime.md index ecaeaaab047..627c946c1bb 100644 --- a/src/doc/unstable-book/src/needs-panic-runtime.md +++ b/src/doc/unstable-book/src/needs-panic-runtime.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32837] [#32837]: https://github.com/rust-lang/rust/issues/32837 +------------------------ + diff --git a/src/doc/unstable-book/src/never-type.md b/src/doc/unstable-book/src/never-type.md index 26db551e850..3b3729a4b21 100644 --- a/src/doc/unstable-book/src/never-type.md +++ b/src/doc/unstable-book/src/never-type.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35121] [#35121]: https://github.com/rust-lang/rust/issues/35121 +------------------------ + diff --git a/src/doc/unstable-book/src/no-core.md b/src/doc/unstable-book/src/no-core.md index 363d0f37d98..6238753447c 100644 --- a/src/doc/unstable-book/src/no-core.md +++ b/src/doc/unstable-book/src/no-core.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29639] [#29639]: https://github.com/rust-lang/rust/issues/29639 +------------------------ + diff --git a/src/doc/unstable-book/src/no-debug.md b/src/doc/unstable-book/src/no-debug.md index 5fcf7e142cf..7536ed9d4e1 100644 --- a/src/doc/unstable-book/src/no-debug.md +++ b/src/doc/unstable-book/src/no-debug.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29721] [#29721]: https://github.com/rust-lang/rust/issues/29721 +------------------------ + diff --git a/src/doc/unstable-book/src/non-ascii-idents.md b/src/doc/unstable-book/src/non-ascii-idents.md index 9bd2609aaf7..f426022ab3a 100644 --- a/src/doc/unstable-book/src/non-ascii-idents.md +++ b/src/doc/unstable-book/src/non-ascii-idents.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#28979] [#28979]: https://github.com/rust-lang/rust/issues/28979 +------------------------ + diff --git a/src/doc/unstable-book/src/omit-gdb-pretty-printer-section.md b/src/doc/unstable-book/src/omit-gdb-pretty-printer-section.md index baa5024357d..d8ac520fcb5 100644 --- a/src/doc/unstable-book/src/omit-gdb-pretty-printer-section.md +++ b/src/doc/unstable-book/src/omit-gdb-pretty-printer-section.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/on-unimplemented.md b/src/doc/unstable-book/src/on-unimplemented.md index 6b4a4268195..81f284d0a6a 100644 --- a/src/doc/unstable-book/src/on-unimplemented.md +++ b/src/doc/unstable-book/src/on-unimplemented.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29628] [#29628]: https://github.com/rust-lang/rust/issues/29628 +------------------------ + diff --git a/src/doc/unstable-book/src/optin-builtin-traits.md b/src/doc/unstable-book/src/optin-builtin-traits.md index 06d0e553b8b..0b2d60accd5 100644 --- a/src/doc/unstable-book/src/optin-builtin-traits.md +++ b/src/doc/unstable-book/src/optin-builtin-traits.md @@ -4,5 +4,6 @@ The tracking issue for this feature is: [#13231] [#13231]: https://github.com/rust-lang/rust/issues/13231 +------------------------ diff --git a/src/doc/unstable-book/src/panic-runtime.md b/src/doc/unstable-book/src/panic-runtime.md index 1d4cca0bc2f..65b067e8296 100644 --- a/src/doc/unstable-book/src/panic-runtime.md +++ b/src/doc/unstable-book/src/panic-runtime.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32837] [#32837]: https://github.com/rust-lang/rust/issues/32837 +------------------------ + diff --git a/src/doc/unstable-book/src/placement-in-syntax.md b/src/doc/unstable-book/src/placement-in-syntax.md index 92a56810e22..da12559a01b 100644 --- a/src/doc/unstable-book/src/placement-in-syntax.md +++ b/src/doc/unstable-book/src/placement-in-syntax.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27779] [#27779]: https://github.com/rust-lang/rust/issues/27779 +------------------------ + diff --git a/src/doc/unstable-book/src/platform-intrinsics.md b/src/doc/unstable-book/src/platform-intrinsics.md index e895e0af5c4..377ac8f7342 100644 --- a/src/doc/unstable-book/src/platform-intrinsics.md +++ b/src/doc/unstable-book/src/platform-intrinsics.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731] [#27731]: https://github.com/rust-lang/rust/issues/27731 +------------------------ + diff --git a/src/doc/unstable-book/src/plugin-registrar.md b/src/doc/unstable-book/src/plugin-registrar.md index 024690e87a1..ca3738bd93f 100644 --- a/src/doc/unstable-book/src/plugin-registrar.md +++ b/src/doc/unstable-book/src/plugin-registrar.md @@ -4,5 +4,10 @@ The tracking issue for this feature is: [#29597] [#29597]: https://github.com/rust-lang/rust/issues/29597 +This feature is part of "compiler plugins." It will often be used with the +[`plugin`] and `rustc_private` features as well. For more details, see +their docs. +[`plugin`]: plugin.html +------------------------ diff --git a/src/doc/unstable-book/src/plugin.md b/src/doc/unstable-book/src/plugin.md index f676e9d98c3..1ec28bbcf03 100644 --- a/src/doc/unstable-book/src/plugin.md +++ b/src/doc/unstable-book/src/plugin.md @@ -5,4 +5,258 @@ The tracking issue for this feature is: [#29597] [#29597]: https://github.com/rust-lang/rust/issues/29597 +This feature is part of "compiler plugins." It will often be used with the +[`plugin_registrar`] and `rustc_private` features. +[`plugin_registrar`]: plugin-registrar.html + +------------------------ + +`rustc` can load compiler plugins, which are user-provided libraries that +extend the compiler's behavior with new syntax extensions, lint checks, etc. + +A plugin is a dynamic library crate with a designated *registrar* function that +registers extensions with `rustc`. Other crates can load these extensions using +the crate attribute `#![plugin(...)]`. See the +`rustc_plugin` documentation for more about the +mechanics of defining and loading a plugin. + +If present, arguments passed as `#![plugin(foo(... args ...))]` are not +interpreted by rustc itself. They are provided to the plugin through the +`Registry`'s `args` method. + +In the vast majority of cases, a plugin should *only* be used through +`#![plugin]` and not through an `extern crate` item. Linking a plugin would +pull in all of libsyntax and librustc as dependencies of your crate. This is +generally unwanted unless you are building another plugin. The +`plugin_as_library` lint checks these guidelines. + +The usual practice is to put compiler plugins in their own crate, separate from +any `macro_rules!` macros or ordinary Rust code meant to be used by consumers +of a library. + +# Syntax extensions + +Plugins can extend Rust's syntax in various ways. One kind of syntax extension +is the procedural macro. These are invoked the same way as [ordinary +macros](macros.html), but the expansion is performed by arbitrary Rust +code that manipulates syntax trees at +compile time. + +Let's write a plugin +[`roman_numerals.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs) +that implements Roman numeral integer literals. + +```rust,ignore +#![crate_type="dylib"] +#![feature(plugin_registrar, rustc_private)] + +extern crate syntax; +extern crate rustc; +extern crate rustc_plugin; + +use syntax::parse::token; +use syntax::tokenstream::TokenTree; +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax::ext::build::AstBuilder; // A trait for expr_usize. +use syntax::ext::quote::rt::Span; +use rustc_plugin::Registry; + +fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) + -> Box<MacResult + 'static> { + + static NUMERALS: &'static [(&'static str, usize)] = &[ + ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), + ("C", 100), ("XC", 90), ("L", 50), ("XL", 40), + ("X", 10), ("IX", 9), ("V", 5), ("IV", 4), + ("I", 1)]; + + if args.len() != 1 { + cx.span_err( + sp, + &format!("argument should be a single identifier, but got {} arguments", args.len())); + return DummyResult::any(sp); + } + + let text = match args[0] { + TokenTree::Token(_, token::Ident(s)) => s.to_string(), + _ => { + cx.span_err(sp, "argument should be a single identifier"); + return DummyResult::any(sp); + } + }; + + let mut text = &*text; + let mut total = 0; + while !text.is_empty() { + match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) { + Some(&(rn, val)) => { + total += val; + text = &text[rn.len()..]; + } + None => { + cx.span_err(sp, "invalid Roman numeral"); + return DummyResult::any(sp); + } + } + } + + MacEager::expr(cx.expr_usize(sp, total)) +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_macro("rn", expand_rn); +} +``` + +Then we can use `rn!()` like any other macro: + +```rust,ignore +#![feature(plugin)] +#![plugin(roman_numerals)] + +fn main() { + assert_eq!(rn!(MMXV), 2015); +} +``` + +The advantages over a simple `fn(&str) -> u32` are: + +* The (arbitrarily complex) conversion is done at compile time. +* Input validation is also performed at compile time. +* It can be extended to allow use in patterns, which effectively gives + a way to define new literal syntax for any data type. + +In addition to procedural macros, you can define new +[`derive`](../reference.html#derive)-like attributes and other kinds of +extensions. See `Registry::register_syntax_extension` and the `SyntaxExtension` +enum. For a more involved macro example, see +[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). + + +## Tips and tricks + +Some of the [macro debugging tips](macros.html#Debugging%20macro%20code) are applicable. + +You can use `syntax::parse` to turn token trees into +higher-level syntax elements like expressions: + +```rust,ignore +fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) + -> Box<MacResult+'static> { + + let mut parser = cx.new_parser_from_tts(args); + + let expr: P<Expr> = parser.parse_expr(); +``` + +Looking through [`libsyntax` parser +code](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs) +will give you a feel for how the parsing infrastructure works. + +Keep the `Span`s of everything you parse, for better error reporting. You can +wrap `Spanned` around your custom data structures. + +Calling `ExtCtxt::span_fatal` will immediately abort compilation. It's better to +instead call `ExtCtxt::span_err` and return `DummyResult` so that the compiler +can continue and find further errors. + +To print syntax fragments for debugging, you can use `span_note` together with +`syntax::print::pprust::*_to_string`. + +The example above produced an integer literal using `AstBuilder::expr_usize`. +As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of +quasiquote macros. They are undocumented and very rough around the edges. +However, the implementation may be a good starting point for an improved +quasiquote as an ordinary plugin library. + + +# Lint plugins + +Plugins can extend [Rust's lint +infrastructure](../reference.html#lint-check-attributes) with additional checks for +code style, safety, etc. Now let's write a plugin +[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs) +that warns about any item named `lintme`. + +```rust,ignore +#![feature(plugin_registrar)] +#![feature(box_syntax, rustc_private)] + +extern crate syntax; + +// Load rustc as a plugin to get macros +#[macro_use] +extern crate rustc; +extern crate rustc_plugin; + +use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, + EarlyLintPassObject, LintArray}; +use rustc_plugin::Registry; +use syntax::ast; + +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); + +struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(TEST_LINT) + } +} + +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { + if it.ident.name.as_str() == "lintme" { + cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_early_lint_pass(box Pass as EarlyLintPassObject); +} +``` + +Then code like + +```rust,ignore +#![plugin(lint_plugin_test)] + +fn lintme() { } +``` + +will produce a compiler warning: + +```txt +foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default +foo.rs:4 fn lintme() { } + ^~~~~~~~~~~~~~~ +``` + +The components of a lint plugin are: + +* one or more `declare_lint!` invocations, which define static `Lint` structs; + +* a struct holding any state needed by the lint pass (here, none); + +* a `LintPass` + implementation defining how to check each syntax element. A single + `LintPass` may call `span_lint` for several different `Lint`s, but should + register them all through the `get_lints` method. + +Lint passes are syntax traversals, but they run at a late stage of compilation +where type information is available. `rustc`'s [built-in +lints](https://github.com/rust-lang/rust/blob/master/src/librustc/lint/builtin.rs) +mostly use the same infrastructure as lint plugins, and provide examples of how +to access type information. + +Lints defined by plugins are controlled by the usual [attributes and compiler +flags](../reference.html#lint-check-attributes), e.g. `#[allow(test_lint)]` or +`-A test-lint`. These identifiers are derived from the first argument to +`declare_lint!`, with appropriate case and punctuation conversion. + +You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, +including those provided by plugins loaded by `foo.rs`. diff --git a/src/doc/unstable-book/src/prelude-import.md b/src/doc/unstable-book/src/prelude-import.md index 6bb093bfbc7..75dae5cfb74 100644 --- a/src/doc/unstable-book/src/prelude-import.md +++ b/src/doc/unstable-book/src/prelude-import.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/proc-macro.md b/src/doc/unstable-book/src/proc-macro.md index 845a61eb22e..f8b53bd5a2f 100644 --- a/src/doc/unstable-book/src/proc-macro.md +++ b/src/doc/unstable-book/src/proc-macro.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#38356] [#38356]: https://github.com/rust-lang/rust/issues/38356 +------------------------ + diff --git a/src/doc/unstable-book/src/pub-restricted.md b/src/doc/unstable-book/src/pub-restricted.md index c15e5d5fdaf..730461813cb 100644 --- a/src/doc/unstable-book/src/pub-restricted.md +++ b/src/doc/unstable-book/src/pub-restricted.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32409] [#32409]: https://github.com/rust-lang/rust/issues/32409 +------------------------ + diff --git a/src/doc/unstable-book/src/quote.md b/src/doc/unstable-book/src/quote.md index a596cc9add7..b4e078d920c 100644 --- a/src/doc/unstable-book/src/quote.md +++ b/src/doc/unstable-book/src/quote.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29601] [#29601]: https://github.com/rust-lang/rust/issues/29601 +------------------------ + diff --git a/src/doc/unstable-book/src/relaxed-adts.md b/src/doc/unstable-book/src/relaxed-adts.md index 274ea08f37a..170570e06a2 100644 --- a/src/doc/unstable-book/src/relaxed-adts.md +++ b/src/doc/unstable-book/src/relaxed-adts.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35626] [#35626]: https://github.com/rust-lang/rust/issues/35626 +------------------------ + diff --git a/src/doc/unstable-book/src/repr-simd.md b/src/doc/unstable-book/src/repr-simd.md index cfb3c151098..c6f051e4fff 100644 --- a/src/doc/unstable-book/src/repr-simd.md +++ b/src/doc/unstable-book/src/repr-simd.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731] [#27731]: https://github.com/rust-lang/rust/issues/27731 +------------------------ + diff --git a/src/doc/unstable-book/src/rustc-attrs.md b/src/doc/unstable-book/src/rustc-attrs.md index f42d2dcf312..d1f18cead06 100644 --- a/src/doc/unstable-book/src/rustc-attrs.md +++ b/src/doc/unstable-book/src/rustc-attrs.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29642] [#29642]: https://github.com/rust-lang/rust/issues/29642 +------------------------ + diff --git a/src/doc/unstable-book/src/rustc-diagnostic-macros.md b/src/doc/unstable-book/src/rustc-diagnostic-macros.md index f48200abd76..0df6ca12089 100644 --- a/src/doc/unstable-book/src/rustc-diagnostic-macros.md +++ b/src/doc/unstable-book/src/rustc-diagnostic-macros.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/sanitizer-runtime.md b/src/doc/unstable-book/src/sanitizer-runtime.md index a22ed342e20..f19504de58e 100644 --- a/src/doc/unstable-book/src/sanitizer-runtime.md +++ b/src/doc/unstable-book/src/sanitizer-runtime.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/simd-ffi.md b/src/doc/unstable-book/src/simd-ffi.md index 1519def25c8..d85779c3d3d 100644 --- a/src/doc/unstable-book/src/simd-ffi.md +++ b/src/doc/unstable-book/src/simd-ffi.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731] [#27731]: https://github.com/rust-lang/rust/issues/27731 +------------------------ + diff --git a/src/doc/unstable-book/src/simd.md b/src/doc/unstable-book/src/simd.md index 56b1d3630c7..13c9722c524 100644 --- a/src/doc/unstable-book/src/simd.md +++ b/src/doc/unstable-book/src/simd.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731] [#27731]: https://github.com/rust-lang/rust/issues/27731 +------------------------ + diff --git a/src/doc/unstable-book/src/slice-patterns.md b/src/doc/unstable-book/src/slice-patterns.md index e075d0b5eed..1e9e1eaafda 100644 --- a/src/doc/unstable-book/src/slice-patterns.md +++ b/src/doc/unstable-book/src/slice-patterns.md @@ -4,5 +4,24 @@ The tracking issue for this feature is: [#23121] [#23121]: https://github.com/rust-lang/rust/issues/23121 +See also [`advanced_slice_patterns`](advanced-slice-patterns.html). +------------------------ + + +If you want to match against a slice or array, you can use `&` with the +`slice_patterns` feature: + +```rust +#![feature(slice_patterns)] + +fn main() { + let v = vec!["match_this", "1"]; + + match &v[..] { + &["match_this", second] => println!("The second element is {}", second), + _ => {}, + } +} +``` diff --git a/src/doc/unstable-book/src/specialization.md b/src/doc/unstable-book/src/specialization.md index 37b0d36f7b8..59f27343b66 100644 --- a/src/doc/unstable-book/src/specialization.md +++ b/src/doc/unstable-book/src/specialization.md @@ -2,7 +2,7 @@ The tracking issue for this feature is: [#31844] -[#31844]: https://github.com/rust-lang/rust/issues/31844 +------------------------ diff --git a/src/doc/unstable-book/src/staged-api.md b/src/doc/unstable-book/src/staged-api.md index c0406a27325..1409e570e88 100644 --- a/src/doc/unstable-book/src/staged-api.md +++ b/src/doc/unstable-book/src/staged-api.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/start.md b/src/doc/unstable-book/src/start.md index 4f11cf5cae0..1ea6d59c78d 100644 --- a/src/doc/unstable-book/src/start.md +++ b/src/doc/unstable-book/src/start.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29633] [#29633]: https://github.com/rust-lang/rust/issues/29633 +------------------------ + diff --git a/src/doc/unstable-book/src/static-nobundle.md b/src/doc/unstable-book/src/static-nobundle.md index 9ba4bdee08c..97b9d71d433 100644 --- a/src/doc/unstable-book/src/static-nobundle.md +++ b/src/doc/unstable-book/src/static-nobundle.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37403] [#37403]: https://github.com/rust-lang/rust/issues/37403 +------------------------ + diff --git a/src/doc/unstable-book/src/static-recursion.md b/src/doc/unstable-book/src/static-recursion.md index cc539a9d280..d419ea41c6f 100644 --- a/src/doc/unstable-book/src/static-recursion.md +++ b/src/doc/unstable-book/src/static-recursion.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29719] [#29719]: https://github.com/rust-lang/rust/issues/29719 +------------------------ + diff --git a/src/doc/unstable-book/src/stmt-expr-attributes.md b/src/doc/unstable-book/src/stmt-expr-attributes.md index 66b1af8f16c..71092fcf290 100644 --- a/src/doc/unstable-book/src/stmt-expr-attributes.md +++ b/src/doc/unstable-book/src/stmt-expr-attributes.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#15701] [#15701]: https://github.com/rust-lang/rust/issues/15701 +------------------------ + diff --git a/src/doc/unstable-book/src/struct-field-attributes.md b/src/doc/unstable-book/src/struct-field-attributes.md index f0f5ecdf04f..1a94562968d 100644 --- a/src/doc/unstable-book/src/struct-field-attributes.md +++ b/src/doc/unstable-book/src/struct-field-attributes.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#38814] [#38814]: https://github.com/rust-lang/rust/issues/38814 +------------------------ + diff --git a/src/doc/unstable-book/src/structural-match.md b/src/doc/unstable-book/src/structural-match.md index 6f23278ef27..b3ca26e6474 100644 --- a/src/doc/unstable-book/src/structural-match.md +++ b/src/doc/unstable-book/src/structural-match.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#31434] [#31434]: https://github.com/rust-lang/rust/issues/31434 +------------------------ + diff --git a/src/doc/unstable-book/src/target-feature.md b/src/doc/unstable-book/src/target-feature.md index 5702bf0e90b..85ab1ab39ef 100644 --- a/src/doc/unstable-book/src/target-feature.md +++ b/src/doc/unstable-book/src/target-feature.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/book/src/benchmark-tests.md b/src/doc/unstable-book/src/test.md index a6ae2b3049a..6b4a3a677db 100644 --- a/src/doc/book/src/benchmark-tests.md +++ b/src/doc/unstable-book/src/test.md @@ -1,7 +1,13 @@ -# Benchmark tests +# `test` -Rust supports benchmark tests, which can test the performance of your -code. Let's make our `src/lib.rs` look like this (comments elided): +The tracking issue for this feature is: None. + +------------------------ + +The internals of the `test` crate are unstable, behind the `test` flag. The +most widely used part of the `test` crate are benchmark tests, which can test +the performance of your code. Let's make our `src/lib.rs` look like this +(comments elided): ```rust,ignore #![feature(test)] diff --git a/src/doc/unstable-book/src/thread-local.md b/src/doc/unstable-book/src/thread-local.md index 5109aa0c59c..83de2f9cd4b 100644 --- a/src/doc/unstable-book/src/thread-local.md +++ b/src/doc/unstable-book/src/thread-local.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29594] [#29594]: https://github.com/rust-lang/rust/issues/29594 +------------------------ + diff --git a/src/doc/unstable-book/src/trace-macros.md b/src/doc/unstable-book/src/trace-macros.md index 84efabd8502..856f1b0a7bb 100644 --- a/src/doc/unstable-book/src/trace-macros.md +++ b/src/doc/unstable-book/src/trace-macros.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29598] [#29598]: https://github.com/rust-lang/rust/issues/29598 +------------------------ + diff --git a/src/doc/unstable-book/src/type-ascription.md b/src/doc/unstable-book/src/type-ascription.md index 2decf512e91..3ebd0d87ccf 100644 --- a/src/doc/unstable-book/src/type-ascription.md +++ b/src/doc/unstable-book/src/type-ascription.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#23416] [#23416]: https://github.com/rust-lang/rust/issues/23416 +------------------------ + diff --git a/src/doc/unstable-book/src/unboxed-closures.md b/src/doc/unstable-book/src/unboxed-closures.md index 0d1eafb9e1d..2cbb436ce0b 100644 --- a/src/doc/unstable-book/src/unboxed-closures.md +++ b/src/doc/unstable-book/src/unboxed-closures.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29625] [#29625]: https://github.com/rust-lang/rust/issues/29625 +------------------------ + diff --git a/src/doc/unstable-book/src/untagged-unions.md b/src/doc/unstable-book/src/untagged-unions.md index 748f49eec6a..6fe4f088ac2 100644 --- a/src/doc/unstable-book/src/untagged-unions.md +++ b/src/doc/unstable-book/src/untagged-unions.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32836] [#32836]: https://github.com/rust-lang/rust/issues/32836 +------------------------ + diff --git a/src/doc/unstable-book/src/unwind-attributes.md b/src/doc/unstable-book/src/unwind-attributes.md index 5ba39afbcf8..0167a33b081 100644 --- a/src/doc/unstable-book/src/unwind-attributes.md +++ b/src/doc/unstable-book/src/unwind-attributes.md @@ -2,3 +2,5 @@ The tracking issue for this feature is: None. +------------------------ + diff --git a/src/doc/unstable-book/src/use-extern-macros.md b/src/doc/unstable-book/src/use-extern-macros.md index 120e00b2551..bc614911502 100644 --- a/src/doc/unstable-book/src/use-extern-macros.md +++ b/src/doc/unstable-book/src/use-extern-macros.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35896] [#35896]: https://github.com/rust-lang/rust/issues/35896 +------------------------ + diff --git a/src/doc/unstable-book/src/windows-subsystem.md b/src/doc/unstable-book/src/windows-subsystem.md index 78b040c0f26..80583352fbf 100644 --- a/src/doc/unstable-book/src/windows-subsystem.md +++ b/src/doc/unstable-book/src/windows-subsystem.md @@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37499] [#37499]: https://github.com/rust-lang/rust/issues/37499 +------------------------ + |
