about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/reference.md26
-rw-r--r--src/doc/trpl/closures.md4
-rw-r--r--src/doc/trpl/rust-inside-other-languages.md46
-rw-r--r--src/doc/trpl/trait-objects.md4
-rw-r--r--src/libcollections/vec.rs78
-rw-r--r--src/libcore/char.rs13
-rw-r--r--src/libcore/str/mod.rs20
-rw-r--r--src/liblibc/lib.rs5
-rw-r--r--src/librustc/middle/dead.rs28
-rw-r--r--src/librustc/middle/pat_util.rs24
-rw-r--r--src/librustc/middle/traits/project.rs4
-rw-r--r--src/librustc_back/sha2.rs1
-rw-r--r--src/librustc_llvm/lib.rs17
-rw-r--r--src/librustc_trans/back/write.rs91
-rw-r--r--src/librustc_trans/trans/adt.rs21
-rw-r--r--src/librustc_trans/trans/attributes.rs15
-rw-r--r--src/librustc_trans/trans/base.rs20
-rw-r--r--src/librustc_trans/trans/cleanup.rs7
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs2
-rw-r--r--src/librustc_trans/trans/debuginfo/mod.rs10
-rw-r--r--src/librustc_typeck/check/cast.rs6
-rw-r--r--src/librustc_typeck/check/method/probe.rs67
-rw-r--r--src/librustc_typeck/constrained_type_params.rs17
-rw-r--r--src/librustdoc/html/render.rs4
-rw-r--r--src/libstd/thread/mod.rs1
-rw-r--r--src/libstd/thread/scoped_tls.rs79
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs132
m---------src/llvm0
-rw-r--r--src/rustllvm/ExecutionEngineWrapper.cpp3
-rw-r--r--src/rustllvm/PassWrapper.cpp58
-rw-r--r--src/rustllvm/RustWrapper.cpp146
-rw-r--r--src/rustllvm/llvm-auto-clean-trigger2
-rw-r--r--src/rustllvm/rustllvm.h7
-rw-r--r--src/test/auxiliary/llvm_pass_plugin.rs2
-rw-r--r--src/test/codegen/loads.rs8
-rw-r--r--src/test/codegen/stores.rs4
-rw-r--r--src/test/compile-fail/issue-26262.rs32
-rw-r--r--src/test/compile-fail/lint-dead-code-variant.rs22
-rw-r--r--src/test/run-pass/asm-in-out-operand.rs3
-rw-r--r--src/test/run-pass/associated-types-method.rs36
-rw-r--r--src/test/run-pass/issue-25089.rs40
-rw-r--r--src/test/run-pass/issue-25679.rs28
-rw-r--r--src/test/run-pass/lint-dead-code-variant.rs22
-rw-r--r--src/test/run-pass/sync-send-iterators-in-libcore.rs79
44 files changed, 905 insertions, 329 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index c19aec78de2..5be61a51bf0 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -638,7 +638,7 @@ apply to the crate as a whole.
 ```
 
 A crate that contains a `main` function can be compiled to an executable. If a
-`main` function is present, its return type must be [`unit`](#primitive-types)
+`main` function is present, its return type must be [`unit`](#tuple-types)
 and it must take no arguments.
 
 # Items and attributes
@@ -928,21 +928,20 @@ A _generic function_ allows one or more _parameterized types_ to appear in its
 signature. Each type parameter must be explicitly declared, in an
 angle-bracket-enclosed, comma-separated list following the function name.
 
-```{.ignore}
-fn iter<T, F>(seq: &[T], f: F) where T: Copy, F: Fn(T) {
-    for elt in seq { f(*elt); }
-}
-fn map<T, U, F>(seq: &[T], f: F) -> Vec<U> where T: Copy, U: Copy, F: Fn(T) -> U {
-    let mut acc = vec![];
-    for elt in seq { acc.push(f(*elt)); }
-    acc
-}
+```rust,ignore
+// foo is generic over A and B
+
+fn foo<A, B>(x: A, y: B) {
 ```
 
 Inside the function signature and body, the name of the type parameter can be
 used as a type name. [Trait](#traits) bounds can be specified for type parameters
 to allow methods with that trait to be called on values of that type. This is
-specified using the `where` syntax, as in the above example.
+specified using the `where` syntax:
+
+```rust,ignore
+fn foo<T>(x: T) where T: Debug {
+```
 
 When a generic function is referenced, its type is instantiated based on the
 context of the reference. For example, calling the `iter` function defined
@@ -2874,7 +2873,7 @@ The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be
 composed with the `=` operator. The expression `lval OP= val` is equivalent to
 `lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`.
 
-Any such expression always has the [`unit`](#primitive-types) type.
+Any such expression always has the [`unit`](#tuple-types) type.
 
 #### Operator precedence
 
@@ -3316,6 +3315,9 @@ assert!(b != "world");
 assert!(p.0 == 10);
 ```
 
+For historical reasons and convenience, the tuple type with no elements (`()`)
+is often called ‘unit’ or ‘the unit type’.
+
 ### Array, and Slice types
 
 Rust has two different types for a list of items:
diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md
index 428897821cf..ce52ea5d690 100644
--- a/src/doc/trpl/closures.md
+++ b/src/doc/trpl/closures.md
@@ -120,7 +120,7 @@ let y = &mut num;
 ```
 
 If your closure requires it, however, Rust will take ownership and move
-the environment instead:
+the environment instead. This doesn’t work:
 
 ```rust,ignore
 let nums = vec![1, 2, 3];
@@ -130,7 +130,7 @@ let takes_nums = || nums;
 println!("{:?}", nums);
 ```
 
-This gives us:
+We get this error:
 
 ```text
 note: `nums` moved into closure environment here because it has type
diff --git a/src/doc/trpl/rust-inside-other-languages.md b/src/doc/trpl/rust-inside-other-languages.md
index 0a1860769d2..6129c98259b 100644
--- a/src/doc/trpl/rust-inside-other-languages.md
+++ b/src/doc/trpl/rust-inside-other-languages.md
@@ -66,10 +66,14 @@ threads = []
     5_000_000.times do
       count += 1
     end
+
+    count
   end
 end
 
-threads.each { |t| t.join }
+threads.each do |t|
+  puts "Thread finished with count=#{t.value}"
+end
 puts "done!"
 ```
 
@@ -103,50 +107,26 @@ use std::thread;
 fn process() {
     let handles: Vec<_> = (0..10).map(|_| {
         thread::spawn(|| {
-            let mut _x = 0;
+            let mut x = 0;
             for _ in (0..5_000_000) {
-                _x += 1
+                x += 1
             }
+	    x
         })
     }).collect();
 
     for h in handles {
-        h.join().ok().expect("Could not join a thread!");
+        println!("Thread finished with count={}",
+	    h.join().map_err(|_| "Could not join a thread!").unwrap());
     }
+    println!("done!");
 }
 ```
 
 Some of this should look familiar from previous examples. We spin up ten
 threads, collecting them into a `handles` vector. Inside of each thread, we
-loop five million times, and add one to `_x` each time. Why the underscore?
-Well, if we remove it and compile:
-
-```bash
-$ cargo build
-   Compiling embed v0.1.0 (file:///home/steve/src/embed)
-src/lib.rs:3:1: 16:2 warning: function is never used: `process`, #[warn(dead_code)] on by default
-src/lib.rs:3 fn process() {
-src/lib.rs:4     let handles: Vec<_> = (0..10).map(|_| {
-src/lib.rs:5         thread::spawn(|| {
-src/lib.rs:6             let mut x = 0;
-src/lib.rs:7             for _ in (0..5_000_000) {
-src/lib.rs:8                 x += 1
-             ...
-src/lib.rs:6:17: 6:22 warning: variable `x` is assigned to, but never used, #[warn(unused_variables)] on by default
-src/lib.rs:6             let mut x = 0;
-                             ^~~~~
-```
-
-That first warning is because we are building a library. If we had a test
-for this function, the warning would go away. But for now, it’s never
-called.
-
-The second is related to `x` versus `_x`. Because we never actually _do_
-anything with `x`, we get a warning about it. In our case, that’s perfectly
-okay, as we’re just trying to waste CPU cycles. Prefixing `x` with the
-underscore removes the warning.
-
-Finally, we join on each thread.
+loop five million times, and add one to `x` each time. Finally, we join on
+each thread.
 
 Right now, however, this is a Rust library, and it doesn’t expose anything
 that’s callable from C. If we tried to hook this up to another language right
diff --git a/src/doc/trpl/trait-objects.md b/src/doc/trpl/trait-objects.md
index 3da29c9b817..f9dbc143c82 100644
--- a/src/doc/trpl/trait-objects.md
+++ b/src/doc/trpl/trait-objects.md
@@ -300,7 +300,3 @@ let y = TraitObject {
 // y.method();
 (y.vtable.method)(y.data);
 ```
-
-If `b` or `y` were owning trait objects (`Box<Foo>`), there would be a
-`(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of
-scope.
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 741452b75f1..ba41f438b37 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1469,42 +1469,26 @@ impl<T> ops::DerefMut for Vec<T> {
 impl<T> FromIterator<T> for Vec<T> {
     #[inline]
     fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> Vec<T> {
+        // Unroll the first iteration, as the vector is going to be
+        // expanded on this iteration in every case when the iterable is not
+        // empty, but the loop in extend_desugared() is not going to see the
+        // vector being full in the few subsequent loop iterations.
+        // So we get better branch prediction and the possibility to
+        // construct the vector with initial estimated capacity.
         let mut iterator = iterable.into_iter();
-        let (lower, _) = iterator.size_hint();
-        let mut vector = Vec::with_capacity(lower);
-
-        // This function should be the moral equivalent of:
-        //
-        //      for item in iterator {
-        //          vector.push(item);
-        //      }
-        //
-        // This equivalent crucially runs the iterator precisely once. Below we
-        // actually in theory run the iterator twice (one without bounds checks
-        // and one with). To achieve the "moral equivalent", we use the `if`
-        // statement below to break out early.
-        //
-        // If the first loop has terminated, then we have one of two conditions.
-        //
-        // 1. The underlying iterator returned `None`. In this case we are
-        //    guaranteed that less than `vector.capacity()` elements have been
-        //    returned, so we break out early.
-        // 2. The underlying iterator yielded `vector.capacity()` elements and
-        //    has not yielded `None` yet. In this case we run the iterator to
-        //    its end below.
-        for element in iterator.by_ref().take(vector.capacity()) {
-            let len = vector.len();
-            unsafe {
-                ptr::write(vector.get_unchecked_mut(len), element);
-                vector.set_len(len + 1);
-            }
-        }
-
-        if vector.len() == vector.capacity() {
-            for element in iterator {
-                vector.push(element);
+        let mut vector = match iterator.next() {
+            None => return Vec::new(),
+            Some(element) => {
+                let (lower, _) = iterator.size_hint();
+                let mut vector = Vec::with_capacity(1 + lower);
+                unsafe {
+                    ptr::write(vector.get_unchecked_mut(0), element);
+                    vector.set_len(1);
+                }
+                vector
             }
-        }
+        };
+        vector.extend_desugared(iterator);
         vector
     }
 }
@@ -1569,11 +1553,27 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
 impl<T> Extend<T> for Vec<T> {
     #[inline]
     fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
-        let iterator = iterable.into_iter();
-        let (lower, _) = iterator.size_hint();
-        self.reserve(lower);
-        for element in iterator {
-            self.push(element)
+        self.extend_desugared(iterable.into_iter())
+    }
+}
+
+impl<T> Vec<T> {
+    fn extend_desugared<I: Iterator<Item=T>>(&mut self, mut iterator: I) {
+        // This function should be the moral equivalent of:
+        //
+        //      for item in iterator {
+        //          self.push(item);
+        //      }
+        while let Some(element) = iterator.next() {
+            let len = self.len();
+            if len == self.capacity() {
+                let (lower, _) = iterator.size_hint();
+                self.reserve(lower + 1);
+            }
+            unsafe {
+                ptr::write(self.get_unchecked_mut(len), element);
+                self.set_len(len + 1);
+            }
         }
     }
 }
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 9938c299615..df371752b86 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -74,17 +74,8 @@ pub const MAX: char = '\u{10ffff}';
 /// ```
 /// use std::char;
 ///
-/// let c = char::from_u32(10084); // produces `Some(❤)`
-/// assert_eq!(c, Some('❤'));
-/// ```
-///
-/// An invalid character:
-///
-/// ```
-/// use std::char;
-///
-/// let none = char::from_u32(1114112);
-/// assert_eq!(none, None);
+/// assert_eq!(char::from_u32(0x2764), Some('❤'));
+/// assert_eq!(char::from_u32(0x110000), None); // invalid character
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 4db64a3097e..ef8b371f061 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -638,10 +638,10 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.split()`.
+        #[doc="Created with the method `.split()`."]
         struct Split;
     reverse:
-        /// Created with the method `.rsplit()`.
+        #[doc="Created with the method `.rsplit()`."]
         struct RSplit;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -652,10 +652,10 @@ generate_pattern_iterators! {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.split_terminator()`.
+        #[doc="Created with the method `.split_terminator()`."]
         struct SplitTerminator;
     reverse:
-        /// Created with the method `.rsplit_terminator()`.
+        #[doc="Created with the method `.rsplit_terminator()`."]
         struct RSplitTerminator;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -698,10 +698,10 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.splitn()`.
+        #[doc="Created with the method `.splitn()`."]
         struct SplitN;
     reverse:
-        /// Created with the method `.rsplitn()`.
+        #[doc="Created with the method `.rsplitn()`."]
         struct RSplitN;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -732,10 +732,10 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.match_indices()`.
+        #[doc="Created with the method `.match_indices()`."]
         struct MatchIndices;
     reverse:
-        /// Created with the method `.rmatch_indices()`.
+        #[doc="Created with the method `.rmatch_indices()`."]
         struct RMatchIndices;
     stability:
         #[unstable(feature = "core",
@@ -773,10 +773,10 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.matches()`.
+        #[doc="Created with the method `.matches()`."]
         struct Matches;
     reverse:
-        /// Created with the method `.rmatches()`.
+        #[doc="Created with the method `.rmatches()`."]
         struct RMatches;
     stability:
         #[unstable(feature = "core", reason = "type got recently added")]
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index b7a40a3f9cf..2676d4879b5 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -146,7 +146,10 @@ pub use funcs::bsd43::*;
 #[link(name = "m")]
 extern {}
 
-#[cfg(all(target_env = "musl", not(test)))]
+// When compiling rust with musl, statically include libc.a in liblibc.rlib.
+// A cargo build of the libc crate will therefore automatically pick up the
+// libc.a symbols because liblibc is transitively linked to by the stdlib.
+#[cfg(all(target_env = "musl", not(feature = "cargo-build"), not(test)))]
 #[link(name = "c", kind = "static")]
 extern {}
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 5068836b557..e618aa5a5b7 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -48,6 +48,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
     struct_has_extern_repr: bool,
     ignore_non_const_paths: bool,
     inherited_pub_visibility: bool,
+    ignore_variant_stack: Vec<ast::NodeId>,
 }
 
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
@@ -60,6 +61,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             struct_has_extern_repr: false,
             ignore_non_const_paths: false,
             inherited_pub_visibility: false,
+            ignore_variant_stack: vec![],
         }
     }
 
@@ -80,7 +82,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                 def::DefPrimTy(_) => (),
                 def::DefVariant(enum_id, variant_id, _) => {
                     self.check_def_id(enum_id);
-                    self.check_def_id(variant_id);
+                    if !self.ignore_variant_stack.contains(&variant_id.node) {
+                        self.check_def_id(variant_id);
+                    }
                 }
                 _ => {
                     self.check_def_id(def.def_id());
@@ -272,6 +276,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         visit::walk_expr(self, expr);
     }
 
+    fn visit_arm(&mut self, arm: &ast::Arm) {
+        if arm.pats.len() == 1 {
+            let pat = &*arm.pats[0];
+            let variants = pat_util::necessary_variants(&self.tcx.def_map, pat);
+
+            // Inside the body, ignore constructions of variants
+            // necessary for the pattern to match. Those construction sites
+            // can't be reached unless the variant is constructed elsewhere.
+            let len = self.ignore_variant_stack.len();
+            self.ignore_variant_stack.push_all(&*variants);
+            visit::walk_arm(self, arm);
+            self.ignore_variant_stack.truncate(len);
+        } else {
+            visit::walk_arm(self, arm);
+        }
+    }
+
     fn visit_pat(&mut self, pat: &ast::Pat) {
         let def_map = &self.tcx.def_map;
         match pat.node {
@@ -393,6 +414,11 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
         worklist.push(*id);
     }
     for id in reachable_symbols {
+        // Reachable variants can be dead, because we warn about
+        // variants never constructed, not variants never used.
+        if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
+            continue;
+        }
         worklist.push(*id);
     }
 
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index bb4c702f373..0cb302d79b8 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -201,3 +201,27 @@ pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
         span: DUMMY_SP,
     })
 }
+
+/// Return variants that are necessary to exist for the pattern to match.
+pub fn necessary_variants(dm: &DefMap, pat: &ast::Pat) -> Vec<ast::NodeId> {
+    let mut variants = vec![];
+    walk_pat(pat, |p| {
+        match p.node {
+            ast::PatEnum(_, _) |
+            ast::PatIdent(_, _, None) |
+            ast::PatStruct(..) => {
+                match dm.borrow().get(&p.id) {
+                    Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
+                        variants.push(id.node);
+                    }
+                    _ => ()
+                }
+            }
+            _ => ()
+        }
+        true
+    });
+    variants.sort();
+    variants.dedup();
+    variants
+}
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index 1631a33588c..4ef8f380e82 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -389,15 +389,19 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
             }
         }
         Ok(ProjectedTy::NoProgress(projected_ty)) => {
+            debug!("normalize_projection_type: projected_ty={} no progress",
+                   projected_ty.repr(selcx.tcx()));
             Some(Normalized {
                 value: projected_ty,
                 obligations: vec!()
             })
         }
         Err(ProjectionTyError::TooManyCandidates) => {
+            debug!("normalize_projection_type: too many candidates");
             None
         }
         Err(ProjectionTyError::TraitSelectionError(_)) => {
+            debug!("normalize_projection_type: ERROR");
             // if we got an error processing the `T as Trait` part,
             // just return `ty::err` but add the obligation `T :
             // Trait`, which when processed will cause the error to be
diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs
index 9ed827da8b2..efbd4c3ef5e 100644
--- a/src/librustc_back/sha2.rs
+++ b/src/librustc_back/sha2.rs
@@ -482,6 +482,7 @@ pub struct Sha256 {
 
 impl Sha256 {
     /// Construct a new instance of a SHA-256 digest.
+    /// Do not – under any circumstances – use this where timing attacks might be possible!
     pub fn new() -> Sha256 {
         Sha256 {
             engine: Engine256::new(&H256)
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 4d7f00e9523..bf331705b32 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -976,6 +976,9 @@ extern {
     pub fn LLVMAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: uint64_t);
     pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
     pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
+    pub fn LLVMAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint,
+                                          Name: *const c_char,
+                                          Value: *const c_char);
     pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
     pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
     pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_ulonglong);
@@ -1920,6 +1923,7 @@ extern {
                                            VarInfo: DIVariable,
                                            AddrOps: *const i64,
                                            AddrOpsCount: c_uint,
+                                           DL: ValueRef,
                                            InsertAtEnd: BasicBlockRef)
                                            -> ValueRef;
 
@@ -1928,6 +1932,7 @@ extern {
                                             VarInfo: DIVariable,
                                             AddrOps: *const i64,
                                             AddrOpsCount: c_uint,
+                                            DL: ValueRef,
                                             InsertBefore: ValueRef)
                                             -> ValueRef;
 
@@ -2035,7 +2040,6 @@ extern {
                                        Level: CodeGenOptLevel,
                                        EnableSegstk: bool,
                                        UseSoftFP: bool,
-                                       NoFramePointerElim: bool,
                                        PositionIndependentExecutable: bool,
                                        FunctionSections: bool,
                                        DataSections: bool) -> TargetMachineRef;
@@ -2046,6 +2050,11 @@ extern {
     pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef,
                                          M: ModuleRef,
                                          DisableSimplifyLibCalls: bool);
+    pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
+                                               OptLevel: CodeGenOptLevel,
+                                               MergeFunctions: bool,
+                                               SLPVectorize: bool,
+                                               LoopVectorize: bool);
     pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, M: ModuleRef,
                                   DisableSimplifyLibCalls: bool);
     pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef);
@@ -2116,6 +2125,12 @@ extern {
     pub fn LLVMWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef);
 }
 
+// LLVM requires symbols from this library, but apparently they're not printed
+// during llvm-config?
+#[cfg(windows)]
+#[link(name = "ole32")]
+extern {}
+
 pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
     unsafe {
         LLVMSetInstructionCallConv(instr, cc as c_uint);
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 5352c61d8c0..1b8f049972f 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -10,7 +10,7 @@
 
 use back::lto;
 use back::link::{get_cc_prog, remove};
-use session::config::{OutputFilenames, NoDebugInfo, Passes, SomePasses, AllPasses};
+use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
 use session::Session;
 use session::config;
 use llvm;
@@ -188,10 +188,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
     let opt_level = get_llvm_opt_level(sess.opts.optimize);
     let use_softfp = sess.opts.cg.soft_float;
 
-    // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
-    let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
-                     !sess.target.target.options.eliminate_frame_pointer;
-
     let any_library = sess.crate_types.borrow().iter().any(|ty| {
         *ty != config::CrateTypeExecutable
     });
@@ -237,7 +233,6 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
             opt_level,
             true /* EnableSegstk */,
             use_softfp,
-            no_fp_elim,
             !any_library && reloc_model == llvm::RelocPIC,
             ffunction_sections,
             fdata_sections,
@@ -279,6 +274,9 @@ struct ModuleConfig {
     no_prepopulate_passes: bool,
     no_builtins: bool,
     time_passes: bool,
+    vectorize_loop: bool,
+    vectorize_slp: bool,
+    merge_functions: bool,
 }
 
 unsafe impl Send for ModuleConfig { }
@@ -301,6 +299,9 @@ impl ModuleConfig {
             no_prepopulate_passes: false,
             no_builtins: false,
             time_passes: false,
+            vectorize_loop: false,
+            vectorize_slp: false,
+            merge_functions: false,
         }
     }
 
@@ -309,6 +310,18 @@ impl ModuleConfig {
         self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
         self.no_builtins = trans.no_builtins;
         self.time_passes = sess.time_passes();
+
+        // Copy what clang does by turning on loop vectorization at O2 and
+        // slp vectorization at O3. Otherwise configure other optimization aspects
+        // of this pass manager builder.
+        self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
+                             (sess.opts.optimize == config::Default ||
+                              sess.opts.optimize == config::Aggressive);
+        self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
+                            sess.opts.optimize == config::Aggressive;
+
+        self.merge_functions = sess.opts.optimize == config::Default ||
+                               sess.opts.optimize == config::Aggressive;
     }
 }
 
@@ -448,27 +461,26 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
                 let pass = CString::new(pass).unwrap();
                 llvm::LLVMRustAddPass(fpm, pass.as_ptr())
             };
-            if !config.no_verify { assert!(addpass("verify")); }
 
+            if !config.no_verify { assert!(addpass("verify")); }
             if !config.no_prepopulate_passes {
                 llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
                 llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
-                populate_llvm_passes(fpm, mpm, llmod, opt_level,
-                                     config.no_builtins);
+                populate_llvm_passes(fpm, mpm, llmod, opt_level, &config);
             }
 
             for pass in &config.passes {
-                let pass = CString::new(pass.clone()).unwrap();
-                if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
-                    cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
+                if !addpass(pass) {
+                    cgcx.handler.warn(&format!("unknown pass `{}`, ignoring",
+                                               pass));
                 }
             }
 
             for pass in &cgcx.plugin_passes {
-                let pass = CString::new(pass.clone()).unwrap();
-                if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
-                    cgcx.handler.err(&format!("a plugin asked for LLVM pass {:?} but LLVM \
-                                               does not recognize it", pass));
+                if !addpass(pass) {
+                    cgcx.handler.err(&format!("a plugin asked for LLVM pass \
+                                               `{}` but LLVM does not \
+                                               recognize it", pass));
                 }
             }
 
@@ -520,7 +532,6 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
         llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod);
         llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
         f(cpm);
-        llvm::LLVMDisposePassManager(cpm);
     }
 
     if config.emit_bc {
@@ -537,13 +548,15 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
             let out = path2cstr(&out);
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
+                llvm::LLVMDisposePassManager(cpm);
             })
         }
 
         if config.emit_asm {
             let path = output_names.with_extension(&format!("{}.s", name_extra));
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
+                write_output_file(cgcx.handler, tm, cpm, llmod, &path,
+                                  llvm::AssemblyFileType);
             });
         }
 
