diff --git a/src/doc/style/style/comments.md b/src/doc/style/style/comments.md index b2d2d9ab6b4d6..3851187b52034 100644 --- a/src/doc/style/style/comments.md +++ b/src/doc/style/style/comments.md @@ -85,3 +85,20 @@ Use inner doc comments _only_ to document crates and file-level modules: //! //! The core library is a something something... ``` + +### Explain context. + +Rust doesn't have special constructors, only functions that return new +instances. These aren't visible in the automatically generated documentation +for a type, so you should specifically link to them: + +``` rust +/// An iterator that yields `None` forever after the underlying iterator +/// yields `None` once. +/// +/// These can be created through +/// [`iter.fuse()`](trait.Iterator.html#method.fuse). +pub struct Fuse { + // ... +} +``` 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/advanced-linking.md b/src/doc/trpl/advanced-linking.md index 921f27336f2dd..9ef6d5c2bffbb 100644 --- a/src/doc/trpl/advanced-linking.md +++ b/src/doc/trpl/advanced-linking.md @@ -26,7 +26,7 @@ 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 +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 @@ -71,7 +71,7 @@ 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`. You can compile +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: diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index 983af4a0efe7f..7d4452a4c8470 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -1,9 +1,10 @@ % Closures -Rust not only has named functions, but anonymous functions as well. Anonymous -functions that have an associated environment are called ‘closures’, because they -close over an environment. Rust has a really great implementation of them, as -we’ll see. +Sometimes it is useful to wrap up a function and _free variables_ for better +clarity and reuse. The free variables that can be used come from the +enclosing scope and are ‘closed over’ when used in the function. From this, we +get the name ‘closures’ and Rust provides a really great implementation of +them, as we’ll see. # Syntax @@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2)); ``` You’ll notice a few things about closures that are a bit different from regular -functions defined with `fn`. The first is that we did not need to +named functions defined with `fn`. The first is that we did not need to annotate the types of arguments the closure takes or the values it returns. We can: @@ -44,14 +45,15 @@ let plus_one = |x: i32| -> i32 { x + 1 }; assert_eq!(2, plus_one(1)); ``` -But we don’t have to. Why is this? Basically, it was chosen for ergonomic reasons. -While specifying the full type for named functions is helpful with things like -documentation and type inference, the types of closures are rarely documented -since they’re anonymous, and they don’t cause the kinds of error-at-a-distance -problems that inferring named function types can. +But we don’t have to. Why is this? Basically, it was chosen for ergonomic +reasons. While specifying the full type for named functions is helpful with +things like documentation and type inference, the full type signatures of +closures are rarely documented since they’re anonymous, and they don’t cause +the kinds of error-at-a-distance problems that inferring named function types +can. -The second is that the syntax is similar, but a bit different. I’ve added spaces -here for easier comparison: +The second is that the syntax is similar, but a bit different. I’ve added +spaces here for easier comparison: ```rust fn plus_one_v1 (x: i32) -> i32 { x + 1 } @@ -63,8 +65,8 @@ Small differences, but they’re similar. # Closures and their environment -Closures are called such because they ‘close over their environment’. It -looks like this: +The environment for a closure can include bindings from its enclosing scope in +addition to parameters and local bindings. It looks like this: ```rust let num = 5; @@ -197,9 +199,10 @@ frame. Without `move`, a closure may be tied to the stack frame that created it, while a `move` closure is self-contained. This means that you cannot generally return a non-`move` closure from a function, for example. -But before we talk about taking and returning closures, we should talk some more -about the way that closures are implemented. As a systems language, Rust gives -you tons of control over what your code does, and closures are no different. +But before we talk about taking and returning closures, we should talk some +more about the way that closures are implemented. As a systems language, Rust +gives you tons of control over what your code does, and closures are no +different. # Closure implementation @@ -288,9 +291,9 @@ isn’t interesting. The next part is: # some_closure(1) } ``` -Because `Fn` is a trait, we can bound our generic with it. In this case, our closure -takes a `i32` as an argument and returns an `i32`, and so the generic bound we use -is `Fn(i32) -> i32`. +Because `Fn` is a trait, we can bound our generic with it. In this case, our +closure takes a `i32` as an argument and returns an `i32`, and so the generic +bound we use is `Fn(i32) -> i32`. There’s one other key point here: because we’re bounding a generic with a trait, this will get monomorphized, and therefore, we’ll be doing static @@ -452,7 +455,7 @@ autogenerated name. The error also points out that the return type is expected to be a reference, but what we are trying to return is not. Further, we cannot directly assign a `'static` lifetime to an object. So we'll take a different approach and return -a "trait object" by `Box`ing up the `Fn`. This _almost_ works: +a ‘trait object’ by `Box`ing up the `Fn`. This _almost_ works: ```rust,ignore fn factory() -> Box i32> { diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 63eccc12b0f65..4a4648c7b563f 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -563,8 +563,8 @@ What's going on here? First, both `extern crate` and `use` allow renaming the thing that is being imported. So the crate is still called "phrases", but here we will refer to it as "sayings". Similarly, the first `use` statement pulls in the -`japanese::farewells` module from the crate, but makes it available as -`jp_farewells` as opposed to simply `farewells`. This can help to avoid +`japanese::greetings` module from the crate, but makes it available as +`ja_greetings` as opposed to simply `greetings`. This can help to avoid ambiguity when importing similarly-named items from different places. The second `use` statement uses a star glob to bring in _all_ symbols from the 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/libcore/option.rs b/src/libcore/option.rs index d1bb65d22904a..0e4c6d1676e63 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -706,7 +706,8 @@ impl Option { } impl<'a, T: Clone> Option<&'a T> { - /// Maps an Option<&T> to an Option by cloning the contents of the Option. + /// Maps an `Option<&T>` to an `Option` by cloning the contents of the + /// option. #[stable(feature = "rust1", since = "1.0.0")] pub fn cloned(self) -> Option { self.map(|t| t.clone()) diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs index dd7c3834e564a..05236a7a6fb28 100644 --- a/src/librustc_trans/diagnostics.rs +++ b/src/librustc_trans/diagnostics.rs @@ -12,6 +12,21 @@ register_long_diagnostics! { +E0515: r##" +A constant index expression was out of bounds. Erroneous code example: + +``` +let x = &[0, 1, 2][7]; // error: const index-expr is out of bounds +``` + +Please specify a valid index (not inferior to 0 or superior to array length). +Example: + +``` +let x = &[0, 1, 2][2]; // ok! +``` +"##, + } register_diagnostics! { diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 8e63f2788ed26..0cae0ae59ba57 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -628,8 +628,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if iv >= len { // FIXME #3170: report this earlier on in the const-eval // pass. Reporting here is a bit late. - cx.sess().span_err(e.span, - "const index-expr is out of bounds"); + span_err!(cx.sess(), e.span, E0515, + "const index-expr is out of bounds"); C_undef(val_ty(arr).element_type()) } else { const_get_elt(cx, arr, &[iv as c_uint]) diff --git a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs index 10bf096dae7f7..5c8db524cc2ed 100644 --- a/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs +++ b/src/test/run-pass/lexer-crlf-line-endings-string-literal-doc-comment.rs @@ -1,7 +1,7 @@ // ignore-tidy-cr ignore-license // ignore-tidy-cr (repeated again because of tidy bug) // license is ignored because tidy can't handle the CRLF here properly. - + // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -11,33 +11,33 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. - + // NB: this file needs CRLF line endings. The .gitattributes file in // this directory should enforce it. - + // ignore-pretty - + /// Doc comment that ends in CRLF pub fn foo() {} - + /** Block doc comment that * contains CRLF characters */ pub fn bar() {} - + fn main() { let s = "string literal"; assert_eq!(s, "string\nliteral"); - + let s = "literal with \ escaped newline"; assert_eq!(s, "literal with escaped newline"); - + let s = r"string literal"; assert_eq!(s, "string\nliteral"); - + // validate that our source file has CRLF endings let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs"); assert!(source.contains("string\r\nliteral"));