diff --git a/src/doc/grammar.md b/src/doc/grammar.md index 7bfe8b62e8a5d..0fd3070d3bd80 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -258,7 +258,7 @@ symbol : "::" | "->" | ',' | ';' ; ``` -Symbols are a general class of printable [token](#tokens) that play structural +Symbols are a general class of printable [tokens](#tokens) that play structural roles in a variety of grammar productions. They are catalogued here for completeness as the set of remaining miscellaneous printable tokens that do not otherwise appear as [unary operators](#unary-operator-expressions), [binary diff --git a/src/doc/reference.md b/src/doc/reference.md index aba7bed842e88..c85b7973ee752 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -418,7 +418,7 @@ The two values of the boolean type are written `true` and `false`. ### Symbols -Symbols are a general class of printable [token](#tokens) that play structural +Symbols are a general class of printable [tokens](#tokens) that play structural roles in a variety of grammar productions. They are catalogued here for completeness as the set of remaining miscellaneous printable tokens that do not otherwise appear as [unary operators](#unary-operator-expressions), [binary @@ -984,99 +984,6 @@ The type parameters can also be explicitly supplied in a trailing there is not sufficient context to determine the type parameters. For example, `mem::size_of::() == 4`. -#### Unsafety - -Unsafe operations are those that potentially violate the memory-safety -guarantees of Rust's static semantics. - -The following language level features cannot be used in the safe subset of -Rust: - -- Dereferencing a [raw pointer](#pointer-types). -- Reading or writing a [mutable static variable](#mutable-statics). -- Calling an unsafe function (including an intrinsic or foreign function). - -##### Unsafe functions - -Unsafe functions are functions that are not safe in all contexts and/or for all -possible inputs. Such a function must be prefixed with the keyword `unsafe` and -can only be called from an `unsafe` block or another `unsafe` function. - -##### Unsafe blocks - -A block of code can be prefixed with the `unsafe` keyword, to permit calling -`unsafe` functions or dereferencing raw pointers within a safe function. - -When a programmer has sufficient conviction that a sequence of potentially -unsafe operations is actually safe, they can encapsulate that sequence (taken -as a whole) within an `unsafe` block. The compiler will consider uses of such -code safe, in the surrounding context. - -Unsafe blocks are used to wrap foreign libraries, make direct use of hardware -or implement features not directly present in the language. For example, Rust -provides the language features necessary to implement memory-safe concurrency -in the language but the implementation of threads and message passing is in the -standard library. - -Rust's type system is a conservative approximation of the dynamic safety -requirements, so in some cases there is a performance cost to using safe code. -For example, a doubly-linked list is not a tree structure and can only be -represented with reference-counted pointers in safe code. By using `unsafe` -blocks to represent the reverse links as raw pointers, it can be implemented -with only boxes. - -##### Behavior considered undefined - -The following is a list of behavior which is forbidden in all Rust code, -including within `unsafe` blocks and `unsafe` functions. Type checking provides -the guarantee that these issues are never caused by safe code. - -* Data races -* Dereferencing a null/dangling raw pointer -* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values) - (uninitialized) memory -* Breaking the [pointer aliasing - rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules) - with raw pointers (a subset of the rules used by C) -* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T` - contains an `UnsafeCell`. Unsafe code must not violate these aliasing - guarantees. -* Mutating non-mutable data (that is, data reached through a shared reference or - data owned by a `let` binding), unless that data is contained within an `UnsafeCell`. -* Invoking undefined behavior via compiler intrinsics: - * Indexing outside of the bounds of an object with `std::ptr::offset` - (`offset` intrinsic), with - the exception of one byte past the end which is permitted. - * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` - intrinsics) on overlapping buffers -* Invalid values in primitive types, even in private fields/locals: - * Dangling/null references or boxes - * A value other than `false` (0) or `true` (1) in a `bool` - * A discriminant in an `enum` not included in the type definition - * A value in a `char` which is a surrogate or above `char::MAX` - * Non-UTF-8 byte sequences in a `str` -* Unwinding into Rust from foreign code or unwinding from Rust into foreign - code. Rust's failure system is not compatible with exception handling in - other languages. Unwinding must be caught and handled at FFI boundaries. - -[noalias]: http://llvm.org/docs/LangRef.html#noalias - -##### Behavior not considered unsafe - -This is a list of behavior not considered *unsafe* in Rust terms, but that may -be undesired. - -* Deadlocks -* Leaks of memory and other resources -* Exiting without calling destructors -* Integer overflow - - Overflow is considered "unexpected" behavior and is always user-error, - unless the `wrapping` primitives are used. In non-optimized builds, the compiler - will insert debug checks that panic on overflow, but in optimized builds overflow - instead results in wrapped values. See [RFC 560] for the rationale and more details. - -[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md - #### Diverging functions A special kind of function can be declared with a `!` character where the @@ -4050,6 +3957,99 @@ In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for all compilation needs, and the other options are just available if more fine-grained control is desired over the output format of a Rust crate. +# Unsafety + +Unsafe operations are those that potentially violate the memory-safety +guarantees of Rust's static semantics. + +The following language level features cannot be used in the safe subset of +Rust: + +- Dereferencing a [raw pointer](#pointer-types). +- Reading or writing a [mutable static variable](#mutable-statics). +- Calling an unsafe function (including an intrinsic or foreign function). + +## Unsafe functions + +Unsafe functions are functions that are not safe in all contexts and/or for all +possible inputs. Such a function must be prefixed with the keyword `unsafe` and +can only be called from an `unsafe` block or another `unsafe` function. + +## Unsafe blocks + +A block of code can be prefixed with the `unsafe` keyword, to permit calling +`unsafe` functions or dereferencing raw pointers within a safe function. + +When a programmer has sufficient conviction that a sequence of potentially +unsafe operations is actually safe, they can encapsulate that sequence (taken +as a whole) within an `unsafe` block. The compiler will consider uses of such +code safe, in the surrounding context. + +Unsafe blocks are used to wrap foreign libraries, make direct use of hardware +or implement features not directly present in the language. For example, Rust +provides the language features necessary to implement memory-safe concurrency +in the language but the implementation of threads and message passing is in the +standard library. + +Rust's type system is a conservative approximation of the dynamic safety +requirements, so in some cases there is a performance cost to using safe code. +For example, a doubly-linked list is not a tree structure and can only be +represented with reference-counted pointers in safe code. By using `unsafe` +blocks to represent the reverse links as raw pointers, it can be implemented +with only boxes. + +## Behavior considered undefined + +The following is a list of behavior which is forbidden in all Rust code, +including within `unsafe` blocks and `unsafe` functions. Type checking provides +the guarantee that these issues are never caused by safe code. + +* Data races +* Dereferencing a null/dangling raw pointer +* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values) + (uninitialized) memory +* Breaking the [pointer aliasing + rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules) + with raw pointers (a subset of the rules used by C) +* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T` + contains an `UnsafeCell`. Unsafe code must not violate these aliasing + guarantees. +* Mutating non-mutable data (that is, data reached through a shared reference or + data owned by a `let` binding), unless that data is contained within an `UnsafeCell`. +* Invoking undefined behavior via compiler intrinsics: + * Indexing outside of the bounds of an object with `std::ptr::offset` + (`offset` intrinsic), with + the exception of one byte past the end which is permitted. + * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` + intrinsics) on overlapping buffers +* Invalid values in primitive types, even in private fields/locals: + * Dangling/null references or boxes + * A value other than `false` (0) or `true` (1) in a `bool` + * A discriminant in an `enum` not included in the type definition + * A value in a `char` which is a surrogate or above `char::MAX` + * Non-UTF-8 byte sequences in a `str` +* Unwinding into Rust from foreign code or unwinding from Rust into foreign + code. Rust's failure system is not compatible with exception handling in + other languages. Unwinding must be caught and handled at FFI boundaries. + +[noalias]: http://llvm.org/docs/LangRef.html#noalias + +## Behavior not considered unsafe + +This is a list of behavior not considered *unsafe* in Rust terms, but that may +be undesired. + +* Deadlocks +* Leaks of memory and other resources +* Exiting without calling destructors +* Integer overflow + - Overflow is considered "unexpected" behavior and is always user-error, + unless the `wrapping` primitives are used. In non-optimized builds, the compiler + will insert debug checks that panic on overflow, but in optimized builds overflow + instead results in wrapped values. See [RFC 560] for the rationale and more details. + +[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md + # Appendix: Influences Rust is not a particularly original language, with design elements coming from 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/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/iterators.md b/src/doc/trpl/iterators.md index 6d1e66b67334f..3350df4ff7f18 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -42,12 +42,12 @@ loop is just a handy way to write this `loop`/`match`/`break` construct. `for` loops aren't the only thing that uses iterators, however. Writing your own iterator involves implementing the `Iterator` trait. While doing that is outside of the scope of this guide, Rust provides a number of useful iterators -to accomplish various tasks. Before we talk about those, we should talk about a -Rust anti-pattern. And that's using ranges like this. +to accomplish various tasks. But first, a few notes about limitations of ranges. -Yes, we just talked about how ranges are cool. But ranges are also very -primitive. For example, if you needed to iterate over the contents of a vector, -you may be tempted to write this: +Ranges are very primitive, and we often can use better alternatives. Consider +following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Let’s +suppose you needed to iterate over the contents of a vector. You may be tempted +to write this: ```rust let nums = vec![1, 2, 3]; @@ -281,8 +281,8 @@ If you are trying to execute a closure on an iterator for its side effects, just use `for` instead. There are tons of interesting iterator adapters. `take(n)` will return an -iterator over the next `n` elements of the original iterator. Let's try it out with our infinite -iterator from before: +iterator over the next `n` elements of the original iterator. Let's try it out +with an infinite iterator: ```rust for i in (1..).take(5) { diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index 4896be714bb89..23569dd1b917e 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -43,11 +43,11 @@ With that in mind, let’s learn about lifetimes. Lending out a reference to a resource that someone else owns can be complicated. For example, imagine this set of operations: -- I acquire a handle to some kind of resource. -- I lend you a reference to the resource. -- I decide I’m done with the resource, and deallocate it, while you still have +1. I acquire a handle to some kind of resource. +2. I lend you a reference to the resource. +3. I decide I’m done with the resource, and deallocate it, while you still have your reference. -- You decide to use the resource. +4. You decide to use the resource. Uh oh! Your reference is pointing to an invalid resource. This is called a dangling pointer or ‘use after free’, when the resource is memory. diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index a365732fe9bd1..8f4a7a439553b 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -23,6 +23,31 @@ match x { This prints `one`. +There’s one pitfall with patterns: like anything that introduces a new binding, +they introduce shadowing. For example: + +```rust +let x = 'x'; +let c = 'c'; + +match c { + x => println!("x: {} c: {}", x, c), +} + +println!("x: {}", x) +``` + +This prints: + +```text +x: c c: c +x: x +``` + +In other words, `x =>` matches the pattern and introduces a new binding named +`x` that’s in scope for the match arm. Because we already have a binding named +`x`, this new `x` shadows it. + # Multiple patterns You can match multiple patterns with `|`: @@ -299,7 +324,7 @@ match x { ``` This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to -just the `5`, In other words, the the precedence of `if` behaves like this: +just the `5`. In other words, the precedence of `if` behaves like this: ```text (4 | 5) if y => ... diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index 0870a6ef34147..27debf86e396b 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -492,3 +492,32 @@ If we forget to implement `Foo`, Rust will tell us: ```text error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277] ``` + +# Deriving + +Implementing traits like `Debug` and `Default` over and over again can become +quite tedious. For that reason, Rust provides an [attribute][attributes] that +allows you to let Rust automatically implement traits for you: + +```rust +#[derive(Debug)] +struct Foo; + +fn main() { + println!("{:?}", Foo); +} +``` + +[attributes]: attributes.html + +However, deriving is limited to a certain set of traits: + +- [`Clone`](../core/clone/trait.Clone.html) +- [`Copy`](../core/marker/trait.Copy.html) +- [`Debug`](../core/fmt/trait.Debug.html) +- [`Default`](../core/default/trait.Default.html) +- [`Eq`](../core/cmp/trait.Eq.html) +- [`Hash`](../core/hash/trait.Hash.html) +- [`Ord`](../core/cmp/trait.Ord.html) +- [`PartialEq`](../core/cmp/trait.PartialEq.html) +- [`PartialOrd`](../core/cmp/trait.PartialOrd.html) diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 764d12dd90334..0d4c0bb648008 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -61,7 +61,8 @@ pub struct DebugStruct<'a, 'b: 'a> { has_fields: bool, } -pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) +pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, + name: &str) -> DebugStruct<'a, 'b> { let result = fmt.write_str(name); DebugStruct { @@ -84,7 +85,8 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { if self.is_pretty() { let mut writer = PadAdapter::new(self.fmt); - fmt::write(&mut writer, format_args!("{}\n{}: {:#?}", prefix, name, value)) + fmt::write(&mut writer, + format_args!("{}\n{}: {:#?}", prefix, name, value)) } else { write!(self.fmt, "{} {}: {:?}", prefix, name, value) } @@ -195,10 +197,18 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { self.result = self.result.and_then(|_| { if self.is_pretty() { let mut writer = PadAdapter::new(self.fmt); - let prefix = if self.has_fields { "," } else { "" }; + let prefix = if self.has_fields { + "," + } else { + "" + }; fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry)) } else { - let prefix = if self.has_fields { ", " } else { "" }; + let prefix = if self.has_fields { + ", " + } else { + "" + }; write!(self.fmt, "{}{:?}", prefix, entry) } }); @@ -207,7 +217,11 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { } pub fn finish(&mut self) { - let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" }; + let prefix = if self.is_pretty() && self.has_fields { + "\n" + } else { + "" + }; self.result = self.result.and_then(|_| self.fmt.write_str(prefix)); } @@ -232,7 +246,7 @@ pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b fmt: fmt, result: result, has_fields: false, - } + }, } } @@ -247,7 +261,9 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// Adds the contents of an iterator of entries to the set output. #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entries(&mut self, entries: I) -> &mut DebugSet<'a, 'b> - where D: fmt::Debug, I: IntoIterator { + where D: fmt::Debug, + I: IntoIterator + { for entry in entries { self.entry(&entry); } @@ -278,7 +294,7 @@ pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, fmt: fmt, result: result, has_fields: false, - } + }, } } @@ -293,7 +309,9 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// Adds the contents of an iterator of entries to the list output. #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entries(&mut self, entries: I) -> &mut DebugList<'a, 'b> - where D: fmt::Debug, I: IntoIterator { + where D: fmt::Debug, + I: IntoIterator + { for entry in entries { self.entry(&entry); } @@ -335,10 +353,19 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self.result = self.result.and_then(|_| { if self.is_pretty() { let mut writer = PadAdapter::new(self.fmt); - let prefix = if self.has_fields { "," } else { "" }; - fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value)) + let prefix = if self.has_fields { + "," + } else { + "" + }; + fmt::write(&mut writer, + format_args!("{}\n{:#?}: {:#?}", prefix, key, value)) } else { - let prefix = if self.has_fields { ", " } else { "" }; + let prefix = if self.has_fields { + ", " + } else { + "" + }; write!(self.fmt, "{}{:?}: {:?}", prefix, key, value) } }); @@ -350,7 +377,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// Adds the contents of an iterator of entries to the map output. #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entries(&mut self, entries: I) -> &mut DebugMap<'a, 'b> - where K: fmt::Debug, V: fmt::Debug, I: IntoIterator { + where K: fmt::Debug, + V: fmt::Debug, + I: IntoIterator + { for (k, v) in entries { self.entry(&k, &v); } @@ -360,7 +390,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// Finishes output and returns any error encountered. #[stable(feature = "debug_builders", since = "1.2.0")] pub fn finish(&mut self) -> fmt::Result { - let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" }; + let prefix = if self.is_pretty() && self.has_fields { + "\n" + } else { + "" + }; self.result.and_then(|_| write!(self.fmt, "{}}}", prefix)) } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 022fe6711bdb3..23642790a8898 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -48,7 +48,9 @@ trait GenericRadix { fn base(&self) -> u8; /// A radix-specific prefix string. - fn prefix(&self) -> &'static str { "" } + fn prefix(&self) -> &'static str { + "" + } /// Converts an integer to corresponding radix digit. fn digit(&self, x: u8) -> u8; @@ -70,7 +72,10 @@ trait GenericRadix { x = x / base; // Deaccumulate the number. *byte = self.digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; - if x == zero { break }; // No more digits left to accumulate. + if x == zero { + // No more digits left to accumulate. + break + }; } } else { // Do the same as above, but accounting for two's complement. @@ -79,7 +84,10 @@ trait GenericRadix { x = x / base; // Deaccumulate the number. *byte = self.digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; - if x == zero { break }; // No more digits left to accumulate. + if x == zero { + // No more digits left to accumulate. + break + }; } } let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) }; @@ -141,13 +149,17 @@ pub struct Radix { impl Radix { fn new(base: u8) -> Radix { - assert!(2 <= base && base <= 36, "the base must be in the range of 2..36: {}", base); + assert!(2 <= base && base <= 36, + "the base must be in the range of 2..36: {}", + base); Radix { base: base } } } impl GenericRadix for Radix { - fn base(&self) -> u8 { self.base } + fn base(&self) -> u8 { + self.base + } fn digit(&self, x: u8) -> u8 { match x { x @ 0 ... 9 => b'0' + x, diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 033834dd5aaaa..f889045a3f595 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -53,5 +53,5 @@ pub enum Count { #[derive(Copy, Clone)] pub enum Position { Next, - At(usize) + At(usize), } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 2a4c909d6384c..4e038f455e1be 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -100,7 +100,9 @@ pub trait Hash { /// Feeds a slice of this type into the state provided. #[stable(feature = "hash_slice", since = "1.3.0")] - fn hash_slice(data: &[Self], state: &mut H) where Self: Sized { + fn hash_slice(data: &[Self], state: &mut H) + where Self: Sized + { for piece in data { piece.hash(state); } @@ -121,7 +123,9 @@ pub trait Hasher { /// Write a single `u8` into this hasher #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] - fn write_u8(&mut self, i: u8) { self.write(&[i]) } + fn write_u8(&mut self, i: u8) { + self.write(&[i]) + } /// Write a single `u16` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] @@ -145,8 +149,7 @@ pub trait Hasher { #[stable(feature = "hasher_write", since = "1.3.0")] fn write_usize(&mut self, i: usize) { let bytes = unsafe { - ::slice::from_raw_parts(&i as *const usize as *const u8, - mem::size_of::()) + ::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::()) }; self.write(bytes); } @@ -154,23 +157,33 @@ pub trait Hasher { /// Write a single `i8` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] - fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) } + fn write_i8(&mut self, i: i8) { + self.write_u8(i as u8) + } /// Write a single `i16` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] - fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) } + fn write_i16(&mut self, i: i16) { + self.write_u16(i as u16) + } /// Write a single `i32` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] - fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) } + fn write_i32(&mut self, i: i32) { + self.write_u32(i as u32) + } /// Write a single `i64` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] - fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) } + fn write_i64(&mut self, i: i64) { + self.write_u64(i as u64) + } /// Write a single `isize` into this hasher. #[inline] #[stable(feature = "hasher_write", since = "1.3.0")] - fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) } + fn write_isize(&mut self, i: isize) { + self.write_usize(i as usize) + } } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 32a4f1e5bd761..722d77a8a11ef 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -37,12 +37,12 @@ pub struct SipHasher { // and simd implementations of SipHash will use vectors // of v02 and v13. By placing them in this order in the struct, // the compiler can pick up on just a few simd optimizations by itself. - v0: u64, // hash state + v0: u64, // hash state v2: u64, v1: u64, v3: u64, tail: u64, // unprocessed bytes le - ntail: usize, // how many bytes in tail are valid + ntail: usize, // how many bytes in tail are valid } // sadly, these macro definitions can't appear later, @@ -80,8 +80,7 @@ macro_rules! u8to64_le { unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 { debug_assert!(i + 8 <= buf.len()); let mut data = 0u64; - ptr::copy_nonoverlapping(buf.get_unchecked(i), - &mut data as *mut _ as *mut u8, 8); + ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8); data.to_le() } @@ -152,12 +151,12 @@ impl Hasher for SipHasher { if self.ntail != 0 { needed = 8 - self.ntail; if length < needed { - self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail; + self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail; self.ntail += length; return } - let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail; + let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail; self.v3 ^= m; compress!(self.v0, self.v1, self.v2, self.v3); diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 00c7773fd8ba8..3554325d0dbfc 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -935,7 +935,7 @@ pub trait Iterator { /// Creates an iterator that clones the elements it yields. /// - /// This is useful for converting an Iterator<&T> to an Iterator, + /// This is useful for converting an `Iterator<&T>` to an`Iterator`, /// so it's a more convenient form of `map(|&x| x)`. /// /// # Examples diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6507bb7bf8c82..e942e8b692351 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -39,7 +39,7 @@ use slice::SliceExt; /// all standard arithmetic operations on the underlying value are /// intended to have wrapping semantics. #[stable(feature = "rust1", since = "1.0.0")] -#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)] pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); pub mod wrapping; 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_driver/lib.rs b/src/librustc_driver/lib.rs index d5644d49e1ea4..e4f033efb58e3 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -285,7 +285,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { -> Compilation { match matches.opt_str("explain") { Some(ref code) => { - match descriptions.find_description(&code[..]) { + let normalised = if !code.starts_with("E") { + format!("E{0:0>4}", code) + } else { + code.to_string() + }; + match descriptions.find_description(&normalised) { Some(ref description) => { // Slice off the leading newline and print. print!("{}", &description[1..]); 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/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index 5ba678ce183dd..64d6a8109888e 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -39,134 +39,175 @@ // OF THE POSSIBILITY OF SUCH DAMAGE. use std::mem; +use std::ops::{Add, Sub, Mul}; const PI: f64 = 3.141592653589793; const SOLAR_MASS: f64 = 4.0 * PI * PI; const YEAR: f64 = 365.24; const N_BODIES: usize = 5; +const N_PAIRS: usize = N_BODIES * (N_BODIES - 1) / 2; -static BODIES: [Planet;N_BODIES] = [ +const BODIES: [Planet; N_BODIES] = [ // Sun Planet { - x: 0.0, y: 0.0, z: 0.0, - vx: 0.0, vy: 0.0, vz: 0.0, + pos: Vec3(0.0, 0.0, 0.0), + vel: Vec3(0.0, 0.0, 0.0), mass: SOLAR_MASS, }, // Jupiter Planet { - x: 4.84143144246472090e+00, - y: -1.16032004402742839e+00, - z: -1.03622044471123109e-01, - vx: 1.66007664274403694e-03 * YEAR, - vy: 7.69901118419740425e-03 * YEAR, - vz: -6.90460016972063023e-05 * YEAR, + pos: Vec3(4.84143144246472090e+00, + -1.16032004402742839e+00, + -1.03622044471123109e-01), + vel: Vec3(1.66007664274403694e-03 * YEAR, + 7.69901118419740425e-03 * YEAR, + -6.90460016972063023e-05 * YEAR), mass: 9.54791938424326609e-04 * SOLAR_MASS, }, // Saturn Planet { - x: 8.34336671824457987e+00, - y: 4.12479856412430479e+00, - z: -4.03523417114321381e-01, - vx: -2.76742510726862411e-03 * YEAR, - vy: 4.99852801234917238e-03 * YEAR, - vz: 2.30417297573763929e-05 * YEAR, + pos: Vec3(8.34336671824457987e+00, + 4.12479856412430479e+00, + -4.03523417114321381e-01), + vel: Vec3(-2.76742510726862411e-03 * YEAR, + 4.99852801234917238e-03 * YEAR, + 2.30417297573763929e-05 * YEAR), mass: 2.85885980666130812e-04 * SOLAR_MASS, }, // Uranus Planet { - x: 1.28943695621391310e+01, - y: -1.51111514016986312e+01, - z: -2.23307578892655734e-01, - vx: 2.96460137564761618e-03 * YEAR, - vy: 2.37847173959480950e-03 * YEAR, - vz: -2.96589568540237556e-05 * YEAR, + pos: Vec3(1.28943695621391310e+01, + -1.51111514016986312e+01, + -2.23307578892655734e-01), + vel: Vec3(2.96460137564761618e-03 * YEAR, + 2.37847173959480950e-03 * YEAR, + -2.96589568540237556e-05 * YEAR), mass: 4.36624404335156298e-05 * SOLAR_MASS, }, // Neptune Planet { - x: 1.53796971148509165e+01, - y: -2.59193146099879641e+01, - z: 1.79258772950371181e-01, - vx: 2.68067772490389322e-03 * YEAR, - vy: 1.62824170038242295e-03 * YEAR, - vz: -9.51592254519715870e-05 * YEAR, + pos: Vec3(1.53796971148509165e+01, + -2.59193146099879641e+01, + 1.79258772950371181e-01), + vel: Vec3(2.68067772490389322e-03 * YEAR, + 1.62824170038242295e-03 * YEAR, + -9.51592254519715870e-05 * YEAR), mass: 5.15138902046611451e-05 * SOLAR_MASS, }, ]; -#[derive(Copy, Clone)] +/// A 3d Vector type with oveloaded operators to improve readability. +#[derive(Clone, Copy)] +struct Vec3(pub f64, pub f64, pub f64); + +impl Vec3 { + fn zero() -> Self { Vec3(0.0, 0.0, 0.0) } + + fn norm(&self) -> f64 { self.squared_norm().sqrt() } + + fn squared_norm(&self) -> f64 { + self.0 * self.0 + self.1 * self.1 + self.2 * self.2 + } +} + +impl Add for Vec3 { + type Output = Self; + fn add(self, rhs: Self) -> Self { + Vec3(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2) + } +} + +impl Sub for Vec3 { + type Output = Self; + fn sub(self, rhs: Self) -> Self { + Vec3(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2) + } +} + +impl Mul for Vec3 { + type Output = Self; + fn mul(self, rhs: f64) -> Self { + Vec3(self.0 * rhs, self.1 * rhs, self.2 * rhs) + } +} + +#[derive(Clone, Copy)] struct Planet { - x: f64, y: f64, z: f64, - vx: f64, vy: f64, vz: f64, + pos: Vec3, + vel: Vec3, mass: f64, } -fn advance(bodies: &mut [Planet;N_BODIES], dt: f64, steps: isize) { - for _ in 0..steps { - let mut b_slice: &mut [_] = bodies; - loop { - let bi = match shift_mut_ref(&mut b_slice) { - Some(bi) => bi, - None => break - }; - for bj in &mut *b_slice { - let dx = bi.x - bj.x; - let dy = bi.y - bj.y; - let dz = bi.z - bj.z; - - let d2 = dx * dx + dy * dy + dz * dz; - let mag = dt / (d2 * d2.sqrt()); - - let massj_mag = bj.mass * mag; - bi.vx -= dx * massj_mag; - bi.vy -= dy * massj_mag; - bi.vz -= dz * massj_mag; - - let massi_mag = bi.mass * mag; - bj.vx += dx * massi_mag; - bj.vy += dy * massi_mag; - bj.vz += dz * massi_mag; - } - bi.x += dt * bi.vx; - bi.y += dt * bi.vy; - bi.z += dt * bi.vz; +/// Computes all pairwise position differences between the planets. +fn pairwise_diffs(bodies: &[Planet; N_BODIES], diff: &mut [Vec3; N_PAIRS]) { + let mut bodies = bodies.iter(); + let mut diff = diff.iter_mut(); + while let Some(bi) = bodies.next() { + for bj in bodies.clone() { + *diff.next().unwrap() = bi.pos - bj.pos; + } + } +} + +/// Computes the magnitude of the force between each pair of planets. +fn magnitudes(diff: &[Vec3; N_PAIRS], dt: f64, mag: &mut [f64; N_PAIRS]) { + for (mag, diff) in mag.iter_mut().zip(diff.iter()) { + let d2 = diff.squared_norm(); + *mag = dt / (d2 * d2.sqrt()); + } +} + +/// Updates the velocities of the planets by computing their gravitational +/// accelerations and performing one step of Euler integration. +fn update_velocities(bodies: &mut [Planet; N_BODIES], dt: f64, + diff: &mut [Vec3; N_PAIRS], mag: &mut [f64; N_PAIRS]) { + pairwise_diffs(bodies, diff); + magnitudes(&diff, dt, mag); + + let mut bodies = &mut bodies[..]; + let mut mag = mag.iter(); + let mut diff = diff.iter(); + while let Some(bi) = shift_mut_ref(&mut bodies) { + for bj in bodies.iter_mut() { + let diff = *diff.next().unwrap(); + let mag = *mag.next().unwrap(); + bi.vel = bi.vel - diff * (bj.mass * mag); + bj.vel = bj.vel + diff * (bi.mass * mag); } } } -fn energy(bodies: &[Planet;N_BODIES]) -> f64 { +/// Advances the solar system by one timestep by first updating the +/// velocities and then integrating the positions using the updated velocities. +/// +/// Note: the `diff` & `mag` arrays are effectively scratch space. They're +/// provided as arguments to avoid re-zeroing them every time `advance` is +/// called. +fn advance(mut bodies: &mut [Planet; N_BODIES], dt: f64, + diff: &mut [Vec3; N_PAIRS], mag: &mut [f64; N_PAIRS]) { + update_velocities(bodies, dt, diff, mag); + for body in bodies.iter_mut() { + body.pos = body.pos + body.vel * dt; + } +} + +/// Computes the total energy of the solar system. +fn energy(bodies: &[Planet; N_BODIES]) -> f64 { let mut e = 0.0; let mut bodies = bodies.iter(); - loop { - let bi = match bodies.next() { - Some(bi) => bi, - None => break - }; - e += (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz) * bi.mass / 2.0; - for bj in bodies.clone() { - let dx = bi.x - bj.x; - let dy = bi.y - bj.y; - let dz = bi.z - bj.z; - let dist = (dx * dx + dy * dy + dz * dz).sqrt(); - e -= bi.mass * bj.mass / dist; - } + while let Some(bi) = bodies.next() { + e += bi.vel.squared_norm() * bi.mass / 2.0 + - bi.mass * bodies.clone() + .map(|bj| bj.mass / (bi.pos - bj.pos).norm()) + .fold(0.0, |a, b| a + b); } e } -fn offset_momentum(bodies: &mut [Planet;N_BODIES]) { - let mut px = 0.0; - let mut py = 0.0; - let mut pz = 0.0; - for bi in bodies.iter() { - px += bi.vx * bi.mass; - py += bi.vy * bi.mass; - pz += bi.vz * bi.mass; - } - let sun = &mut bodies[0]; - sun.vx = - px / SOLAR_MASS; - sun.vy = - py / SOLAR_MASS; - sun.vz = - pz / SOLAR_MASS; +/// Offsets the sun's velocity to make the overall momentum of the system zero. +fn offset_momentum(bodies: &mut [Planet; N_BODIES]) { + let p = bodies.iter().fold(Vec3::zero(), |v, b| v + b.vel * b.mass); + bodies[0].vel = p * (-1.0 / bodies[0].mass); } fn main() { @@ -178,11 +219,15 @@ fn main() { .unwrap_or(1000) }; let mut bodies = BODIES; + let mut diff = [Vec3::zero(); N_PAIRS]; + let mut mag = [0.0f64; N_PAIRS]; offset_momentum(&mut bodies); println!("{:.9}", energy(&bodies)); - advance(&mut bodies, 0.01, n); + for _ in (0..n) { + advance(&mut bodies, 0.01, &mut diff, &mut mag); + } println!("{:.9}", energy(&bodies)); } 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"));