@@ -1008,16 +1021,9 @@ unsafe fn configure_llvm(sess: &Session) {
     use std::sync::Once;
     static INIT: Once = Once::new();
 
-    // Copy what clang does by turning on loop vectorization at O2 and
-    // slp vectorization at O3
-    let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
-                         (sess.opts.optimize == config::Default ||
-                          sess.opts.optimize == config::Aggressive);
-    let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
-                        sess.opts.optimize == config::Aggressive;
-
     let mut llvm_c_strs = Vec::new();
     let mut llvm_args = Vec::new();
+
     {
         let mut add = |arg: &str| {
             let s = CString::new(arg).unwrap();
@@ -1025,8 +1031,6 @@ unsafe fn configure_llvm(sess: &Session) {
             llvm_c_strs.push(s);
         };
         add("rustc"); // fake program name
-        if vectorize_loop { add("-vectorize-loops"); }
-        if vectorize_slp  { add("-vectorize-slp");   }
         if sess.time_llvm_passes() { add("-time-passes"); }
         if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
 
@@ -1084,41 +1088,40 @@ unsafe fn populate_llvm_passes(fpm: llvm::PassManagerRef,
                                mpm: llvm::PassManagerRef,
                                llmod: ModuleRef,
                                opt: llvm::CodeGenOptLevel,
-                               no_builtins: bool) {
+                               config: &ModuleConfig) {
     // Create the PassManagerBuilder for LLVM. We configure it with
     // reasonable defaults and prepare it to actually populate the pass
     // manager.
     let builder = llvm::LLVMPassManagerBuilderCreate();
+
+    llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
+                                              config.merge_functions,
+                                              config.vectorize_slp,
+                                              config.vectorize_loop);
+
+    llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
+
+    // Here we match what clang does (kinda). For O0 we only inline
+    // always-inline functions (but don't add lifetime intrinsics), at O1 we
+    // inline with lifetime intrinsics, and O2+ we add an inliner with a
+    // thresholds copied from clang.
     match opt {
         llvm::CodeGenLevelNone => {
-            // Don't add lifetime intrinsics at O0
             llvm::LLVMRustAddAlwaysInlinePass(builder, false);
         }
         llvm::CodeGenLevelLess => {
             llvm::LLVMRustAddAlwaysInlinePass(builder, true);
         }
-        // numeric values copied from clang
         llvm::CodeGenLevelDefault => {
-            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
-                                                                225);
+            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
         }
         llvm::CodeGenLevelAggressive => {
-            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder,
-                                                                275);
+            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
         }
     }
-    llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt as c_uint);
-    llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, no_builtins);
 
     // Use the builder to populate the function/module pass managers.
     llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(builder, fpm);
     llvm::LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
     llvm::LLVMPassManagerBuilderDispose(builder);
