about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-04-18 19:24:06 +0000
committerbors <bors@rust-lang.org>2015-04-18 19:24:06 +0000
commit49a94f29bbe49bd26d14cbf87b0955bd4befb8c1 (patch)
tree708d53e4b619fb227aefd191af1d7be2f4121d2a /src
parenta81ce5f991148b3c701c6b4276cdcafe366cd8f4 (diff)
parent88601f8d7d0784a2fe502193b9d98edd3e7d88ea (diff)
downloadrust-49a94f29bbe49bd26d14cbf87b0955bd4befb8c1.tar.gz
rust-49a94f29bbe49bd26d14cbf87b0955bd4befb8c1.zip
Auto merge of #24562 - Manishearth:rollup, r=Manishearth
- Successful merges: #24466, #24472, #24532, #24542, #24548
- Failed merges: #24552
Diffstat (limited to 'src')
-rw-r--r--src/doc/complement-lang-faq.md2
-rw-r--r--src/doc/grammar.md9
-rw-r--r--src/doc/reference.md138
-rw-r--r--src/doc/trpl/lifetimes.md2
-rw-r--r--src/doc/trpl/move-semantics.md104
-rw-r--r--src/doc/trpl/references-and-borrowing.md2
-rw-r--r--src/librustc/diagnostics.rs115
-rw-r--r--src/librustc_trans/trans/adt.rs8
-rw-r--r--src/librustc_trans/trans/base.rs20
-rw-r--r--src/librustc_trans/trans/build.rs8
-rw-r--r--src/librustc_trans/trans/builder.rs7
-rw-r--r--src/librustc_trans/trans/foreign.rs4
-rw-r--r--src/librustc_trans/trans/intrinsic.rs11
-rw-r--r--src/libsyntax/diagnostics/plugin.rs21
14 files changed, 317 insertions, 134 deletions
diff --git a/src/doc/complement-lang-faq.md b/src/doc/complement-lang-faq.md
index 8238dd3a5ba..f731a78ef12 100644
--- a/src/doc/complement-lang-faq.md
+++ b/src/doc/complement-lang-faq.md
@@ -124,7 +124,7 @@ Yes. Calling C code from Rust is simple and exactly as efficient as calling C co
 
 Yes. The Rust code has to be exposed via an `extern` declaration, which makes it C-ABI compatible. Such a function can be passed to C code as a function pointer or, if given the `#[no_mangle]` attribute to disable symbol mangling, can be called directly from C code.
 
-## Why aren't function signatures inferred? Why only local slots?
+## Why aren't function signatures inferred? Why only local variables?
 
 * Mechanically, it simplifies the inference algorithm; inference only requires looking at one function at a time.
 * The same simplification goes double for human readers. A reader does not need an IDE running an inference algorithm across an entire crate to be able to guess at a function's argument types; it's always explicit and nearby.
diff --git a/src/doc/grammar.md b/src/doc/grammar.md
index 1ea3c7d7bd9..3d9a5bafbd7 100644
--- a/src/doc/grammar.md
+++ b/src/doc/grammar.md
@@ -5,8 +5,7 @@
 This document is the primary reference for the Rust programming language grammar. It
 provides only one kind of material:
 
-  - Chapters that formally define the language grammar and, for each
-    construct.
+  - Chapters that formally define the language grammar.
 
 This document does not serve as an introduction to the language. Background
 familiarity with the language is assumed. A separate [guide] is available to
@@ -427,7 +426,7 @@ meta_seq : meta_item [ ',' meta_seq ] ? ;
 **FIXME:** grammar?
 
 A _declaration statement_ is one that introduces one or more *names* into the
-enclosing statement block. The declared names may denote new slots or new
+enclosing statement block. The declared names may denote new variables or new
 items.
 
 #### Item declarations
@@ -441,7 +440,7 @@ function, enumeration, structure, type, static, trait, implementation or module
 scope to a narrow region containing all of its uses; it is otherwise identical
 in meaning to declaring the item outside the statement block.
 
