TRPL Nightly -> Unstable Book

Port the chapters from TRPL's "Nightly Rust" section to the Unstable
Book, and remove it from TRPL.
This commit is contained in:
Steve Klabnik 2017-02-15 20:27:58 -05:00
parent aba4bf60f5
commit 6fb2545f77
104 changed files with 1261 additions and 1093 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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 dont 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;
}
```

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -1,145 +0,0 @@
# No stdlib
Rusts 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
dont 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`.

View File

@ -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));
}
```

View File

@ -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)

View File

@ -3,3 +3,5 @@
The tracking issue for this feature is: [#38487]
[#38487]: https://github.com/rust-lang/rust/issues/38487
------------------------

View File

@ -2,3 +2,4 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -4,5 +4,4 @@ The tracking issue for this feature is: [#36167]
[#36167]: https://github.com/rust-lang/rust/issues/36167
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: none.
------------------------

View File

@ -2,4 +2,6 @@
The tracking issue for this feature is: none.
------------------------

View File

@ -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));
}
```

View File

@ -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() {}
```

View File

@ -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() {}
```

View File

@ -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.

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -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

View File

@ -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 dont 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;
}
```

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29661]
[#29661]: https://github.com/rust-lang/rust/issues/29661
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34981]
[#34981]: https://github.com/rust-lang/rust/issues/34981
------------------------

View File

@ -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!()
}
}
```

View File

@ -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;
}
```

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29717]
[#29717]: https://github.com/rust-lang/rust/issues/29717
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32976]
[#32976]: https://github.com/rust-lang/rust/issues/32976
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29594]
[#29594]: https://github.com/rust-lang/rust/issues/29594
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29717]
[#29717]: https://github.com/rust-lang/rust/issues/29717
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29599]
[#29599]: https://github.com/rust-lang/rust/issues/29599
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34511]
[#34511]: https://github.com/rust-lang/rust/issues/34511
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#24111]
[#24111]: https://github.com/rust-lang/rust/issues/24111
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29947]
[#29947]: https://github.com/rust-lang/rust/issues/29947
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29642]
[#29642]: https://github.com/rust-lang/rust/issues/29642
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29644]
[#29644]: https://github.com/rust-lang/rust/issues/29644
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27336]
[#27336]: https://github.com/rust-lang/rust/issues/27336
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#33156]
[#33156]: https://github.com/rust-lang/rust/issues/33156
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34761]
[#34761]: https://github.com/rust-lang/rust/issues/34761
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#28498]
[#28498]: https://github.com/rust-lang/rust/issues/28498
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37854]
[#37854]: https://github.com/rust-lang/rust/issues/37854
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37340]
[#37340]: https://github.com/rust-lang/rust/issues/37340
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29635]
[#29635]: https://github.com/rust-lang/rust/issues/29635
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#34761]
[#34761]: https://github.com/rust-lang/rust/issues/34761
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35118]
[#35118]: https://github.com/rust-lang/rust/issues/35118
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#28237]
[#28237]: https://github.com/rust-lang/rust/issues/28237
------------------------

View File

@ -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.

View File

@ -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`.

View File

@ -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.

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37406]
[#37406]: https://github.com/rust-lang/rust/issues/37406
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29602]
[#29602]: https://github.com/rust-lang/rust/issues/29602
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29603]
[#29603]: https://github.com/rust-lang/rust/issues/29603
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29598]
[#29598]: https://github.com/rust-lang/rust/issues/29598
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37339]
[#37339]: https://github.com/rust-lang/rust/issues/37339
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29638]
[#29638]: https://github.com/rust-lang/rust/issues/29638
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29634]
[#29634]: https://github.com/rust-lang/rust/issues/29634
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32408]
[#32408]: https://github.com/rust-lang/rust/issues/32408
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27389]
[#27389]: https://github.com/rust-lang/rust/issues/27389
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32837]
[#32837]: https://github.com/rust-lang/rust/issues/32837
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35121]
[#35121]: https://github.com/rust-lang/rust/issues/35121
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29639]
[#29639]: https://github.com/rust-lang/rust/issues/29639
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29721]
[#29721]: https://github.com/rust-lang/rust/issues/29721
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#28979]
[#28979]: https://github.com/rust-lang/rust/issues/28979
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29628]
[#29628]: https://github.com/rust-lang/rust/issues/29628
------------------------

View File

@ -4,5 +4,6 @@ The tracking issue for this feature is: [#13231]
[#13231]: https://github.com/rust-lang/rust/issues/13231
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32837]
[#32837]: https://github.com/rust-lang/rust/issues/32837
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27779]
[#27779]: https://github.com/rust-lang/rust/issues/27779
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731]
[#27731]: https://github.com/rust-lang/rust/issues/27731
------------------------

View File

@ -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
------------------------

View File

@ -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`.

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#38356]
[#38356]: https://github.com/rust-lang/rust/issues/38356
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#32409]
[#32409]: https://github.com/rust-lang/rust/issues/32409
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29601]
[#29601]: https://github.com/rust-lang/rust/issues/29601
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#35626]
[#35626]: https://github.com/rust-lang/rust/issues/35626
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731]
[#27731]: https://github.com/rust-lang/rust/issues/27731
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29642]
[#29642]: https://github.com/rust-lang/rust/issues/29642
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731]
[#27731]: https://github.com/rust-lang/rust/issues/27731
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#27731]
[#27731]: https://github.com/rust-lang/rust/issues/27731
------------------------

View File

@ -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),
_ => {},
}
}
```

View File

@ -2,7 +2,7 @@
The tracking issue for this feature is: [#31844]
[#31844]: https://github.com/rust-lang/rust/issues/31844
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29633]
[#29633]: https://github.com/rust-lang/rust/issues/29633
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#37403]
[#37403]: https://github.com/rust-lang/rust/issues/37403
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29719]
[#29719]: https://github.com/rust-lang/rust/issues/29719
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#15701]
[#15701]: https://github.com/rust-lang/rust/issues/15701
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#38814]
[#38814]: https://github.com/rust-lang/rust/issues/38814
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#31434]
[#31434]: https://github.com/rust-lang/rust/issues/31434
------------------------

View File

@ -2,3 +2,5 @@
The tracking issue for this feature is: None.
------------------------

View File

@ -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)]

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29594]
[#29594]: https://github.com/rust-lang/rust/issues/29594
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29598]
[#29598]: https://github.com/rust-lang/rust/issues/29598
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#23416]
[#23416]: https://github.com/rust-lang/rust/issues/23416
------------------------

View File

@ -4,5 +4,7 @@ The tracking issue for this feature is: [#29625]
[#29625]: https://github.com/rust-lang/rust/issues/29625
------------------------

Some files were not shown because too many files have changed in this diff Show More