-
-    match opt {
-        llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
-            llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
-        }
-        _ => {}
-    };
 }
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index d9e1a75d3dc..68d72ab4241 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -1029,11 +1029,26 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         }
         General(ity, ref cases, _) => {
             let ccx = bcx.ccx();
-            let unr_cx = fcx.new_temp_block("enum-variant-iter-unr");
-            Unreachable(unr_cx);
+
+            // See the comments in trans/base.rs for more information (inside
+            // iter_structural_ty), but the gist here is that if the enum's
+            // discriminant is *not* in the range that we're expecting (in which
+            // case we'll take the fall-through branch on the switch
+            // instruction) then we can't just optimize this to an Unreachable
+            // block.
+            //
+            // Currently we still have filling drop, so this means that the drop
+            // glue for enums may be called when the enum has been paved over
+            // with the "I've been dropped" value. In this case the default
+            // branch of the switch instruction will actually be taken at
+            // runtime, so the basic block isn't actually unreachable, so we
+            // need to make it do something with defined behavior. In this case
+            // we just return early from the function.
+            let ret_void_cx = fcx.new_temp_block("enum-variant-iter-ret-void");
+            RetVoid(ret_void_cx, DebugLoc::None);
 
             let discr_val = trans_get_discr(bcx, r, value, None);
-            let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len());
+            let llswitch = Switch(bcx, discr_val, ret_void_cx.llbb, cases.len());
             let bcx_next = fcx.new_temp_block("enum-variant-iter-next");
 
             for (discr, case) in cases.iter().enumerate() {
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
index d4ce17cc7b5..b0f44e65739 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -12,6 +12,7 @@
 use libc::{c_uint, c_ulonglong};
 use llvm::{self, ValueRef, AttrHelper};
 use middle::ty::{self, ClosureTyper};
+use session::config::NoDebugInfo;
 use syntax::abi;
 use syntax::ast;
 pub use syntax::attr::InlineAttr;
@@ -106,6 +107,20 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
     use syntax::attr::*;
     inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
 
+    // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
+    // parameter.
+    let no_fp_elim = (ccx.sess().opts.debuginfo != NoDebugInfo) ||
+                     !ccx.sess().target.target.options.eliminate_frame_pointer;
+    if no_fp_elim {
+        unsafe {
+            let attr = "no-frame-pointer-elim\0".as_ptr() as *const _;
+            let val = "true\0".as_ptr() as *const _;
+            llvm::LLVMAddFunctionAttrStringValue(llfn,
+                                                 llvm::FunctionIndex as c_uint,
+                                                 attr, val);
+        }
+    }
+
     for attr in attrs {
         if attr.check_name("no_stack_check") {
             split_stack(llfn, false);
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 0ec2d1abb09..c2293dcc6d4 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -481,9 +481,23 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
               }
               (_match::Switch, Some(lldiscrim_a)) => {
                   cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
-                  let unr_cx = fcx.new_temp_block("enum-iter-unr");
-                  Unreachable(unr_cx);
-                  let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
+
+                  // Create a fall-through basic block for the "else" case of
+                  // the switch instruction we're about to generate. Note that
+                  // we do **not** use an Unreachable instruction here, even
+                  // though most of the time this basic block will never be hit.
+                  //
+                  // When an enum is dropped it's contents are currently
+                  // overwritten to DTOR_DONE, which means the discriminant
+                  // could have changed value to something not within the actual
+                  // range of the discriminant. Currently this function is only
+                  // used for drop glue so in this case we just return quickly
+                  // from the outer function, and any other use case will only
+                  // call this for an already-valid enum in which case the `ret
+                  // void` will never be hit.
+                  let ret_void_cx = fcx.new_temp_block("enum-iter-ret-void");
+                  RetVoid(ret_void_cx, DebugLoc::None);
+                  let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb,
                                         n_variants);
                   let next_cx = fcx.new_temp_block("enum-iter-next");
 
diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs
index d23543924dd..9133004dfef 100644
--- a/src/librustc_trans/trans/cleanup.rs
+++ b/src/librustc_trans/trans/cleanup.rs
@@ -954,8 +954,15 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> {
         }
     }
 
+    /// Manipulate cleanup scope for call arguments. Conceptually, each
+    /// argument to a call is an lvalue, and performing the call moves each
+    /// of the arguments into a new rvalue (which gets cleaned up by the
+    /// callee). As an optimization, instead of actually performing all of
+    /// those moves, trans just manipulates the cleanup scope to obtain the
+    /// same effect.
     pub fn drop_non_lifetime_clean(&mut self) {
         self.cleanups.retain(|c| c.is_lifetime_end());
+        self.clear_cached_exits();
     }
 }
 
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index 42aa96ed21e..5e35e5c67f3 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -1677,7 +1677,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         DIB(cx),
         containing_scope,
         enum_name.as_ptr(),