-#### Slot declarations
+#### Variable declarations
 
 ```antlr
 let_decl : "let" pat [':' type ] ? [ init ] ? ';' ;
@@ -763,7 +762,7 @@ bound := path | lifetime
 
 ### Memory ownership
 
-### Memory slots
+### Variables
 
 ### Boxes
 
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 57110df0f9e..c159f6164c2 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -564,7 +564,7 @@ type_path_tail : '<' type_expr [ ',' type_expr ] + '>'
 
 A _path_ is a sequence of one or more path components _logically_ separated by
 a namespace qualifier (`::`). If a path consists of only one component, it may
-refer to either an [item](#items) or a [slot](#memory-slots) in a local control
+refer to either an [item](#items) or a [variable](#variables) in a local control
 scope. If a path has multiple components, it refers to an item.
 
 Every item has a _canonical path_ within its crate, but the path naming an item
@@ -735,13 +735,11 @@ Rust syntax is restricted in two ways:
 
 # Crates and source files
 
-Rust is a *compiled* language. Its semantics obey a *phase distinction*
-between compile-time and run-time. Those semantic rules that have a *static
-interpretation* govern the success or failure of compilation. We refer to
-these rules as "static semantics". Semantic rules called "dynamic semantics"
-govern the behavior of programs at run-time. A program that fails to compile
-due to violation of a compile-time rule has no defined dynamic semantics; the
-compiler should halt with an error report, and produce no executable artifact.
+Rust is a *compiled* language. Its semantics obey a *phase distinction* between
+compile-time and run-time. Those semantic rules that have a *static
+interpretation* govern the success or failure of compilation. Those semantics
+that have a *dynamic interpretation* govern the behavior of the program at
+run-time.
 
 The compilation model centers on artifacts called _crates_. Each compilation
 processes a single crate in source form, and if successful, produces a single
@@ -1064,9 +1062,9 @@ fn main() {}
 A _function item_ defines a sequence of [statements](#statements) and an
 optional final [expression](#expressions), along with a name and a set of
 parameters. Functions are declared with the keyword `fn`. Functions declare a
-set of *input* [*slots*](#memory-slots) as parameters, through which the caller
-passes arguments into the function, and an *output* [*slot*](#memory-slots)
-through which the function passes results back to the caller.
+set of *input* [*variables*](#variables) as parameters, through which the caller
+passes arguments into the function, and the *output* [*type*](#types)
+of the value the function will return to its caller on completion.
 
 A function may also be copied into a first-class *value*, in which case the
 value has the corresponding [*function type*](#function-types), and can be used
@@ -1229,7 +1227,7 @@ be undesired.
 #### Diverging functions
 
 A special kind of function can be declared with a `!` character where the
-output slot type would normally be. For example:
+output type would normally be. For example:
 
 ```
 fn my_err(s: &str) -> ! {
@@ -1302,18 +1300,11 @@ contiguous stack segments like C.
 
 A _type alias_ defines a new name for an existing [type](#types). Type
 aliases are declared with the keyword `type`. Every value has a single,
-specific type; the type-specified aspects of a value include:
+specific type, but may implement several different traits, or be compatible with
+several different type constraints.
 
-* Whether the value is composed of sub-values or is indivisible.
-* Whether the value represents textual or numerical information.
-* Whether the value represents integral or floating-point information.
-* The sequence of memory operations required to access the value.
-* The [kind](#type-kinds) of the type.
-
-For example, the type `(u8, u8)` defines the set of immutable values that are
-composite pairs, each containing two unsigned 8-bit integers accessed by
-pattern-matching and laid out in memory with the `x` component preceding the
-`y` component:
+For example, the following defines the type `Point` as a synonym for the type
+`(u8, u8)`, the type of pairs of unsigned 8 bit integers.:
 
 ```
 type Point = (u8, u8);
@@ -2551,7 +2542,7 @@ statements](#expression-statements).
 ### Declaration statements
 
 A _declaration statement_ is one that introduces one or more *names* into the
-enclosing statement block. The declared names may denote new slots or new
+enclosing statement block. The declared names may denote new variables or new
 items.
 
 #### Item declarations
@@ -2566,18 +2557,18 @@ in meaning to declaring the item outside the statement block.
 > **Note**: there is no implicit capture of the function's dynamic environment when
 > declaring a function-local item.
 
-#### Slot declarations
+#### Variable declarations
 
 ```{.ebnf .gram}
 let_decl : "let" pat [':' type ] ? [ init ] ? ';' ;
 init : [ '=' ] expr ;
 ```
 
-A _slot declaration_ introduces a new set of slots, given by a pattern. The
+A _variable declaration_ introduces a new set of variable, given by a pattern. The
 pattern may be followed by a type annotation, and/or an initializer expression.
 When no type annotation is given, the compiler will infer the type, or signal
 an error if insufficient type information is available for definite inference.
-Any slots introduced by a slot declaration are visible from the point of
+Any variables introduced by a variable declaration are visible from the point of
 declaration until the end of the enclosing block scope.
 
 ### Expression statements
@@ -2632,7 +2623,7 @@ of any reference that points to it.
 
 #### Moved and copied types
 
-When a [local variable](#memory-slots) is used as an
+When a [local variable](#variables) is used as an
 [rvalue](#lvalues,-rvalues-and-temporaries) the variable will either be moved
 or copied, depending on its type. All values whose type implements `Copy` are
 copied, all others are moved.
@@ -3042,10 +3033,9 @@ paren_expr_list : '(' expr_list ')' ;
 call_expr : expr paren_expr_list ;
 ```
 
-A _call expression_ invokes a function, providing zero or more input slots and
-an optional reference slot to serve as the function's output, bound to the
-`lval` on the right hand side of the call. If the function eventually returns,
-then the expression completes.
+A _call expression_ invokes a function, providing zero or more input variables
+and an optional location to move the function's output into. If the function
+eventually returns, then the expression completes.
 
 Some examples of call expressions:
 
@@ -3456,9 +3446,9 @@ return_expr : "return" expr ? ;
 ```
 
 Return expressions are denoted with the keyword `return`. Evaluating a `return`
-expression moves its argument into the output slot of the current function,
-destroys the current function activation frame, and transfers control to the
-caller frame.
+expression moves its argument into the designated output location for the
+current function call, destroys the current function activation frame, and
+transfers control to the caller frame.
 
 An example of a `return` expression:
 
@@ -3475,7 +3465,7 @@ fn max(a: i32, b: i32) -> i32 {
 
 ## Types
 
-Every slot, item and value in a Rust program has a type. The _type_ of a
+Every variable, item and value in a Rust program has a type. The _type_ of a
 *value* defines the interpretation of the memory holding it.
 
 Built-in types and type-constructors are tightly integrated into the language,
@@ -3493,7 +3483,7 @@ The primitive types are the following:
 * The machine-dependent integer and floating-point types.
 
 [^unittype]: The "unit" value `()` is *not* a sentinel "null pointer" value for
-    reference slots; the "unit" type is the implicit return type from functions
+    reference variables; the "unit" type is the implicit return type from functions
     otherwise lacking a return type, and can be used in other contexts (such as
     message-sending or type-parametric code) as a zero-size type.]
 
@@ -3831,18 +3821,20 @@ impl Printable for String {
 `self` refers to the value of type `String` that is the receiver for a call to
 the method `make_string`.
 
-# The `Copy` trait
+# Special traits
+
+Several traits define special evaluation behavior.
 
-Rust has a special trait, `Copy`, which when implemented changes the semantics
-of a value. Values whose type implements `Copy` are copied rather than moved
-upon assignment.
+## The `Copy` trait
 
-# The `Sized` trait
+The `Copy` trait changes the semantics of a type implementing it. Values whose
+type implements `Copy` are copied rather than moved upon assignment.
 
-`Sized` is a special trait which indicates that the size of this type is known
-at compile-time.
+## The `Sized` trait
 
-# The `Drop` trait
+The `Sized` trait indicates that the size of this type is known at compile-time.
+
+## The `Drop` trait
 
 The `Drop` trait provides a destructor, to be run whenever a value of this type
 is to be destroyed.
@@ -3850,10 +3842,12 @@ is to be destroyed.
 # Memory model
 
 A Rust program's memory consists of a static set of *items* and a *heap*.
-Immutable portions of the heap may be shared between threads, mutable portions
-may not.
+Immutable portions of the heap may be safely shared between threads, mutable
+portions may not be safely shared, but several mechanisms for effectively-safe
+sharing of mutable values, built on unsafe code but enforcing a safe locking
+discipline, exist in the standard library.
 
-Allocations in the stack consist of *slots*, and allocations in the heap
+Allocations in the stack consist of *variables*, and allocations in the heap
 consist of *boxes*.
 
 ### Memory allocation and lifetime
@@ -3872,10 +3866,11 @@ in the heap, heap allocations may outlive the frame they are allocated within.
 When a stack frame is exited, its local allocations are all released, and its
 references to boxes are dropped.
 
-### Memory slots
+### Variables
 
-A _slot_ is a component of a stack frame, either a function parameter, a
-[temporary](#lvalues,-rvalues-and-temporaries), or a local variable.
+A _variable_ is a component of a stack frame, either a named function parameter,
+an anonymous [temporary](#lvalues,-rvalues-and-temporaries), or a named local
+variable.
 
 A _local variable_ (or *stack-local* allocation) holds a value directly,
 allocated within the stack's memory. The value is a part of the stack frame.
@@ -3888,7 +3883,7 @@ Box<i32>, y: Box<i32>)` declare one mutable variable `x` and one immutable
 variable `y`).
 
 Methods that take either `self` or `Box<Self>` can optionally place them in a
-mutable slot by prefixing them with `mut` (similar to regular arguments):
+mutable variable by prefixing them with `mut` (similar to regular arguments):
 
 ```
 trait Changer {
@@ -3903,44 +3898,7 @@ state. Subsequent statements within a function may or may not initialize the
 local variables. Local variables can be used only after they have been
 initialized; this is enforced by the compiler.
 
-# Runtime services, linkage and debugging
-
-The Rust _runtime_ is a relatively compact collection of Rust code that
-provides fundamental services and datatypes to all Rust threads at run-time. It
-is smaller and simpler than many modern language runtimes. It is tightly
-integrated into the language's execution model of memory, threads, communication
-and logging.
-
-### Memory allocation
-
-The runtime memory-management system is based on a _service-provider
-interface_, through which the runtime requests blocks of memory from its
-environment and releases them back to its environment when they are no longer
-needed. The default implementation of the service-provider interface consists
-of the C runtime functions `malloc` and `free`.
-
-The runtime memory-management system, in turn, supplies Rust threads with
-facilities for allocating releasing stacks, as well as allocating and freeing
-heap data.
-
-### Built in types
-
-The runtime provides C and Rust code to assist with various built-in types,
-such as arrays, strings, and the low level communication system (ports,
-channels, threads).
-
-Support for other built-in types such as simple types, tuples and enums is
-open-coded by the Rust compiler.
-
-### Thread scheduling and communication
-
-The runtime provides code to manage inter-thread communication. This includes
-the system of thread-lifecycle state transitions depending on the contents of
-queues, as well as code to copy values between queues and their recipients and
-to serialize values for transmission over operating-system inter-process
-communication facilities.
-
-### Linkage
+# Linkage
 
 The Rust compiler supports various methods to link crates together both
 statically and dynamically. This section will explore the various methods to
diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md
index c6eee97dc6a..cfcd8c4ee15 100644
--- a/src/doc/trpl/lifetimes.md
+++ b/src/doc/trpl/lifetimes.md
@@ -1,3 +1,3 @@
 % Lifetimes
 
-Coming soon!
+Coming Soon! Until then, check out the [ownership](ownership.html) chapter.
diff --git a/src/doc/trpl/move-semantics.md b/src/doc/trpl/move-semantics.md
index 6917d7f8b8e..b5bd53e1d75 100644
--- a/src/doc/trpl/move-semantics.md
+++ b/src/doc/trpl/move-semantics.md
@@ -1,3 +1,105 @@
 % Move Semantics
 
-Coming Soon
+An important aspect of [ownership][ownership] is ‘move semantics’. Move
+semantics control how and when ownership is transferred between bindings.
+
+[ownership]: ownership.html
+
+For example, consider a type like `Vec<T>`, which owns its contents:
+
+```rust
+let v = vec![1, 2, 3];
+```
+
+I can assign this vector to another binding:
+
+```rust
+let v = vec![1, 2, 3];
+
+let v2 = v;
+```
+
+But, if we try to use `v` afterwards, we get an error:
+
+```rust,ignore
+let v = vec![1, 2, 3];
+
+let v2 = v;
+
+println!("v[0] is: {}", v[0]);
+```
+
+It looks like this:
+
+```text
+error: use of moved value: `v`
+println!("v[0] is: {}", v[0]);
+                        ^
+```
+
+A similar thing happens if we define a function which takes ownership, and
+try to use something after we’ve passed it as an argument:
+
+```rust,ignore
+fn take(v: Vec<i32>) {
+    // what happens here isn’t important.
+}
+
+let v = vec![1, 2, 3];
+
+take(v);
+
+println!("v[0] is: {}", v[0]);
+```
+
+Same error: “use of moved value.” When we transfer ownership to something else,
+we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of
+special annotation here, it’s the default thing that Rust does.
+
+# The details
+
+The reason that we cannot use a binding after we’ve moved it is subtle, but
+important. When we write code like this:
+
+```rust
+let v = vec![1, 2, 3];
+
+let v2 = v;
+```
+
+The first line creates some data for the vector on the stack, `v`. The vector’s
+data, however, is stored on the heap, and so it contains a pointer to that
+data. When we move `v` to `v2`, it creates a copy of that data, for `v2`. Which
+would mean two pointers to the contents of the vector on the heap. That would
+be a problem: it would violate Rust’s safety guarantees by introducing a data
+race. Therefore, Rust forbids using `v` after we’ve done the move.
+
+It’s also important to note that optimizations may remove the actual copy of
+the bytes, depending on circumstances. So it may not be as inefficient as it
+initially seems.
+
+# `Copy` types
+
+We’ve established that when ownership is transferred to another binding, you
+cannot use the original binding. However, there’s a [trait][traits] that changes this
+behavior, and it’s called `Copy`. We haven’t discussed traits yet, but for now,
+you can think of them as an annotation to a particular type that adds extra
+behavior. For example:
+
+```rust
+let v = 1;
+
+let v2 = v;
+
+println!("v is: {}", v);
+```
+
+In this case, `v` is an `i32`, which implements the `Copy` trait. This means
+that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
+But, unlike a move, we can still use `v` afterward. This is because an `i32`
+has no pointers to data somewhere else, copying it is a full copy.
+
+We will discuss how to make your own types `Copy` in the [traits][traits]
+section.
+
+[traits]: traits.html
diff --git a/src/doc/trpl/references-and-borrowing.md b/src/doc/trpl/references-and-borrowing.md
index 6acb326958d..0e13ea61264 100644
--- a/src/doc/trpl/references-and-borrowing.md
+++ b/src/doc/trpl/references-and-borrowing.md
@@ -1,3 +1,3 @@
 % References and Borrowing
 
-Coming Soon!
+Coming Soon! Until then, check out the [ownership](ownership.html) chapter.
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index e1eb8d74186..306d2cd102f 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -55,15 +55,17 @@ underscore `_` wildcard pattern can be added after all other patterns to match
 
 // FIXME: Remove duplication here?
 E0005: r##"
-Patterns used to bind names must be irrefutable, that is, they must guarantee that a
-name will be extracted in all cases. If you encounter this error you probably need
-to use a `match` or `if let` to deal with the possibility of failure.
+Patterns used to bind names must be irrefutable, that is, they must guarantee
+that a name will be extracted in all cases. If you encounter this error you
+probably need to use a `match` or `if let` to deal with the possibility of
+failure.
 "##,
 
 E0006: r##"
-Patterns used to bind names must be irrefutable, that is, they must guarantee that a
-name will be extracted in all cases. If you encounter this error you probably need
-to use a `match` or `if let` to deal with the possibility of failure.
+Patterns used to bind names must be irrefutable, that is, they must guarantee
+that a name will be extracted in all cases. If you encounter this error you
+probably need to use a `match` or `if let` to deal with the possibility of
+failure.
 "##,
 
 E0007: r##"
@@ -112,6 +114,65 @@ reference when using guards or refactor the entire expression, perhaps by
 putting the condition inside the body of the arm.
 "##,
 
+E0009: r##"
+In a pattern, all values that don't implement the `Copy` trait have to be bound
+the same way. The goal here is to avoid binding simultaneously by-move and
+by-ref.
+
+This limitation may be removed in a future version of Rust.
+
+Wrong example:
+
+```
+struct X { x: (), }
+
+let x = Some((X { x: () }, X { x: () }));
+match x {
+    Some((y, ref z)) => {},
+    None => panic!()
+}
+```
+
+You have two solutions:
+1. Bind the pattern's values the same way:
+
+```
+struct X { x: (), }
+
+let x = Some((X { x: () }, X { x: () }));
+match x {
+    Some((ref y, ref z)) => {},
+    // or Some((y, z)) => {}
+    None => panic!()
+}
+```
+
+2. Implement the `Copy` trait for the X structure (however, please
+keep in mind that the first solution should be preferred!):
+
+```
+#[derive(Clone, Copy)]
+struct X { x: (), }
+
+let x = Some((X { x: () }, X { x: () }));
+match x {
+    Some((y, ref z)) => {},
+    None => panic!()
+}
+```
+"##,
+
+E0015: r##"
+The only function calls allowed in static or constant expressions are enum
+variant constructors or struct constructors (for unit or tuple structs). This
+is because Rust currently does not support compile-time function execution.
+"##,
+
+E0020: r##"
+This error indicates that an attempt was made to divide by zero (or take the
+remainder of a zero divisor) in a static or constant expression.
+"##,
+
 E0152: r##"
 Lang items are already implemented in the standard library. Unless you are
 writing a free-standing application (e.g. a kernel), you do not need to provide
@@ -217,6 +278,26 @@ use Method::*;
 enum Method { GET, POST }
 "##,
 
+E0267: r##"
+This error indicates the use of loop keyword (break or continue) inside a
+closure but outside of any loop. Break and continue can be used as normal
+inside closures as long as they are also contained within a loop. To halt the
+execution of a closure you should instead use a return statement.
+"##,
+
+E0268: r##"
+This error indicates the use of loop keyword (break or continue) outside of a
+loop. Without a loop to break out of or continue in, no sensible action can be
+taken.
+"##,
+
+E0296: r##"
+This error indicates that the given recursion limit could not be parsed. Ensure
+that the value provided is a positive integer between quotes, like so:
+
+#![recursion_limit="1000"]
+"##,
+
 E0297: r##"
 Patterns used to bind names must be irrefutable. That is, they must guarantee
 that a name will be extracted in all cases. Instead of pattern matching the
@@ -277,21 +358,23 @@ In certain cases it is possible for sub-bindings to violate memory safety.
 Updates to the borrow checker in a future version of Rust may remove this
 restriction, but for now patterns must be rewritten without sub-bindings.
 
-// Code like this...
-match Some(5) {
-    ref op_num @ Some(num) => ...
+// Before.
+match Some("hi".to_string()) {
+    ref op_string_ref @ Some(ref s) => ...
     None => ...
 }
 
-// ... should be updated to code like this.
-match Some(5) {
-    Some(num) => {
-        let op_num = &Some(num);
+// After.
+match Some("hi".to_string()) {
+    Some(ref s) => {
+        let op_string_ref = &Some(&s);
         ...
     }
     None => ...
 }
 
+The `op_string_ref` binding has type &Option<&String> in both cases.
+
 See also https://github.com/rust-lang/rust/issues/14587
 "##,
 
@@ -308,18 +391,15 @@ a compile-time constant.
 }
 
 register_diagnostics! {
-    E0009,
     E0010,
     E0011,
     E0012,
     E0013,
     E0014,
-    E0015,
     E0016,
     E0017,
     E0018,
     E0019,
-    E0020,
     E0022,
     E0079, // enum variant: expected signed integer constant
     E0080, // enum variant: constant evaluation error
@@ -338,8 +418,6 @@ register_diagnostics! {
     E0264, // unknown external lang item
     E0265, // recursive constant
     E0266, // expected item
-    E0267, // thing inside of a closure
-    E0268, // thing outside of a loop
     E0269, // not all control paths return a value
     E0270, // computation may converge in a function marked as diverging
     E0271, // type mismatch resolving
@@ -357,7 +435,6 @@ register_diagnostics! {
     E0283, // cannot resolve type
     E0284, // cannot resolve type
     E0285, // overflow evaluation builtin bounds
-    E0296, // malformed recursion limit attribute
     E0298, // mismatched types between arms
     E0299, // mismatched types between arms
     E0300, // unexpanded macro
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index f574b4ed8db..ffa068a2ae4 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -880,7 +880,7 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
         CEnum(ity, min, max) => {
             assert_discr_in_range(ity, min, max, discr);
             Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
-                  val)
+                  val);
         }
         General(ity, ref cases, dtor) => {
             if dtor_active(dtor) {
@@ -889,7 +889,7 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
                 Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED as usize), ptr);
             }
             Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
-                  GEPi(bcx, val, &[0, 0]))
+                  GEPi(bcx, val, &[0, 0]));
         }
         Univariant(ref st, dtor) => {
             assert_eq!(discr, 0);
@@ -901,14 +901,14 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
         RawNullablePointer { nndiscr, nnty, ..} => {
             if discr != nndiscr {
                 let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty);
-                Store(bcx, C_null(llptrty), val)
+                Store(bcx, C_null(llptrty), val);
             }
         }
         StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
             if discr != nndiscr {
                 let llptrptr = GEPi(bcx, val, &discrfield[..]);
                 let llptrty = val_ty(llptrptr).element_type();
-                Store(bcx, C_null(llptrty), llptrptr)
+                Store(bcx, C_null(llptrty), llptrptr);
             }
         }
     }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 023f9e0bda1..59f3ff72602 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -765,9 +765,14 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     }
 
     let ptr = to_arg_ty_ptr(cx, ptr, t);
+    let align = type_of::align_of(cx.ccx(), t);
 
     if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
-        return Load(cx, ptr);
+        let load = Load(cx, ptr);
+        unsafe {
+            llvm::LLVMSetAlignment(load, align);
+        }
+        return load;
     }
 
     unsafe {
@@ -793,13 +798,24 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         Load(cx, ptr)
     };
 
+    unsafe {
+        llvm::LLVMSetAlignment(val, align);
+    }
+
     from_arg_ty(cx, val, t)
 }
 
 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
 /// differs from the type used for SSA values.
 pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
-    Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
+    if cx.unreachable.get() {
+        return;
+    }
+
+    let store = Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
+    unsafe {
+        llvm::LLVMSetAlignment(store, type_of::align_of(cx.ccx(), t));
+    }
 }
 
 pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs
index a16c4d6c2c4..32d73e50e6b 100644
--- a/src/librustc_trans/trans/build.rs
+++ b/src/librustc_trans/trans/build.rs
@@ -646,13 +646,13 @@ pub fn LoadNonNull(cx: Block, ptr: ValueRef) -> ValueRef {
     }
 }
 
-pub fn Store(cx: Block, val: ValueRef, ptr: ValueRef) {
-    if cx.unreachable.get() { return; }
+pub fn Store(cx: Block, val: ValueRef, ptr: ValueRef) -> ValueRef {
+    if cx.unreachable.get() { return C_nil(cx.ccx()); }
     B(cx).store(val, ptr)
 }
 
-pub fn VolatileStore(cx: Block, val: ValueRef, ptr: ValueRef) {
-    if cx.unreachable.get() { return; }
+pub fn VolatileStore(cx: Block, val: ValueRef, ptr: ValueRef) -> ValueRef {
+    if cx.unreachable.get() { return C_nil(cx.ccx()); }
     B(cx).volatile_store(val, ptr)
 }
 
diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs
index 92bc20bafcf..3febd41bdce 100644
--- a/src/librustc_trans/trans/builder.rs
+++ b/src/librustc_trans/trans/builder.rs
@@ -509,18 +509,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         value
     }
 
-    pub fn store(&self, val: ValueRef, ptr: ValueRef) {
+    pub fn store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
         debug!("Store {} -> {}",
                self.ccx.tn().val_to_string(val),
                self.ccx.tn().val_to_string(ptr));
         assert!(!self.llbuilder.is_null());
         self.count_insn("store");
         unsafe {
-            llvm::LLVMBuildStore(self.llbuilder, val, ptr);
+            llvm::LLVMBuildStore(self.llbuilder, val, ptr)
         }
     }
 
-    pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) {
+    pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
         debug!("Store {} -> {}",
                self.ccx.tn().val_to_string(val),
                self.ccx.tn().val_to_string(ptr));
@@ -529,6 +529,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         unsafe {
             let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
             llvm::LLVMSetVolatile(insn, llvm::True);
+            insn
         }
     }
 
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 8f3a51a5007..c025be2ee98 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -802,7 +802,9 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     // appropriately sized integer and we have to convert it
                     let tmp = builder.bitcast(llforeign_arg,
                                               type_of::arg_type_of(ccx, rust_ty).ptr_to());
-                    builder.load(tmp)
+                    let load = builder.load(tmp);
+                    llvm::LLVMSetAlignment(load, type_of::align_of(ccx, rust_ty));
+                    load
                 } else {
                     builder.load(llforeign_arg)
                 }
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index fc3c0841dd8..1e67212871a 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -456,13 +456,20 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, "volatile_load") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
             let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
-            from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty)
+            let load = VolatileLoad(bcx, ptr);
+            unsafe {
+                llvm::LLVMSetAlignment(load, type_of::align_of(ccx, tp_ty));
+            }
+            from_arg_ty(bcx, load, tp_ty)
         },
         (_, "volatile_store") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
             let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
             let val = to_arg_ty(bcx, llargs[1], tp_ty);
-            VolatileStore(bcx, val, ptr);
+            let store = VolatileStore(bcx, val, ptr);
+            unsafe {
+                llvm::LLVMSetAlignment(store, type_of::align_of(ccx, tp_ty));
+            }
             C_nil(ccx)
         },
 
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 59fe3658437..6fcf39f0b17 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -20,6 +20,9 @@ use parse::token;
 use ptr::P;
 use util::small_vector::SmallVector;
 
+// Maximum width of any line in an extended error description (inclusive).
+const MAX_DESCRIPTION_WIDTH: usize = 80;
+
 thread_local! {
     static REGISTERED_DIAGNOSTICS: RefCell<BTreeMap<Name, Option<Name>>> = {
         RefCell::new(BTreeMap::new())
@@ -92,6 +95,24 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
         }
         _ => unreachable!()
     };
+    // Check that the description starts and ends with a newline and doesn't
+    // overflow the maximum line width.
+    description.map(|raw_msg| {
+        let msg = raw_msg.as_str();
+        if !msg.starts_with("\n") || !msg.ends_with("\n") {
+            ecx.span_err(span, &format!(
+                "description for error code {} doesn't start and end with a newline",
+                token::get_ident(*code)
+            ));
+        }
+        if msg.lines().any(|line| line.len() > MAX_DESCRIPTION_WIDTH) {
+            ecx.span_err(span, &format!(
+                "description for error code {} contains a line longer than {} characters",
+                token::get_ident(*code), MAX_DESCRIPTION_WIDTH
+            ));
+        }
+        raw_msg
+    });
     with_registered_diagnostics(|diagnostics| {
         if diagnostics.insert(code.name, description).is_some() {
             ecx.span_err(span, &format!(