diff --git a/src/doc/index.md b/src/doc/index.md index 1e667d3600fb4..992b6eef5e801 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -98,3 +98,4 @@ languages: - [Korean](https://github.com/rust-kr/doc.rust-kr.org) - [Chinese](https://github.com/KaiserY/rust-book-chinese) - [Spanish](https://goyox86.github.io/elpr) +- [German](https://panicbit.github.io/rustbook-de) diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index ae2416018c8f7..fd02a7b1afa5b 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -68,5 +68,6 @@ * [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) * [Bibliography](bibliography.md) diff --git a/src/doc/trpl/custom-allocators.md b/src/doc/trpl/custom-allocators.md new file mode 100644 index 0000000000000..3e46f8153fbcf --- /dev/null +++ b/src/doc/trpl/custom-allocators.md @@ -0,0 +1,169 @@ +% 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 just 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,no_run +#![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. +#![feature(no_std)] +#![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 +} + +# // just needed to get rustdoc to test this +# fn main() {} +# #[lang = "panic_fmt"] fn panic_fmt() {} +# #[lang = "eh_personality"] fn eh_personality() {} +``` + +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 than 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/libcollections/str.rs b/src/libcollections/str.rs index 124fe3fab56e9..5f1ace19f6d74 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -867,6 +867,10 @@ impl str { /// ```rust,ignore /// assert_eq!(d, &["a", "b", "c"]); /// ``` + /// + /// Use [`.split_whitespace()`][split_whitespace] for this behavior. + /// + /// [split_whitespace]: #method.split_whitespace #[stable(feature = "rust1", since = "1.0.0")] pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { core_str::StrExt::split(self, pat) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 5ed7f4113ec91..7cb2de78e2c7d 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1992,6 +1992,39 @@ static A : &'static u32 = &S.a; // ok! ``` "##, +E0496: r##" +A lifetime name is shadowing another lifetime name. Erroneous code example: + +``` +struct Foo<'a> { + a: &'a i32, +} + +impl<'a> Foo<'a> { + fn f<'a>(x: &'a i32) { // error: lifetime name `'a` shadows a lifetime + // name that is already in scope + } +} +``` + +Please change the name of one of the lifetimes to remove this error. Example: + + +``` +struct Foo<'a> { + a: &'a i32, +} + +impl<'a> Foo<'a> { + fn f<'b>(x: &'b i32) { // ok! + } +} + +fn main() { +} +``` +"##, + E0497: r##" A stability attribute was used outside of the standard library. Erroneous code example: @@ -2072,7 +2105,6 @@ register_diagnostics! { E0491, // in type `..`, reference has a longer lifetime than the data it... E0492, // cannot borrow a constant which contains interior mutability E0495, // cannot infer an appropriate lifetime due to conflicting requirements - E0496, // .. name `..` shadows a .. name that is already in scope E0498, // malformed plugin attribute E0514, // metadata version mismatch } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index a7bb4043e7d81..8e63f2788ed26 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -630,7 +630,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // pass. Reporting here is a bit late. cx.sess().span_err(e.span, "const index-expr is out of bounds"); - C_undef(type_of::type_of(cx, bt).element_type()) + C_undef(val_ty(arr).element_type()) } else { const_get_elt(cx, arr, &[iv as c_uint]) } diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs new file mode 100644 index 0000000000000..519c4917c71b3 --- /dev/null +++ b/src/test/compile-fail/const-slice-oob.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const FOO: &'static[u32] = &[1, 2, 3]; +const BAR: u32 = FOO[5]; //~ ERROR const index-expr is out of bounds + +fn main() { + let _ = BAR; +}