-        UNKNOWN_FILE_METADATA,
+        file_metadata,
         UNKNOWN_LINE_NUMBER,
         bytes_to_bits(enum_type_size),
         bytes_to_bits(enum_type_align),
diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs
index 7210c35e0e0..06f1a56c6ef 100644
--- a/src/librustc_trans/trans/debuginfo/mod.rs
+++ b/src/librustc_trans/trans/debuginfo/mod.rs
@@ -485,10 +485,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let param_metadata = unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
-                        file_metadata,
+                        ptr::null_mut(),
                         name.as_ptr(),
                         actual_self_type_metadata,
-                        ptr::null_mut(),
+                        file_metadata,
                         0,
                         0)
                 };
@@ -519,10 +519,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let param_metadata = unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
-                        file_metadata,
+                        ptr::null_mut(),
                         name.as_ptr(),
                         actual_type_metadata,
-                        ptr::null_mut(),
+                        file_metadata,
                         0,
                         0)
                 };
@@ -581,12 +581,14 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                                           loc.line,
                                                                           loc.col.to_usize()));
             unsafe {
+                let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
                 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
                     DIB(cx),
                     alloca,
                     metadata,
                     address_operations.as_ptr(),
                     address_operations.len() as c_uint,
+                    debug_loc,
                     bcx.llbb);
 
                 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 6e306047f75..9fefd7ac036 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -99,7 +99,6 @@ enum CastError {
     NeedViaInt,
     NeedViaUsize,
     NonScalar,
-    RefToMutPtr
 }
 
 impl<'tcx> CastCheck<'tcx> {
@@ -161,11 +160,6 @@ impl<'tcx> CastCheck<'tcx> {
                             fcx.infcx().ty_to_string(self.cast_ty))
                 }, self.expr_ty, None);
             }
-            CastError::RefToMutPtr => {
-                span_err!(fcx.tcx().sess, self.span, E0188,
-                          "cannot cast an immutable reference to a \
-                           mutable pointer");
-            }
         }
     }
 
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 79449b2f10d..915aadd722b 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -59,10 +59,12 @@ struct Candidate<'tcx> {
 }
 
 enum CandidateKind<'tcx> {
-    InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
+    InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>,
+                          /* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
     ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ usize, /* vtable index */ usize),
     ExtensionImplCandidate(/* Impl */ ast::DefId, ty::TraitRef<'tcx>,
-                           subst::Substs<'tcx>, ItemIndex),
+                           subst::Substs<'tcx>, ItemIndex,
+                           /* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
     ClosureCandidate(/* Trait */ ast::DefId, ItemIndex),
     WhereClauseCandidate(ty::PolyTraitRef<'tcx>, ItemIndex),
     ProjectionCandidate(ast::DefId, ItemIndex),
@@ -398,16 +400,24 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
 
         let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
-        let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty);
+        let impl_ty = impl_ty.subst(self.tcx(), &impl_substs);
 
         // Determine the receiver type that the method itself expects.
-        let xform_self_ty =
-            self.xform_self_ty(&item, impl_ty, &impl_substs);
+        let xform_self_ty = self.xform_self_ty(&item, impl_ty, &impl_substs);
+
+        // We can't use normalize_associated_types_in as it will pollute the
+        // fcx's fulfillment context after this probe is over.
+        let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
+        let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
+        let traits::Normalized { value: xform_self_ty, obligations } =
+            traits::normalize(selcx, cause, &xform_self_ty);
+        debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
+               xform_self_ty.repr(self.tcx()));
 
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
             item: item,
-            kind: InherentImplCandidate(impl_def_id, impl_substs)
+            kind: InherentImplCandidate(impl_def_id, impl_substs, obligations)
         });
     }
 
@@ -653,12 +663,24 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                    impl_trait_ref.self_ty(),
                                    impl_trait_ref.substs);
 
+            // Normalize the receiver. We can't use normalize_associated_types_in
+            // as it will pollute the fcx's fulfillment context after this probe
+            // is over.
+            let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
+            let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
+            let traits::Normalized { value: xform_self_ty, obligations } =
+                traits::normalize(selcx, cause, &xform_self_ty);
+
             debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
 
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 item: item.clone(),
-                kind: ExtensionImplCandidate(impl_def_id, impl_trait_ref, impl_substs, item_index)
+                kind: ExtensionImplCandidate(impl_def_id,
+                                             impl_trait_ref,
+                                             impl_substs,
+                                             item_index,
+                                             obligations)
             });
         });
     }
@@ -1026,8 +1048,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             // match as well (or at least may match, sometimes we
             // don't have enough information to fully evaluate).
             match probe.kind {
-                InherentImplCandidate(impl_def_id, ref substs) |
-                ExtensionImplCandidate(impl_def_id, _, ref substs, _) => {
+                InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
+                ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
                     let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx);
                     let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
 
@@ -1046,8 +1068,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                     debug!("impl_obligations={}", obligations.repr(self.tcx()));
 
                     // Evaluate those obligations to see if they might possibly hold.
-                    obligations.iter().all(|o| selcx.evaluate_obligation(o)) &&
-                        norm_obligations.iter().all(|o| selcx.evaluate_obligation(o))
+                    obligations.iter()
+                        .chain(norm_obligations.iter()).chain(ref_obligations.iter())
+                        .all(|o| selcx.evaluate_obligation(o))
+
                 }
 
                 ProjectionCandidate(..) |
@@ -1281,13 +1305,13 @@ impl<'tcx> Candidate<'tcx> {
         Pick {
             item: self.item.clone(),
             kind: match self.kind {
-                InherentImplCandidate(def_id, _) => {
+                InherentImplCandidate(def_id, _, _) => {
                     InherentImplPick(def_id)
                 }
                 ObjectCandidate(def_id, item_num, real_index) => {
                     ObjectPick(def_id, item_num, real_index)
                 }
-                ExtensionImplCandidate(def_id, _, _, index) => {
+                ExtensionImplCandidate(def_id, _, _, index, _) => {
                     ExtensionImplPick(def_id, index)
                 }
                 ClosureCandidate(trait_def_id, index) => {
@@ -1315,9 +1339,9 @@ impl<'tcx> Candidate<'tcx> {
 
     fn to_source(&self) -> CandidateSource {
         match self.kind {
-            InherentImplCandidate(def_id, _) => ImplSource(def_id),
+            InherentImplCandidate(def_id, _, _) => ImplSource(def_id),
             ObjectCandidate(def_id, _, _) => TraitSource(def_id),
-            ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
+            ExtensionImplCandidate(def_id, _, _, _, _) => ImplSource(def_id),
             ClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
             WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
             ProjectionCandidate(trait_def_id, _) => TraitSource(trait_def_id),
@@ -1335,7 +1359,7 @@ impl<'tcx> Candidate<'tcx> {
             ClosureCandidate(trait_def_id, item_num) => {
                 Some((trait_def_id, item_num))
             }
-            ExtensionImplCandidate(_, ref trait_ref, _, item_num) => {
+            ExtensionImplCandidate(_, ref trait_ref, _, item_num, _) => {
                 Some((trait_ref.def_id, item_num))
             }
             WhereClauseCandidate(ref trait_ref, item_num) => {
@@ -1359,13 +1383,14 @@ impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
 impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
-            InherentImplCandidate(ref a, ref b) =>
-                format!("InherentImplCandidate({},{})", a.repr(tcx), b.repr(tcx)),
+            InherentImplCandidate(ref a, ref b, ref c) =>
+                format!("InherentImplCandidate({},{},{})", a.repr(tcx), b.repr(tcx),
+                        c.repr(tcx)),
             ObjectCandidate(a, b, c) =>
                 format!("ObjectCandidate({},{},{})", a.repr(tcx), b, c),
-            ExtensionImplCandidate(ref a, ref b, ref c, ref d) =>
-                format!("ExtensionImplCandidate({},{},{},{})", a.repr(tcx), b.repr(tcx),
-                        c.repr(tcx), d),
+            ExtensionImplCandidate(ref a, ref b, ref c, ref d, ref e) =>
+                format!("ExtensionImplCandidate({},{},{},{},{})", a.repr(tcx), b.repr(tcx),
+                        c.repr(tcx), d, e.repr(tcx)),
             ClosureCandidate(ref a, ref b) =>
                 format!("ClosureCandidate({},{})", a.repr(tcx), b),
             WhereClauseCandidate(ref a, ref b) =>
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 09539931c34..b1580a74876 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -19,10 +19,21 @@ pub enum Parameter {
     Region(ty::EarlyBoundRegion),
 }
 
+/// Returns the list of parameters that are constrained by the type `ty`
+/// - i.e. the value of each parameter in the list is uniquely determined
+/// by `ty` (see RFC 447).
 pub fn parameters_for_type<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
-    ty.walk()
-      .flat_map(|ty| parameters_for_type_shallow(ty))
-      .collect()
+    let mut result = vec![];
+    ty::maybe_walk_ty(ty, |t| {
+        if let ty::TyProjection(..) = t.sty {
+            false // projections are not injective.
+        } else {
+            result.append(&mut parameters_for_type_shallow(t));
+            // non-projection type constructors are injective.
+            true
+        }
+    });
+    result
 }
 
 pub fn parameters_for_trait_ref<'tcx>(trait_ref: &ty::TraitRef<'tcx>) -> Vec<Parameter> {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index c23cfd298aa..0080b5e5f22 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -456,13 +456,15 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
             let did = ast_util::local_def(pid);
             match paths.get(&did) {
                 Some(&(ref fqp, _)) => {
+                    // Needed to determine `self` type.
+                    let parent_basename = Some(fqp[fqp.len() - 1].clone());
                     search_index.push(IndexItem {
                         ty: shortty(item),
                         name: item.name.clone().unwrap(),
                         path: fqp[..fqp.len() - 1].connect("::"),
                         desc: shorter(item.doc_value()),
                         parent: Some(did),
-                        search_type: None,
+                        search_type: get_index_search_type(&item, parent_basename),
                     });
                 },
                 None => {}
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index f090d3e77dd..153b0436087 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -217,6 +217,7 @@ pub use self::local::{LocalKey, LocalKeyState};
 pub use self::scoped_tls::ScopedKey;
 
 #[doc(hidden)] pub use self::local::__KeyInner as __LocalKeyInner;
+#[doc(hidden)] pub use self::scoped_tls::__KeyInner as __ScopedKeyInner;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Builder
diff --git a/src/libstd/thread/scoped_tls.rs b/src/libstd/thread/scoped_tls.rs
index f0a4c318d91..679902ec7ab 100644
--- a/src/libstd/thread/scoped_tls.rs
+++ b/src/libstd/thread/scoped_tls.rs
@@ -43,6 +43,9 @@
 
 use prelude::v1::*;
 
+#[doc(hidden)]
+pub use self::imp::KeyInner as __KeyInner;
+
 /// Type representing a thread local storage key corresponding to a reference
 /// to the type parameter `T`.
 ///
@@ -53,7 +56,7 @@ use prelude::v1::*;
 #[unstable(feature = "scoped_tls",
            reason = "scoped TLS has yet to have wide enough use to fully consider \
                      stabilizing its interface")]
-pub struct ScopedKey<T> { inner: imp::KeyInner<T> }
+pub struct ScopedKey<T> { inner: fn() -> &'static imp::KeyInner<T> }
 
 /// Declare a new scoped thread local storage key.
 ///
@@ -64,42 +67,51 @@ pub struct ScopedKey<T> { inner: imp::KeyInner<T> }
 /// information.
 #[macro_export]
 #[allow_internal_unstable]
-#[cfg(not(no_elf_tls))]
 macro_rules! scoped_thread_local {
     (static $name:ident: $t:ty) => (
-        #[cfg_attr(not(any(windows,
-                           target_os = "android",
-                           target_os = "ios",
-                           target_os = "openbsd",
-                           target_arch = "aarch64")),
-                   thread_local)]
         static $name: ::std::thread::ScopedKey<$t> =
-            ::std::thread::ScopedKey::new();
+            __scoped_thread_local_inner!($t);
     );
     (pub static $name:ident: $t:ty) => (
-        #[cfg_attr(not(any(windows,
-                           target_os = "android",
-                           target_os = "ios",
-                           target_os = "openbsd",
-                           target_arch = "aarch64")),
-                   thread_local)]
         pub static $name: ::std::thread::ScopedKey<$t> =
-            ::std::thread::ScopedKey::new();
+            __scoped_thread_local_inner!($t);
     );
 }
 
+#[doc(hidden)]
+#[unstable(feature = "thread_local_internals",
+           reason = "should not be necessary")]
 #[macro_export]
 #[allow_internal_unstable]
 #[cfg(no_elf_tls)]
-macro_rules! scoped_thread_local {
-    (static $name:ident: $t:ty) => (
-        static $name: ::std::thread::ScopedKey<$t> =
-            ::std::thread::ScopedKey::new();
-    );
-    (pub static $name:ident: $t:ty) => (
-        pub static $name: ::std::thread::ScopedKey<$t> =
-            ::std::thread::ScopedKey::new();
-    );
+macro_rules! __scoped_thread_local_inner {
+    ($t:ty) => {{
+        static _KEY: ::std::thread::__ScopedKeyInner<$t> =
+            ::std::thread::__ScopedKeyInner::new();
+        fn _getit() -> &'static ::std::thread::__ScopedKeyInner<$t> { &_KEY }
+        ::std::thread::ScopedKey::new(_getit)
+    }}
+}
+
+#[doc(hidden)]
+#[unstable(feature = "thread_local_internals",
+           reason = "should not be necessary")]
+#[macro_export]
+#[allow_internal_unstable]
+#[cfg(not(no_elf_tls))]
+macro_rules! __scoped_thread_local_inner {
+    ($t:ty) => {{
+        #[cfg_attr(not(any(windows,
+                           target_os = "android",
+                           target_os = "ios",
+                           target_os = "openbsd",
+                           target_arch = "aarch64")),
+                   thread_local)]
+        static _KEY: ::std::thread::__ScopedKeyInner<$t> =
+            ::std::thread::__ScopedKeyInner::new();
+        fn _getit() -> &'static ::std::thread::__ScopedKeyInner<$t> { &_KEY }
+        ::std::thread::ScopedKey::new(_getit)
+    }}
 }
 
 #[unstable(feature = "scoped_tls",
@@ -107,8 +119,8 @@ macro_rules! scoped_thread_local {
                      stabilizing its interface")]
 impl<T> ScopedKey<T> {
     #[doc(hidden)]
-    pub const fn new() -> ScopedKey<T> {
-        ScopedKey { inner: imp::KeyInner::new() }
+    pub const fn new(inner: fn() -> &'static imp::KeyInner<T>) -> ScopedKey<T> {
+        ScopedKey { inner: inner }
     }
 
     /// Inserts a value into this scoped thread local storage slot for a
@@ -153,13 +165,14 @@ impl<T> ScopedKey<T> {
             }
         }
 
+        let inner = (self.inner)();
         let prev = unsafe {
-            let prev = self.inner.get();
-            self.inner.set(t as *const T as *mut T);
+            let prev = inner.get();
+            inner.set(t as *const T as *mut T);
             prev
         };
 
-        let _reset = Reset { key: &self.inner, val: prev };
+        let _reset = Reset { key: inner, val: prev };
         cb()
     }
 
@@ -186,7 +199,7 @@ impl<T> ScopedKey<T> {
         F: FnOnce(&T) -> R
     {
         unsafe {
-            let ptr = self.inner.get();
+            let ptr = (self.inner)().get();
             assert!(!ptr.is_null(), "cannot access a scoped thread local \
                                      variable without calling `set` first");
             cb(&*ptr)
@@ -195,7 +208,7 @@ impl<T> ScopedKey<T> {
 
     /// Test whether this TLS key has been `set` for the current thread.
     pub fn is_set(&'static self) -> bool {
-        unsafe { !self.inner.get().is_null() }
+        unsafe { !(self.inner)().get().is_null() }
     }
 }
 
@@ -205,6 +218,7 @@ impl<T> ScopedKey<T> {
               target_os = "openbsd",
               target_arch = "aarch64",
               no_elf_tls)))]
+#[doc(hidden)]
 mod imp {
     use std::cell::Cell;
 
@@ -227,6 +241,7 @@ mod imp {
           target_os = "openbsd",
           target_arch = "aarch64",
           no_elf_tls))]
+#[doc(hidden)]
 mod imp {
     use prelude::v1::*;
 
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index ec3006898f3..e7d242ab703 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -1042,21 +1042,31 @@ impl<'a> MethodDef<'a> {
     /// variants where all of the variants match, and one catch-all for
     /// when one does not match.
 
+    /// As an optimization we generate code which checks whether all variants
+    /// match first which makes llvm see that C-like enums can be compiled into
+    /// a simple equality check (for PartialEq).
+
     /// The catch-all handler is provided access the variant index values
-    /// for each of the self-args, carried in precomputed variables. (Nota
-    /// bene: the variant index values are not necessarily the
-    /// discriminant values.  See issue #15523.)
+    /// for each of the self-args, carried in precomputed variables.
 
     /// ```{.text}
-    /// match (this, that, ...) {
-    ///   (Variant1, Variant1, Variant1) => ... // delegate Matching on Variant1
-    ///   (Variant2, Variant2, Variant2) => ... // delegate Matching on Variant2
-    ///   ...
-    ///   _ => {
-    ///     let __this_vi = match this { Variant1 => 0, Variant2 => 1, ... };
-    ///     let __that_vi = match that { Variant1 => 0, Variant2 => 1, ... };
+    /// let __self0_vi = unsafe {
+    ///     std::intrinsics::discriminant_value(&self) } as i32;
+    /// let __self1_vi = unsafe {
+    ///     std::intrinsics::discriminant_value(&__arg1) } as i32;
+    /// let __self2_vi = unsafe {
+    ///     std::intrinsics::discriminant_value(&__arg2) } as i32;
+    ///
+    /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
+    ///     match (...) {
+    ///         (Variant1, Variant1, ...) => Body1
+    ///         (Variant2, Variant2, ...) => Body2,
+    ///         ...
+    ///         _ => ::core::intrinsics::unreachable()
+    ///     }
+    /// }
+    /// else {
     ///     ... // catch-all remainder can inspect above variant index values.
-    ///   }
     /// }
     /// ```
     fn build_enum_match_tuple<'b>(
@@ -1187,7 +1197,6 @@ impl<'a> MethodDef<'a> {
 
                 cx.arm(sp, vec![single_pat], arm_expr)
             }).collect();
-
         // We will usually need the catch-all after matching the
         // tuples `(VariantK, VariantK, ...)` for each VariantK of the
         // enum.  But:
@@ -1223,9 +1232,14 @@ impl<'a> MethodDef<'a> {
             // ```
             let mut index_let_stmts: Vec<P<ast::Stmt>> = Vec::new();
 
+            //We also build an expression which checks whether all discriminants are equal
+            // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
+            let mut discriminant_test = cx.expr_bool(sp, true);
+
             let target_type_name =
                 find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs);
 
+            let mut first_ident = None;
             for (&ident, self_arg) in vi_idents.iter().zip(&self_args) {
                 let path = vec![cx.ident_of_std("core"),
                                 cx.ident_of("intrinsics"),
@@ -1243,32 +1257,64 @@ impl<'a> MethodDef<'a> {
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
                 index_let_stmts.push(let_stmt);
+
+                match first_ident {
+                    Some(first) => {
+                        let first_expr = cx.expr_ident(sp, first);
+                        let id = cx.expr_ident(sp, ident);
+                        let test = cx.expr_binary(sp, ast::BiEq, first_expr, id);
+                        discriminant_test = cx.expr_binary(sp, ast::BiAnd, discriminant_test, test)
+                    }
+                    None => {
+                        first_ident = Some(ident);
+                    }
+                }
             }
 
             let arm_expr = self.call_substructure_method(
                 cx, trait_, type_ident, &self_args[..], nonself_args,
                 &catch_all_substructure);
 
-            // Builds the expression:
-            // {
-            //   let __self0_vi = ...;
-            //   let __self1_vi = ...;
-            //   ...
-            //   <delegated expression referring to __self0_vi, et al.>
-            // }
-            let arm_expr = cx.expr_block(
-                cx.block_all(sp, index_let_stmts, Some(arm_expr)));
-
-            // Builds arm:
-            // _ => { let __self0_vi = ...;
-            //        let __self1_vi = ...;
-            //        ...
-            //        <delegated expression as above> }
-            let catch_all_match_arm =
-                cx.arm(sp, vec![cx.pat_wild(sp)], arm_expr);
-
-            match_arms.push(catch_all_match_arm);
-
+            //Since we know that all the arguments will match if we reach the match expression we
+            //add the unreachable intrinsics as the result of the catch all which should help llvm
+            //in optimizing it
+            let path = vec![cx.ident_of_std("core"),
+                            cx.ident_of("intrinsics"),
+                            cx.ident_of("unreachable")];
+            let call = cx.expr_call_global(
+                sp, path, vec![]);
+            let unreachable = cx.expr_block(P(ast::Block {
+                stmts: vec![],
+                expr: Some(call),
+                id: ast::DUMMY_NODE_ID,
+                rules: ast::UnsafeBlock(ast::CompilerGenerated),
+                span: sp }));
+            match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], unreachable));
+
+            // Final wrinkle: the self_args are expressions that deref
+            // down to desired l-values, but we cannot actually deref
+            // them when they are fed as r-values into a tuple
+            // expression; here add a layer of borrowing, turning
+            // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
+            let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
+            let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
+
+            //Lastly we create an expression which branches on all discriminants being equal
+            //  if discriminant_test {
+            //      match (...) {
+            //          (Variant1, Variant1, ...) => Body1
+            //          (Variant2, Variant2, ...) => Body2,
+            //          ...
+            //          _ => ::core::intrinsics::unreachable()
+            //      }
+            //  }
+            //  else {
+            //      <delegated expression referring to __self0_vi, et al.>
+            //  }
+            let all_match = cx.expr_match(sp, match_arg, match_arms);
+            let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr));
+            cx.expr_block(
+                cx.block_all(sp, index_let_stmts, Some(arm_expr)))
         } else if variants.is_empty() {
             // As an additional wrinkle, For a zero-variant enum A,
             // currently the compiler
@@ -1319,17 +1365,19 @@ impl<'a> MethodDef<'a> {
             // derive Debug on such a type could here generate code
             // that needs the feature gate enabled.)
 
-            return cx.expr_unreachable(sp);
+            cx.expr_unreachable(sp)
+        }
+        else {
+
+            // Final wrinkle: the self_args are expressions that deref
+            // down to desired l-values, but we cannot actually deref
+            // them when they are fed as r-values into a tuple
+            // expression; here add a layer of borrowing, turning
+            // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
+            let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
+            let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
+            cx.expr_match(sp, match_arg, match_arms)
         }
-
-        // Final wrinkle: the self_args are expressions that deref
-        // down to desired l-values, but we cannot actually deref
-        // them when they are fed as r-values into a tuple
-        // expression; here add a layer of borrowing, turning
-        // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
-        let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
-        let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
-        cx.expr_match(sp, match_arg, match_arms)
     }
 
     fn expand_static_enum_method_body(&self,
diff --git a/src/llvm b/src/llvm
-Subproject bff69076975642c64e76dbeaa53476bfa721208
+Subproject 8cbcdf1b72e1b23679646f6faca265f76b20d37
diff --git a/src/rustllvm/ExecutionEngineWrapper.cpp b/src/rustllvm/ExecutionEngineWrapper.cpp
index bd4fcc0fc7d..df83f32670c 100644
--- a/src/rustllvm/ExecutionEngineWrapper.cpp
+++ b/src/rustllvm/ExecutionEngineWrapper.cpp
@@ -103,9 +103,6 @@ extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
     std::string error_str;
     TargetOptions options;
 
-    options.JITEmitDebugInfo = true;
-    options.NoFramePointerElim = true;
-
     RustJITMemoryManager *mm = new RustJITMemoryManager;
 
     ExecutionEngine *ee =
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index a2ab8040198..2c0240eb8f9 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -15,12 +15,19 @@
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
+#if LLVM_VERSION_MINOR >= 7
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#else
 #include "llvm/Target/TargetLibraryInfo.h"
+#endif
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
+
 #include "llvm-c/Transforms/PassManagerBuilder.h"
 
 using namespace llvm;
+using namespace llvm::legacy;
 
 extern cl::opt<bool> EnableARMEHABI;
 
@@ -71,7 +78,6 @@ LLVMRustCreateTargetMachine(const char *triple,
                             CodeGenOpt::Level OptLevel,
                             bool EnableSegmentedStacks,
                             bool UseSoftFloat,
-                            bool NoFramePointerElim,
                             bool PositionIndependentExecutable,
                             bool FunctionSections,
                             bool DataSections) {
@@ -91,12 +97,12 @@ LLVMRustCreateTargetMachine(const char *triple,
 
     TargetOptions Options;
     Options.PositionIndependentExecutable = PositionIndependentExecutable;
-    Options.NoFramePointerElim = NoFramePointerElim;
     Options.FloatABIType = FloatABI::Default;
-    Options.UseSoftFloat = UseSoftFloat;
     if (UseSoftFloat) {
         Options.FloatABIType = FloatABI::Soft;
     }
+    Options.DataSections = DataSections;
+    Options.FunctionSections = FunctionSections;
 
     TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
                                                        real_cpu,
@@ -105,8 +111,6 @@ LLVMRustCreateTargetMachine(const char *triple,
                                                        RM,
                                                        CM,
                                                        OptLevel);
-    TM->setDataSections(DataSections);
-    TM->setFunctionSections(FunctionSections);
     return wrap(TM);
 }
 
@@ -123,12 +127,32 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
                           LLVMPassManagerRef PMR,
                           LLVMModuleRef M) {
     PassManagerBase *PM = unwrap(PMR);
-#if LLVM_VERSION_MINOR >= 6
+#if LLVM_VERSION_MINOR >= 7
+    PM->add(createTargetTransformInfoWrapperPass(
+          unwrap(TM)->getTargetIRAnalysis()));
+#else
+#if LLVM_VERSION_MINOR == 6
     PM->add(new DataLayoutPass());
 #else
     PM->add(new DataLayoutPass(unwrap(M)));
 #endif
     unwrap(TM)->addAnalysisPasses(*PM);
+#endif
+}
+
+extern "C" void
+LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
+                                    CodeGenOpt::Level OptLevel,
+                                    bool MergeFunctions,
+                                    bool SLPVectorize,
+                                    bool LoopVectorize) {
+#if LLVM_VERSION_MINOR >= 6
+    // Ignore mergefunc for now as enabling it causes crashes.
+    //unwrap(PMB)->MergeFunctions = MergeFunctions;
+#endif
+    unwrap(PMB)->SLPVectorize = SLPVectorize;
+    unwrap(PMB)->OptLevel = OptLevel;
+    unwrap(PMB)->LoopVectorize = LoopVectorize;
 }
 
 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
@@ -138,7 +162,11 @@ LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
                               LLVMModuleRef M,
                               bool DisableSimplifyLibCalls) {
     Triple TargetTriple(unwrap(M)->getTargetTriple());
+#if LLVM_VERSION_MINOR >= 7
+    TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
+#else
     TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
+#endif
     if (DisableSimplifyLibCalls)
       TLI->disableAllFunctions();
     unwrap(PMB)->LibraryInfo = TLI;
@@ -151,10 +179,17 @@ LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
                        LLVMModuleRef M,
                        bool DisableSimplifyLibCalls) {
     Triple TargetTriple(unwrap(M)->getTargetTriple());
+#if LLVM_VERSION_MINOR >= 7
+    TargetLibraryInfoImpl TLII(TargetTriple);
+    if (DisableSimplifyLibCalls)
+      TLII.disableAllFunctions();
+    unwrap(PMB)->add(new TargetLibraryInfoWrapperPass(TLII));
+#else
     TargetLibraryInfo *TLI = new TargetLibraryInfo(TargetTriple);
     if (DisableSimplifyLibCalls)
       TLI->disableAllFunctions();
     unwrap(PMB)->add(TLI);
+#endif
 }
 
 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
@@ -204,10 +239,19 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
     LLVMRustSetLastError(ErrorInfo.c_str());
     return false;
   }
-  formatted_raw_ostream FOS(OS);
 
+#if LLVM_VERSION_MINOR >= 7
+  unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
+#else
+  formatted_raw_ostream FOS(OS);
   unwrap(Target)->addPassesToEmitFile(*PM, FOS, FileType, false);
+#endif
   PM->run(*unwrap(M));
+
+  // Apparently `addPassesToEmitFile` adds an pointer to our on-the-stack output
+  // stream (OS), so the only real safe place to delete this is here? Don't we
+  // wish this was written in Rust?
+  delete PM;
   return true;
 }
 
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index ad6533e5480..70ef64afc43 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -141,6 +141,15 @@ extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const
   F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
 }
 
+extern "C" void LLVMAddFunctionAttrStringValue(LLVMValueRef Fn, unsigned index,
+                                               const char *Name,
+                                               const char *Value) {
+  Function *F = unwrap<Function>(Fn);
+  AttrBuilder B;
+  B.addAttribute(Name, Value);
+  F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
+}
+
 extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
   Function *f = unwrap<Function>(fn);
   LLVMContext &C = f->getContext();
@@ -229,9 +238,24 @@ typedef LLVMValueRef LLVMMetadataRef;
 #endif
 
 template<typename DIT>
+DIT* unwrapDIptr(LLVMMetadataRef ref) {
+    return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
+}
+
+#if LLVM_VERSION_MINOR <= 6
+template<typename DIT>
 DIT unwrapDI(LLVMMetadataRef ref) {
     return DIT(ref ? unwrap<MDNode>(ref) : NULL);
 }
+#else
+#define DIDescriptor DIScope
+#define DIArray DINodeArray
+#define unwrapDI unwrapDIptr
+#endif
+
+#if LLVM_VERSION_MINOR <= 5
+#define DISubroutineType DICompositeType
+#endif
 
 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
     return DEBUG_METADATA_VERSION;
@@ -296,7 +320,9 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
     LLVMMetadataRef ParameterTypes) {
     return wrap(Builder->createSubroutineType(
         unwrapDI<DIFile>(File),
-#if LLVM_VERSION_MINOR >= 6
+#if LLVM_VERSION_MINOR >= 7
+        DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
+#elif LLVM_VERSION_MINOR >= 6
         unwrapDI<DITypeArray>(ParameterTypes)));
 #else
         unwrapDI<DIArray>(ParameterTypes)));
@@ -322,11 +348,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
     return wrap(Builder->createFunction(
         unwrapDI<DIScope>(Scope), Name, LinkageName,
         unwrapDI<DIFile>(File), LineNo,
-        unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
+        unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
         Flags, isOptimized,
         unwrap<Function>(Fn),
-        unwrapDI<MDNode*>(TParam),
-        unwrapDI<MDNode*>(Decl)));
+        unwrapDIptr<MDNode>(TParam),
+        unwrapDIptr<MDNode>(Decl)));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
@@ -373,7 +399,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
         AlignInBits,
         Flags,
         unwrapDI<DIType>(DerivedFrom),
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Elements)),
+#else
         unwrapDI<DIArray>(Elements),
+#endif
         RunTimeLang,
         unwrapDI<DIType>(VTableHolder),
         UniqueId
@@ -436,7 +466,7 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
         unwrapDI<DIType>(Ty),
         isLocalToUnit,
         cast<Constant>(unwrap(Val)),
-        unwrapDI<MDNode*>(Decl)));
+        unwrapDIptr<MDNode>(Decl)));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
@@ -486,7 +516,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
     LLVMMetadataRef Subscripts) {
     return wrap(Builder->createArrayType(Size, AlignInBits,
         unwrapDI<DIType>(Ty),
-        unwrapDI<DIArray>(Subscripts)));
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Subscripts))
+#else
+        unwrapDI<DIArray>(Subscripts)
+#endif
+    ));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
@@ -497,7 +532,12 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
     LLVMMetadataRef Subscripts) {
     return wrap(Builder->createVectorType(Size, AlignInBits,
         unwrapDI<DIType>(Ty),
-        unwrapDI<DIArray>(Subscripts)));
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Subscripts))
+#else
+        unwrapDI<DIArray>(Subscripts)
+#endif
+    ));
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
@@ -511,12 +551,18 @@ extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
     DIBuilderRef Builder,
     LLVMMetadataRef* Ptr,
     unsigned Count) {
+#if LLVM_VERSION_MINOR >= 7
+    Metadata **DataValue = unwrap(Ptr);
+    return wrap(Builder->getOrCreateArray(
+        ArrayRef<Metadata*>(DataValue, Count)).get());
+#else
     return wrap(Builder->getOrCreateArray(
 #if LLVM_VERSION_MINOR >= 6
         ArrayRef<Metadata*>(unwrap(Ptr), Count)));
 #else
         ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
 #endif
+#endif
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
@@ -525,21 +571,21 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
     LLVMMetadataRef VarInfo,
     int64_t* AddrOps,
     unsigned AddrOpsCount,
+    LLVMValueRef DL,
     LLVMBasicBlockRef InsertAtEnd) {
-#if LLVM_VERSION_MINOR >= 6
-    DIExpression Expr;
-    if (AddrOpsCount == 0) {
-      Expr = Builder->createExpression();
-    } else {
-      llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
-      Expr = Builder->createExpression(addr_ops);
-    }
-#endif
     return wrap(Builder->insertDeclare(
         unwrap(Val),
+#if LLVM_VERSION_MINOR >= 7
+        unwrap<DILocalVariable>(VarInfo),
+#else
         unwrapDI<DIVariable>(VarInfo),
+#endif
 #if LLVM_VERSION_MINOR >= 6
-        Expr,
+        Builder->createExpression(
+          llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
+#endif
+#if LLVM_VERSION_MINOR >= 7
+        DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
 #endif
         unwrap(InsertAtEnd)));
 }
@@ -550,21 +596,23 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
     LLVMMetadataRef VarInfo,
     int64_t* AddrOps,
     unsigned AddrOpsCount,
+    LLVMValueRef DL,
     LLVMValueRef InsertBefore) {
 #if LLVM_VERSION_MINOR >= 6
-    DIExpression Expr;
-    if (AddrOpsCount == 0) {
-      Expr = Builder->createExpression();
-    } else {
-      llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
-      Expr = Builder->createExpression(addr_ops);
-    }
 #endif
     return wrap(Builder->insertDeclare(
         unwrap(Val),
+#if LLVM_VERSION_MINOR >= 7
+        unwrap<DILocalVariable>(VarInfo),
+#else
         unwrapDI<DIVariable>(VarInfo),
+#endif
 #if LLVM_VERSION_MINOR >= 6
-        Expr,
+        Builder->createExpression(
+          llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
+#endif
+#if LLVM_VERSION_MINOR >= 7
+        DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
 #endif
         unwrap<Instruction>(InsertBefore)));
 }
@@ -595,7 +643,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
         LineNumber,
         SizeInBits,
         AlignInBits,
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Elements)),
+#else
         unwrapDI<DIArray>(Elements),
+#endif
         unwrapDI<DIType>(ClassType)));
 }
 
@@ -620,7 +672,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
         SizeInBits,
         AlignInBits,
         Flags,
+#if LLVM_VERSION_MINOR >= 7
+        DINodeArray(unwrapDI<MDTuple>(Elements)),
+#else
         unwrapDI<DIArray>(Elements),
+#endif
         RunTimeLang,
         UniqueId
         ));
@@ -638,10 +694,14 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
     return wrap(Builder->createTemplateTypeParameter(
       unwrapDI<DIDescriptor>(Scope),
       Name,
-      unwrapDI<DIType>(Ty),
+      unwrapDI<DIType>(Ty)
+#if LLVM_VERSION_MINOR <= 6
+      ,
       unwrapDI<MDNode*>(File),
       LineNo,
-      ColumnNo));
+      ColumnNo
+#endif
+      ));
 }
 
 extern "C" int64_t LLVMDIBuilderCreateOpDeref()
@@ -673,7 +733,10 @@ extern "C" void LLVMDICompositeTypeSetTypeArray(
     LLVMMetadataRef CompositeType,
     LLVMMetadataRef TypeArray)
 {
-#if LLVM_VERSION_MINOR >= 6
+#if LLVM_VERSION_MINOR >= 7
+    DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
+    Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
+#elif LLVM_VERSION_MINOR >= 6
     DICompositeType tmp = unwrapDI<DICompositeType>(CompositeType);
     Builder->replaceArrays(tmp, unwrapDI<DIArray>(TypeArray));
 #else
@@ -692,11 +755,15 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
 
     DebugLoc debug_loc = DebugLoc::get(Line,
                                        Column,
-                                       unwrapDI<MDNode*>(Scope),
-                                       unwrapDI<MDNode*>(InlinedAt));
+                                       unwrapDIptr<MDNode>(Scope),
+                                       unwrapDIptr<MDNode>(InlinedAt));
 
 #if LLVM_VERSION_MINOR >= 6
-    return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context)));
+    return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(
+#if LLVM_VERSION_MINOR <= 6
+            context
+#endif
+        )));
 #else
     return wrap(debug_loc.getAsMDNode(context));
 #endif
@@ -721,7 +788,12 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
     Module *Dst = unwrap(dst);
 #if LLVM_VERSION_MINOR >= 6
     std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
+#if LLVM_VERSION_MINOR >= 7
+    ErrorOr<std::unique_ptr<Module>> Src =
+        llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
+#else
     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
+#endif
 #else
     MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
@@ -739,7 +811,11 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
 #if LLVM_VERSION_MINOR >= 6
     raw_string_ostream Stream(Err);
     DiagnosticPrinterRawOStream DP(Stream);
+#if LLVM_VERSION_MINOR >= 7
+    if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
+#else
     if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
+#endif
 #else
     if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
 #endif
@@ -813,8 +889,12 @@ extern "C" const Archive::Child*
 LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
     if (rai->cur == rai->end)
         return NULL;
+#if LLVM_VERSION_MINOR >= 6
     const Archive::Child &ret = *rai->cur;
     return &ret;
+#else
+    return rai->cur.operator->();
+#endif
 }
 
 extern "C" void
@@ -942,7 +1022,11 @@ extern "C" void LLVMWriteDebugLocToString(
     RustStringRef str)
 {
     raw_rust_string_ostream os(str);
+#if LLVM_VERSION_MINOR >= 7
+    unwrap(dl)->print(os);
+#else
     unwrap(dl)->print(*unwrap(C), os);
+#endif
 }
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 1ea40fc46a5..38b7b49a344 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2015-03-04
+2015-06-16
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index bb82c0c8186..2a47e8b0895 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -12,7 +12,6 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
-#include "llvm/PassManager.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Analysis/Passes.h"
@@ -46,6 +45,12 @@
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/Object.h"
 
+#if LLVM_VERSION_MINOR >= 7
+#include "llvm/IR/LegacyPassManager.h"
+#else
+#include "llvm/PassManager.h"
+#endif
+
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DIBuilder.h"
diff --git a/src/test/auxiliary/llvm_pass_plugin.rs b/src/test/auxiliary/llvm_pass_plugin.rs
index d61f47fd7ef..bacc1acd3c4 100644
--- a/src/test/auxiliary/llvm_pass_plugin.rs
+++ b/src/test/auxiliary/llvm_pass_plugin.rs
@@ -24,5 +24,5 @@ pub fn plugin_registrar(reg: &mut Registry) {
     // Normally, we would name a pass that was registered through
     // C++ static object constructors in the same .so file as the
     // plugin registrar.
-    reg.register_llvm_pass("inline");
+    reg.register_llvm_pass("gvn");
 }
diff --git a/src/test/codegen/loads.rs b/src/test/codegen/loads.rs
index 20a55740bb7..45b8731c3b1 100644
--- a/src/test/codegen/loads.rs
+++ b/src/test/codegen/loads.rs
@@ -20,14 +20,14 @@ pub struct Bytes {
 // CHECK-LABEL: @borrow
 #[no_mangle]
 pub fn borrow(x: &i32) -> &i32 {
-// CHECK: load i32** %x{{.*}}, !nonnull
+// CHECK: load i32*, i32** %x{{.*}}, !nonnull
     x
 }
 
 // CHECK-LABEL: @_box
 #[no_mangle]
 pub fn _box(x: Box<i32>) -> i32 {
-// CHECK: load i32** %x{{.*}}, !nonnull
+// CHECK: load i32*, i32** %x{{.*}}, !nonnull
     *x
 }
 
@@ -36,7 +36,7 @@ pub fn _box(x: Box<i32>) -> i32 {
 // dependent alignment
 #[no_mangle]
 pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
-// CHECK: [[VAR:%[0-9]+]] = load i32* %{{.*}}, align 1
+// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
 // CHECK: ret i32 [[VAR]]
     x
 }
@@ -46,7 +46,7 @@ pub fn small_array_alignment(x: [i8; 4]) -> [i8; 4] {
 // dependent alignment
 #[no_mangle]
 pub fn small_struct_alignment(x: Bytes) -> Bytes {
-// CHECK: [[VAR:%[0-9]+]] = load i32* %{{.*}}, align 1
+// CHECK: [[VAR:%[0-9]+]] = load i32, i32* %{{.*}}, align 1
 // CHECK: ret i32 [[VAR]]
     x
 }
diff --git a/src/test/codegen/stores.rs b/src/test/codegen/stores.rs
index 32337b085cd..15cf76b2ab1 100644
--- a/src/test/codegen/stores.rs
+++ b/src/test/codegen/stores.rs
@@ -22,7 +22,7 @@ pub struct Bytes {
 // dependent alignment
 #[no_mangle]
 pub fn small_array_alignment(x: &mut [i8; 4]) {
-// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]** %x
+// CHECK: [[VAR:%[0-9]+]] = load [4 x i8]*, [4 x i8]** %x
 // CHECK: [[VAR2:%[0-9]+]] = bitcast [4 x i8]* [[VAR]] to i32*
 // CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
     *x = [0; 4];
@@ -33,7 +33,7 @@ pub fn small_array_alignment(x: &mut [i8; 4]) {
 // dependent alignment
 #[no_mangle]
 pub fn small_struct_alignment(x: &mut Bytes) {
-// CHECK: [[VAR:%[0-9]+]] = load %Bytes** %x
+// CHECK: [[VAR:%[0-9]+]] = load %Bytes*, %Bytes** %x
 // CHECK: [[VAR2:%[0-9]+]] = bitcast %Bytes* [[VAR]] to i32*
 // CHECK: store i32 %{{.*}}, i32* [[VAR2]], align 1
     *x = Bytes {
diff --git a/src/test/compile-fail/issue-26262.rs b/src/test/compile-fail/issue-26262.rs
new file mode 100644
index 00000000000..8d79fd4570d
--- /dev/null
+++ b/src/test/compile-fail/issue-26262.rs
@@ -0,0 +1,32 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that projections don't count as constraining type parameters.
+
+struct S<T>(T);
+
+trait Tr { type Assoc; fn test(); }
+
+impl<T: Tr> S<T::Assoc> {
+//~^ ERROR the type parameter `T` is not constrained
+    fn foo(self, _: T) {
+        T::test();
+    }
+}
+
+trait Trait1<T> { type Bar; }
+trait Trait2<'x> { type Foo; }
+
+impl<'a,T: Trait2<'a>> Trait1<<T as Trait2<'a>>::Foo> for T {
+//~^ ERROR the lifetime parameter `'a` is not constrained
+    type Bar = &'a ();
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/lint-dead-code-variant.rs b/src/test/compile-fail/lint-dead-code-variant.rs
new file mode 100644
index 00000000000..0116d63caf2
--- /dev/null
+++ b/src/test/compile-fail/lint-dead-code-variant.rs
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(dead_code)]
+
+#[derive(Clone)]
+enum Enum {
+    Variant1, //~ ERROR: variant is never used
+    Variant2,
+}
+
+fn main() {
+    let e = Enum::Variant2;
+    e.clone();
+}
diff --git a/src/test/run-pass/asm-in-out-operand.rs b/src/test/run-pass/asm-in-out-operand.rs
index 3eebc7acb0f..243ecf86e9c 100644
--- a/src/test/run-pass/asm-in-out-operand.rs
+++ b/src/test/run-pass/asm-in-out-operand.rs
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 #![feature(asm)]
 
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 unsafe fn next_power_of_2(n: u32) -> u32 {
     let mut tmp = n;
     asm!("dec $0" : "+rm"(tmp) :: "cc");
-    let mut shift = 1_usize;
+    let mut shift = 1_u32;
     while shift <= 16 {
         asm!(
             "shr %cl, $2
diff --git a/src/test/run-pass/associated-types-method.rs b/src/test/run-pass/associated-types-method.rs
new file mode 100644
index 00000000000..b57687a49fa
--- /dev/null
+++ b/src/test/run-pass/associated-types-method.rs
@@ -0,0 +1,36 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that methods whose impl-trait-ref contains associated types
+// are supported.
+
+trait Device {
+    type Resources;
+}
+struct Foo<D, R>(D, R);
+
+trait Tr {
+    fn present(&self) {}
+}
+
+impl<D: Device> Tr for Foo<D, D::Resources> {
+    fn present(&self) {}
+}
+
+struct Res;
+struct Dev;
+impl Device for Dev {
+    type Resources = Res;
+}
+
+fn main() {
+    let foo = Foo(Dev, Res);
+    foo.present();
+}
diff --git a/src/test/run-pass/issue-25089.rs b/src/test/run-pass/issue-25089.rs
new file mode 100644
index 00000000000..b619d1dd448
--- /dev/null
+++ b/src/test/run-pass/issue-25089.rs
@@ -0,0 +1,40 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::thread;
+
+struct Foo(i32);
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        static mut DROPPED: bool = false;
+        unsafe {
+            assert!(!DROPPED);
+            DROPPED = true;
+        }
+    }
+}
+
+struct Empty;
+
+fn empty() -> Empty { Empty }
+
+fn should_panic(_: Foo, _: Empty) {
+    panic!("test panic");
+}
+
+fn test() {
+    should_panic(Foo(1), empty());
+}
+
+fn main() {
+    let ret = thread::spawn(test).join();
+    assert!(ret.is_err());
+}
diff --git a/src/test/run-pass/issue-25679.rs b/src/test/run-pass/issue-25679.rs
new file mode 100644
index 00000000000..0ba7feece60
--- /dev/null
+++ b/src/test/run-pass/issue-25679.rs
@@ -0,0 +1,28 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Device {
+    type Resources;
+}
+struct Foo<D, R>(D, R);
+
+impl<D: Device> Foo<D, D::Resources> {
+    fn present(&self) {}
+}
+
+struct Res;
+struct Dev;
+
+impl Device for Dev { type Resources = Res; }
+
+fn main() {
+    let foo = Foo(Dev, Res);
+    foo.present();
+}
diff --git a/src/test/run-pass/lint-dead-code-variant.rs b/src/test/run-pass/lint-dead-code-variant.rs
new file mode 100644
index 00000000000..074c69d8708
--- /dev/null
+++ b/src/test/run-pass/lint-dead-code-variant.rs
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(dead_code)]
+
+enum Foo {
+    A,
+    B,
+}
+
+pub fn main() {
+    match Foo::A {
+        Foo::A | Foo::B => Foo::B
+    };
+}
diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs
index 969cf853f05..cd99b39fdd0 100644
--- a/src/test/run-pass/sync-send-iterators-in-libcore.rs
+++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs
@@ -10,28 +10,101 @@
 
 // pretty-expanded FIXME #23616
 
+#![allow(unused_mut)]
+#![feature(core)]
 #![feature(collections)]
+#![feature(step_by)]
+#![feature(iter_empty)]
+#![feature(iter_once)]
+
+use std::iter::{empty, once, range_inclusive, repeat, Unfold};
 
 fn is_sync<T>(_: T) where T: Sync {}
 fn is_send<T>(_: T) where T: Send {}
 
 macro_rules! all_sync_send {
+    ($ctor:expr, $iter:ident) => ({
+        let mut x = $ctor;
+        is_sync(x.$iter());
+        let mut y = $ctor;
+        is_send(y.$iter());
+    });
+    ($ctor:expr, $iter:ident($($param:expr),+)) => ({
+        let mut x = $ctor;
+        is_sync(x.$iter($( $param ),+));
+        let mut y = $ctor;
+        is_send(y.$iter($( $param ),+));
+    });
+    ($ctor:expr, $iter:ident, $($rest:tt)*) => ({
+        all_sync_send!($ctor, $iter);
+        all_sync_send!($ctor, $($rest)*);
+    });
+    ($ctor:expr, $iter:ident($($param:expr),+), $($rest:tt)*) => ({
+        all_sync_send!($ctor, $iter($( $param ),+));
+        all_sync_send!($ctor, $($rest)*);
+    });
+}
+
+macro_rules! all_sync_send_mutable_ref {
     ($ctor:expr, $($iter:ident),+) => ({
         $(
             let mut x = $ctor;
-            is_sync(x.$iter());
+            is_sync((&mut x).$iter());
             let mut y = $ctor;
-            is_send(y.$iter());
+            is_send((&mut y).$iter());
         )+
     })
 }
 
+macro_rules! is_sync_send {
+    ($ctor:expr) => ({
+        let x = $ctor;
+        is_sync(x);
+        let y = $ctor;
+        is_send(y);
+    })
+}
+
 fn main() {
     // for char.rs
     all_sync_send!("Я", escape_default, escape_unicode);
 
     // for iter.rs
-    // FIXME
+    all_sync_send_mutable_ref!([1], iter);
+
+    // Bytes implements DoubleEndedIterator
+    all_sync_send!("a".bytes(), rev);
+
+    let a = [1];
+    let b = [2];
+    all_sync_send!(a.iter(),
+                   cloned,
+                   cycle,
+                   chain([2].iter()),
+                   zip([2].iter()),
+                   map(|_| 1),
+                   filter(|_| true),
+                   filter_map(|_| Some(1)),
+                   enumerate,
+                   peekable,
+                   skip_while(|_| true),
+                   take_while(|_| true),
+                   skip(1),
+                   take(1),
+                   scan(1, |_, _| Some(1)),
+                   flat_map(|_| b.iter()),
+                   fuse,
+                   inspect(|_| ()));
+
+    is_sync_send!(Unfold::new(Some(1), |&mut v| v));
+    is_sync_send!((1..).step_by(2));
+    is_sync_send!(range_inclusive(1, 1));
+    is_sync_send!((1..2).step_by(2));
+    is_sync_send!((1..2));
+    is_sync_send!((1..));
+    is_sync_send!(repeat(1));
+    is_sync_send!(empty::<usize>());
+    is_sync_send!(once(1));
 
     // for option.rs
     // FIXME