about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGlyne J. Gittens <Jgit121@gmail.com>2017-02-19 17:32:21 -0500
committerGlyne J. Gittens <Jgit121@gmail.com>2017-02-19 17:32:21 -0500
commit9a6a72b81837bed367de38297479ad554537d70c (patch)
treea9fc17869c699ea448d458d2194dec241e410099 /src
parentb3f61ce538862e58d4d3cb02960fe6e9a8ccc4e4 (diff)
parent0e77277950aafd38ce3e52b7b1cd9bcc6664de3c (diff)
Merge branch 'master' of https://github.com/rust-lang/rust
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/bin/rustc.rs5
-rw-r--r--src/bootstrap/bootstrap.py56
-rw-r--r--src/bootstrap/native.rs6
-rw-r--r--src/doc/book/src/procedural-macros.md2
-rw-r--r--src/libcollections/string.rs18
-rw-r--r--src/libcore/iter/iterator.rs6
m---------src/liblibc0
-rw-r--r--src/librustc/dep_graph/dep_node.rs46
-rw-r--r--src/librustc/hir/def.rs39
-rw-r--r--src/librustc/hir/lowering.rs16
-rw-r--r--src/librustc/mir/mod.rs21
-rw-r--r--src/librustc/mir/tcx.rs1
-rw-r--r--src/librustc/mir/visit.rs21
-rw-r--r--src/librustc/traits/mod.rs5
-rw-r--r--src/librustc/traits/select.rs4
-rw-r--r--src/librustc/ty/mod.rs30
-rw-r--r--src/librustc/ty/relate.rs2
-rw-r--r--src/librustc/ty/subst.rs6
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/impls.rs1
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs1
-rw-r--r--src/librustc_borrowck/borrowck/mir/gather_moves.rs4
-rw-r--r--src/librustc_borrowck/borrowck/mir/mod.rs1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs16
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/expr/stmt.rs17
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs5
-rw-r--r--src/librustc_mir/transform/type_check.rs5
-rw-r--r--src/librustc_passes/mir_stats.rs2
-rw-r--r--src/librustc_resolve/lib.rs79
-rw-r--r--src/librustc_resolve/macros.rs2
-rw-r--r--src/librustc_trans/collector.rs5
-rw-r--r--src/librustc_trans/context.rs3
-rw-r--r--src/librustc_trans/mir/constant.rs3
-rw-r--r--src/librustc_trans/mir/rvalue.rs21
-rw-r--r--src/librustc_trans/mir/statement.rs14
-rw-r--r--src/librustc_typeck/astconv.rs14
-rw-r--r--src/librustc_typeck/check/method/confirm.rs6
-rw-r--r--src/librustc_typeck/check/method/probe.rs4
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/libstd/env.rs15
-rw-r--r--src/libstd/sync/once.rs2
-rw-r--r--src/libstd/sys/unix/os.rs38
-rw-r--r--src/libstd/thread/local.rs4
-rw-r--r--src/rustllvm/llvm-auto-clean-trigger2
-rw-r--r--src/test/compile-fail/issue-39559.rs31
-rw-r--r--src/test/compile-fail/resolve-self-in-impl.rs3
-rw-r--r--src/test/run-pass/issue-39292.rs26
47 files changed, 390 insertions, 222 deletions
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 90fd31ecbdd..62e476bd737 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -205,6 +205,11 @@ fn main() {
                 }
             }
         }
+
+        if target.contains("pc-windows-msvc") {
+            cmd.arg("-Z").arg("unstable-options");
+            cmd.arg("-C").arg("target-feature=+crt-static");
+        }
     }
 
     if verbose > 1 {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index ee3f663dbd5..7ca7ef4bd72 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -173,6 +173,8 @@ class RustBuild(object):
             if not os.path.exists(tarball):
                 get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
             unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose)
+            self.fix_executable(self.bin_root() + "/bin/rustc")
+            self.fix_executable(self.bin_root() + "/bin/rustdoc")
             with open(self.rustc_stamp(), 'w') as f:
                 f.write(self.stage0_rustc_date())
 
@@ -185,9 +187,63 @@ class RustBuild(object):
             if not os.path.exists(tarball):
                 get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
             unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose)
+            self.fix_executable(self.bin_root() + "/bin/cargo")
             with open(self.cargo_stamp(), 'w') as f:
                 f.write(self.stage0_cargo_rev())
 
+    def fix_executable(self, fname):
+        # If we're on NixOS we need to change the path to the dynamic loader
+
+        default_encoding = sys.getdefaultencoding()
+        try:
+            ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding)
+        except (subprocess.CalledProcessError, WindowsError):
+            return
+
+        if ostype != "Linux":
+            return
+
+        if not os.path.exists("/etc/NIXOS"):
+            return
+        if os.path.exists("/lib"):
+            return
+
+        # At this point we're pretty sure the user is running NixOS
+        print("info: you seem to be running NixOS. Attempting to patch " + fname)
+
+        try:
+            interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname])
+            interpreter = interpreter.strip().decode(default_encoding)
+        except subprocess.CalledProcessError as e:
+            print("warning: failed to call patchelf: %s" % e)
+            return
+
+        loader = interpreter.split("/")[-1]
+
+        try:
+            ldd_output = subprocess.check_output(['ldd', '/run/current-system/sw/bin/sh'])
+            ldd_output = ldd_output.strip().decode(default_encoding)
+        except subprocess.CalledProcessError as e:
+            print("warning: unable to call ldd: %s" % e)
+            return
+
+        for line in ldd_output.splitlines():
+            libname = line.split()[0]
+            if libname.endswith(loader):
+                loader_path = libname[:len(libname) - len(loader)]
+                break
+        else:
+            print("warning: unable to find the path to the dynamic linker")
+            return
+
+        correct_interpreter = loader_path + loader
+
+        try:
+            subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname])
+        except subprocess.CalledProcessError as e:
+            print("warning: failed to call patchelf: %s" % e)
+            return
+
     def stage0_cargo_rev(self):
         return self._cargo_rev
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 21fc61cc814..f16fc2092f6 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -99,6 +99,12 @@ pub fn llvm(build: &Build, target: &str) {
        .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
        .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
 
+    if target.contains("msvc") {
+        cfg.define("LLVM_USE_CRT_DEBUG", "MT");
+        cfg.define("LLVM_USE_CRT_RELEASE", "MT");
+        cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT");
+    }
+
     if target.starts_with("i686") {
         cfg.define("LLVM_BUILD_32_BITS", "ON");
     }
diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md
index 6c4700f9305..079324d56d1 100644
--- a/src/doc/book/src/procedural-macros.md
+++ b/src/doc/book/src/procedural-macros.md
@@ -169,7 +169,7 @@ So this is where quotes comes in. The `ast` argument is a struct that gives us
 a representation of our type (which can be either a `struct` or an `enum`).
 Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html),
 there is some useful information there. We are able to get the name of the
-type using `ast.ident`. The `quote!` macro let's us write up the Rust code
+type using `ast.ident`. The `quote!` macro lets us write up the Rust code
 that we wish to return and convert it into `Tokens`. `quote!` let's us use some
 really cool templating mechanics; we simply write `#name` and `quote!` will
 replace it with the variable named `name`. You can even do some repetition
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 4c82e2e2e7e..e92eb4ff7bd 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1250,17 +1250,17 @@ impl String {
         self.len() == 0
     }
 
-    /// Divide one string into two at an index.
+    /// Splits the string into two at the given index.
     ///
-    /// The argument, `mid`, should be a byte offset from the start of the string. It must also
-    /// be on the boundary of a UTF-8 code point.
+    /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and
+    /// the returned `String` contains bytes `[at, len)`. `at` must be on the
+    /// boundary of a UTF-8 code point.
     ///
-    /// The two strings returned go from the start of the string to `mid`, and from `mid` to the end
-    /// of the string.
+    /// Note that the capacity of `self` does not change.
     ///
     /// # Panics
     ///
-    /// Panics if `mid` is not on a `UTF-8` code point boundary, or if it is beyond the last
+    /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last
     /// code point of the string.
     ///
     /// # Examples
@@ -1275,9 +1275,9 @@ impl String {
     /// ```
     #[inline]
     #[stable(feature = "string_split_off", since = "1.16.0")]
-    pub fn split_off(&mut self, mid: usize) -> String {
-        assert!(self.is_char_boundary(mid));
-        let other = self.vec.split_off(mid);
+    pub fn split_off(&mut self, at: usize) -> String {
+        assert!(self.is_char_boundary(at));
+        let other = self.vec.split_off(at);
         unsafe { String::from_utf8_unchecked(other) }
     }
 
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index d41767cce18..3785bbe9bb0 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -1603,12 +1603,12 @@ pub trait Iterator {
         let mut i = self.len();
 
         while let Some(v) = self.next_back() {
-            if predicate(v) {
-                return Some(i - 1);
-            }
             // No need for an overflow check here, because `ExactSizeIterator`
             // implies that the number of elements fits into a `usize`.
             i -= 1;
+            if predicate(v) {
+                return Some(i);
+            }
         }
         None
     }
diff --git a/src/liblibc b/src/liblibc
-Subproject 8d8264b967a31a1a8cebe2a05110564106b6e90
+Subproject 7a3754f2bb5e65eb39adacb189c362617303217
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 006de1c06e2..96d1a925425 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -131,7 +131,37 @@ pub enum DepNode<D: Clone + Debug> {
     // which would yield an overly conservative dep-graph.
     TraitItems(D),
     ReprHints(D),
-    TraitSelect(Vec<D>),
+
+    // Trait selection cache is a little funny. Given a trait
+    // reference like `Foo: SomeTrait<Bar>`, there could be
+    // arbitrarily many def-ids to map on in there (e.g., `Foo`,
+    // `SomeTrait`, `Bar`). We could have a vector of them, but it
+    // requires heap-allocation, and trait sel in general can be a
+    // surprisingly hot path. So instead we pick two def-ids: the
+    // trait def-id, and the first def-id in the input types. If there
+    // is no def-id in the input types, then we use the trait def-id
+    // again. So for example:
+    //
+    // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
+    // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
+    // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
+    // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
+    // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
+    // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
+    // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
+    // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
+    // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
+    //
+    // You can see that we map many trait refs to the same
+    // trait-select node.  This is not a problem, it just means
+    // imprecision in our dep-graph tracking.  The important thing is
+    // that for any given trait-ref, we always map to the **same**
+    // trait-select node.
+    TraitSelect { trait_def_id: D, input_def_id: D },
+
+    // For proj. cache, we just keep a list of all def-ids, since it is
+    // not a hotspot.
+    ProjectionCache { def_ids: Vec<D> },
 }
 
 impl<D: Clone + Debug> DepNode<D> {
@@ -236,9 +266,17 @@ impl<D: Clone + Debug> DepNode<D> {
             TraitImpls(ref d) => op(d).map(TraitImpls),
             TraitItems(ref d) => op(d).map(TraitItems),
             ReprHints(ref d) => op(d).map(ReprHints),
-            TraitSelect(ref type_ds) => {
-                let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect());
-                Some(TraitSelect(type_ds))
+            TraitSelect { ref trait_def_id, ref input_def_id } => {
+                op(trait_def_id).and_then(|trait_def_id| {
+                    op(input_def_id).and_then(|input_def_id| {
+                        Some(TraitSelect { trait_def_id: trait_def_id,
+                                           input_def_id: input_def_id })
+                    })
+                })
+            }
+            ProjectionCache { ref def_ids } => {
+                let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
+                def_ids.map(|d| ProjectionCache { def_ids: d })
             }
         }
     }
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index b6fce2d6ca0..53b7be74f85 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -59,32 +59,45 @@ pub enum Def {
     Err,
 }
 
-/// The result of resolving a path.
-/// Before type checking completes, `depth` represents the number of
-/// trailing segments which are yet unresolved. Afterwards, if there
-/// were no errors, all paths should be fully resolved, with `depth`
-/// set to `0` and `base_def` representing the final resolution.
-///
+/// The result of resolving a path before lowering to HIR.
+/// `base_def` is definition of resolved part of the
+/// path, `unresolved_segments` is the number of unresolved
+/// segments.
 ///     module::Type::AssocX::AssocY::MethodOrAssocType
 ///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-///     base_def      depth = 3
+///     base_def      unresolved_segments = 3
 ///
 ///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
 ///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
-///           base_def        depth = 2
+///           base_def        unresolved_segments = 2
 #[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
-    pub base_def: Def,
-    pub depth: usize
+    base_def: Def,
+    unresolved_segments: usize,
 }
 
 impl PathResolution {
-    pub fn new(def: Def) -> PathResolution {
-        PathResolution { base_def: def, depth: 0 }
+    pub fn new(def: Def) -> Self {
+        PathResolution { base_def: def, unresolved_segments: 0 }
+    }
+
+    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
+        if def == Def::Err { unresolved_segments = 0 }
+        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
+    }
+
+    #[inline]
+    pub fn base_def(&self) -> Def {
+        self.base_def
+    }
+
+    #[inline]
+    pub fn unresolved_segments(&self) -> usize {
+        self.unresolved_segments
     }
 
     pub fn kind_name(&self) -> &'static str {
-        if self.depth != 0 {
+        if self.unresolved_segments != 0 {
             "associated item"
         } else {
             self.base_def.kind_name()
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 8a4acb3d038..c87ce6505fc 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -217,10 +217,10 @@ impl<'a> LoweringContext<'a> {
 
     fn expect_full_def(&mut self, id: NodeId) -> Def {
         self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
-            if pr.depth != 0 {
+            if pr.unresolved_segments() != 0 {
                 bug!("path not fully resolved: {:?}", pr);
             }
-            pr.base_def
+            pr.base_def()
         })
     }
 
@@ -421,9 +421,9 @@ impl<'a> LoweringContext<'a> {
         let resolution = self.resolver.get_resolution(id)
                                       .unwrap_or(PathResolution::new(Def::Err));
 
-        let proj_start = p.segments.len() - resolution.depth;
+        let proj_start = p.segments.len() - resolution.unresolved_segments();
         let path = P(hir::Path {
-            def: resolution.base_def,
+            def: resolution.base_def(),
             segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
                 let param_mode = match (qself_position, param_mode) {
                     (Some(j), ParamMode::Optional) if i < j => {
@@ -443,7 +443,7 @@ impl<'a> LoweringContext<'a> {
                         index: this.def_key(def_id).parent.expect("missing parent")
                     }
                 };
-                let type_def_id = match resolution.base_def {
+                let type_def_id = match resolution.base_def() {
                     Def::AssociatedTy(def_id) if i + 2 == proj_start => {
                         Some(parent_def_id(self, def_id))
                     }
@@ -474,7 +474,7 @@ impl<'a> LoweringContext<'a> {
 
         // Simple case, either no projections, or only fully-qualified.
         // E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
-        if resolution.depth == 0 {
+        if resolution.unresolved_segments() == 0 {
             return hir::QPath::Resolved(qself, path);
         }
 
@@ -749,7 +749,7 @@ impl<'a> LoweringContext<'a> {
                                        bound_pred.bound_lifetimes.is_empty() => {
                                 if let Some(Def::TyParam(def_id)) =
                                         self.resolver.get_resolution(bound_pred.bounded_ty.id)
-                                                     .map(|d| d.base_def) {
+                                                     .map(|d| d.base_def()) {
                                     if let Some(node_id) =
                                             self.resolver.definitions().as_local_node_id(def_id) {
                                         for ty_param in &g.ty_params {
@@ -1295,7 +1295,7 @@ impl<'a> LoweringContext<'a> {
                 PatKind::Wild => hir::PatKind::Wild,
                 PatKind::Ident(ref binding_mode, pth1, ref sub) => {
                     self.with_parent_def(p.id, |this| {
-                        match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
+                        match this.resolver.get_resolution(p.id).map(|d| d.base_def()) {
                             // `None` can occur in body-less function signatures
                             def @ None | def @ Some(Def::Local(_)) => {
                                 let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index d8212807eb2..3403cf04774 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -777,6 +777,12 @@ pub enum StatementKind<'tcx> {
     /// End the current live range for the storage of the local.
     StorageDead(Lvalue<'tcx>),
 
+    InlineAsm {
+        asm: InlineAsm,
+        outputs: Vec<Lvalue<'tcx>>,
+        inputs: Vec<Operand<'tcx>>
+    },
+
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
 }
@@ -790,7 +796,10 @@ impl<'tcx> Debug for Statement<'tcx> {
             StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
             SetDiscriminant{lvalue: ref lv, variant_index: index} => {
                 write!(fmt, "discriminant({:?}) = {:?}", lv, index)
-            }
+            },
+            InlineAsm { ref asm, ref outputs, ref inputs } => {
+                write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
+            },
             Nop => write!(fmt, "nop"),
         }
     }
@@ -1004,12 +1013,6 @@ pub enum Rvalue<'tcx> {
     /// that `Foo` has a destructor. These rvalues can be optimized
     /// away after type-checking and before lowering.
     Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
-
-    InlineAsm {
-        asm: InlineAsm,
-        outputs: Vec<Lvalue<'tcx>>,
-        inputs: Vec<Operand<'tcx>>
-    }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
@@ -1111,10 +1114,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
             UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
             Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval),
             Box(ref t) => write!(fmt, "Box({:?})", t),
-            InlineAsm { ref asm, ref outputs, ref inputs } => {
-                write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
-            }
-
             Ref(_, borrow_kind, ref lv) => {
                 let kind_str = match borrow_kind {
                     BorrowKind::Shared => "",
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 7b0863b4c42..5c8d031caf6 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -207,7 +207,6 @@ impl<'tcx> Rvalue<'tcx> {
                     }
                 }
             }
-            Rvalue::InlineAsm { .. } => None
         }
     }
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index be3c43db7ba..7cdbd5cae06 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -333,6 +333,16 @@ macro_rules! make_mir_visitor {
                     StatementKind::StorageDead(ref $($mutability)* lvalue) => {
                         self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
                     }
+                    StatementKind::InlineAsm { ref $($mutability)* outputs,
+                                               ref $($mutability)* inputs,
+                                               asm: _ } => {
+                        for output in & $($mutability)* outputs[..] {
+                            self.visit_lvalue(output, LvalueContext::Store, location);
+                        }
+                        for input in & $($mutability)* inputs[..] {
+                            self.visit_operand(input, location);
+                        }
+                    }
                     StatementKind::Nop => {}
                 }
             }
@@ -526,17 +536,6 @@ macro_rules! make_mir_visitor {
                             self.visit_operand(operand, location);
                         }
                     }
-
-                    Rvalue::InlineAsm { ref $($mutability)* outputs,
-                                        ref $($mutability)* inputs,
-                                        asm: _ } => {
-                        for output in & $($mutability)* outputs[..] {
-                            self.visit_lvalue(output, LvalueContext::Store, location);
-                        }
-                        for input in & $($mutability)* inputs[..] {
-                            self.visit_operand(input, location);
-                        }
-                    }
                 }
             }
 
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 4893e240911..58ab713ef27 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -628,6 +628,11 @@ pub fn get_vtable_methods<'a, 'tcx>(
                                           |_, _| tcx.mk_region(ty::ReErased),
                                           |def, _| trait_ref.substs().type_for_def(def));
 
+            // the trait type may have higher-ranked lifetimes in it;
+            // so erase them if they appear, so that we get the type
+            // at some particular call site
+            let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs));
+
             // It's possible that the method relies on where clauses that
             // do not hold for this particular set of type parameters.
             // Note that this method could then never be called, so we
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 41f3f825c3d..40c62762c3c 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2547,7 +2547,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 // TyError and ensure they do not affect any other fields.
                 // This could be checked after type collection for any struct
                 // with a potentially unsized trailing field.
-                let params = substs_a.params().iter().enumerate().map(|(i, &k)| {
+                let params = substs_a.iter().enumerate().map(|(i, &k)| {
                     if ty_params.contains(i) {
                         Kind::from(tcx.types.err)
                     } else {
@@ -2567,7 +2567,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
                 // Check that the source structure with the target's
                 // type parameters is a subtype of the target.
-                let params = substs_a.params().iter().enumerate().map(|(i, &k)| {
+                let params = substs_a.iter().enumerate().map(|(i, &k)| {
                     if ty_params.contains(i) {
                         Kind::from(substs_b.type_at(i))
                     } else {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 411e14531fa..7937d2ccfe4 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -34,7 +34,6 @@ use serialize::{self, Encodable, Encoder};
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell, Ref};
 use std::hash::{Hash, Hasher};
-use std::iter;
 use std::ops::Deref;
 use std::rc::Rc;
 use std::slice;
@@ -843,27 +842,22 @@ impl<'tcx> TraitPredicate<'tcx> {
 
     /// Creates the dep-node for selecting/evaluating this trait reference.
     fn dep_node(&self) -> DepNode<DefId> {
-        // Ideally, the dep-node would just have all the input types
-        // in it.  But they are limited to including def-ids. So as an
-        // approximation we include the def-ids for all nominal types
-        // found somewhere. This means that we will e.g. conflate the
-        // dep-nodes for `u32: SomeTrait` and `u64: SomeTrait`, but we
-        // would have distinct dep-nodes for `Vec<u32>: SomeTrait`,
-        // `Rc<u32>: SomeTrait`, and `(Vec<u32>, Rc<u32>): SomeTrait`.
-        // Note that it's always sound to conflate dep-nodes, it just
-        // leads to more recompilation.
-        let def_ids: Vec<_> =
+        // Extact the trait-def and first def-id from inputs.  See the
+        // docs for `DepNode::TraitSelect` for more information.
+        let trait_def_id = self.def_id();
+        let input_def_id =
             self.input_types()
                 .flat_map(|t| t.walk())
                 .filter_map(|t| match t.sty {
-                    ty::TyAdt(adt_def, _) =>
-                        Some(adt_def.did),
-                    _ =>
-                        None
+                    ty::TyAdt(adt_def, _) => Some(adt_def.did),
+                    _ => None
                 })
-                .chain(iter::once(self.def_id()))
-                .collect();
-        DepNode::TraitSelect(def_ids)
+                .next()
+                .unwrap_or(trait_def_id);
+        DepNode::TraitSelect {
+            trait_def_id: trait_def_id,
+            input_def_id: input_def_id
+        }
     }
 
     pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index adedf78bba7..2e3009b4ed6 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -143,7 +143,7 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
 {
     let tcx = relation.tcx();
 
-    let params = a_subst.params().iter().zip(b_subst.params()).enumerate().map(|(i, (a, b))| {
+    let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances.map_or(ty::Invariant, |v| v[i]);
         if let (Some(a_ty), Some(b_ty)) = (a.as_type(), b.as_type()) {
             Ok(Kind::from(relation.relate_with_variance(variance, &a_ty, &b_ty)?))
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index d6f61a12a3c..c0a529b936b 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -255,12 +255,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
     }
 
     #[inline]
-    pub fn params(&self) -> &[Kind<'tcx>] {
-        // FIXME (dikaiosune) this should be removed, and corresponding compilation errors fixed
-        self
-    }
-
-    #[inline]
     pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
         self.iter().filter_map(|k| k.as_type())
     }
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
index 1fa4da94dd6..7888a56d39d 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
@@ -473,6 +473,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
             }
             mir::StatementKind::StorageLive(_) |
             mir::StatementKind::StorageDead(_) |
+            mir::StatementKind::InlineAsm { .. } |
             mir::StatementKind::Nop => {}
         }
     }
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
index ea6ef423c92..940dd5433a0 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
@@ -104,6 +104,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
             mir::StatementKind::StorageLive(_) |
             mir::StatementKind::StorageDead(_) |
+            mir::StatementKind::InlineAsm { .. } |
             mir::StatementKind::Nop => continue,
             mir::StatementKind::SetDiscriminant{ .. } =>
                 span_bug!(stmt.source_info.span,
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
index 0c7e922c48a..35ace6628cf 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
@@ -412,6 +412,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
                 span_bug!(stmt.source_info.span,
                           "SetDiscriminant should not exist during borrowck");
             }
+            StatementKind::InlineAsm { .. } |
             StatementKind::Nop => {}
         }
     }
@@ -436,8 +437,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
             }
             Rvalue::Ref(..) |
             Rvalue::Discriminant(..) |
-            Rvalue::Len(..) |
-            Rvalue::InlineAsm { .. } => {}
+            Rvalue::Len(..) => {}
             Rvalue::Box(..) => {
                 // This returns an rvalue with uninitialized contents. We can't
                 // move out of it here because it is an rvalue - assignments always
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs
index a0c36139ddc..d9283e7037f 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/mod.rs
@@ -378,6 +378,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
             }
             mir::StatementKind::StorageLive(_) |
             mir::StatementKind::StorageDead(_) |
+            mir::StatementKind::InlineAsm { .. } |
             mir::StatementKind::Nop => {}
         },
         None => {
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index dad1d713168..7adcc0e730b 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -49,21 +49,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Scope { extent, value } => {
                 this.in_scope(extent, block, |this| this.as_rvalue(block, value))
             }
-            ExprKind::InlineAsm { asm, outputs, inputs } => {
-                let outputs = outputs.into_iter().map(|output| {
-                    unpack!(block = this.as_lvalue(block, output))
-                }).collect();
-
-                let inputs = inputs.into_iter().map(|input| {
-                    unpack!(block = this.as_operand(block, input))
-                }).collect();
-
-                block.and(Rvalue::InlineAsm {
-                    asm: asm.clone(),
-                    outputs: outputs,
-                    inputs: inputs
-                })
-            }
             ExprKind::Repeat { value, count } => {
                 let value_operand = unpack!(block = this.as_operand(block, value));
                 block.and(Rvalue::Repeat(value_operand, count))
@@ -238,6 +223,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Break { .. } |
             ExprKind::Continue { .. } |
             ExprKind::Return { .. } |
+            ExprKind::InlineAsm { .. } |
             ExprKind::StaticRef { .. } => {
                 // these do not have corresponding `Rvalue` variants,
                 // so make an operand and then return that
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 35841c2cbdf..e66f2b4e2bf 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -232,6 +232,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::AssignOp { .. } |
             ExprKind::Continue { .. } |
             ExprKind::Break { .. } |
+            ExprKind::InlineAsm { .. } |
             ExprKind::Return {.. } => {
                 this.stmt_expr(block, expr)
             }
@@ -257,7 +258,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::Index { .. } |
             ExprKind::Deref { .. } |
             ExprKind::Literal { .. } |
-            ExprKind::InlineAsm { .. } |
             ExprKind::Field { .. } => {
                 debug_assert!(match Category::of(&expr.kind).unwrap() {
                     Category::Rvalue(RvalueFunc::Into) => false,
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index f04d630379a..c577aab40db 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -117,6 +117,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 this.exit_scope(expr_span, extent, block, return_block);
                 this.cfg.start_new_block().unit()
             }
+            ExprKind::InlineAsm { asm, outputs, inputs } => {
+                let outputs = outputs.into_iter().map(|output| {
+                    unpack!(block = this.as_lvalue(block, output))
+                }).collect();
+                let inputs = inputs.into_iter().map(|input| {
+                    unpack!(block = this.as_operand(block, input))
+                }).collect();
+                this.cfg.push(block, Statement {
+                    source_info: source_info,
+                    kind: StatementKind::InlineAsm {
+                        asm: asm.clone(),
+                        outputs: outputs,
+                        inputs: inputs
+                    },
+                });
+                block.unit()
+            }
             _ => {
                 let expr_ty = expr.ty;
                 let temp = this.temp(expr.ty.clone());
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 922521726c6..4459142cfb2 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -774,10 +774,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     }
                 }
             }
-
-            Rvalue::InlineAsm {..} => {
-                self.not_const();
-            }
         }
     }
 
@@ -933,6 +929,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 StatementKind::SetDiscriminant { .. } |
                 StatementKind::StorageLive(_) |
                 StatementKind::StorageDead(_) |
+                StatementKind::InlineAsm {..} |
                 StatementKind::Nop => {}
             }
         });
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 8ede7aaab5f..8d108815e0f 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -361,9 +361,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}",
                                      lv_ty, rv_ty, terr);
                     }
-                // FIXME: rvalue with undeterminable type - e.g. inline
-                // asm.
                 }
+                // FIXME: rvalue with undeterminable type - e.g. AggregateKind::Array branch that
+                // returns `None`.
             }
             StatementKind::SetDiscriminant{ ref lvalue, variant_index } => {
                 let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx);
@@ -392,6 +392,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     }
                 }
             }
+            StatementKind::InlineAsm { .. } |
             StatementKind::Nop => {}
         }
     }
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index 517a4720563..33b7089c382 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -128,6 +128,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
             StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
             StatementKind::StorageLive(..) => "StatementKind::StorageLive",
             StatementKind::StorageDead(..) => "StatementKind::StorageDead",
+            StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
             StatementKind::Nop => "StatementKind::Nop",
         }, &statement.kind);
         self.super_statement(block, statement, location);
@@ -198,7 +199,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
 
                 "Rvalue::Aggregate"
             }
-            Rvalue::InlineAsm { .. } => "Rvalue::InlineAsm",
         };
         self.record(rvalue_kind, rvalue);
         self.super_rvalue(rvalue, location);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index fa3c12624c6..c9e870188aa 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1195,7 +1195,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
         let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
         match self.resolve_path(&path, Some(namespace), Some(span)) {
             PathResult::Module(module) => *def = module.def().unwrap(),
-            PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def,
+            PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
+                *def = path_res.base_def(),
             PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
                 PathResult::Failed(msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@@ -1718,7 +1719,7 @@ impl<'a> Resolver<'a> {
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
             let def = self.smart_resolve_path(trait_ref.ref_id, None,
-                                              &trait_ref.path, PathSource::Trait).base_def;
+                                              &trait_ref.path, PathSource::Trait).base_def();
             if def != Def::Err {
                 new_val = Some((def.def_id(), trait_ref.clone()));
                 new_id = Some(def.def_id());
@@ -1849,8 +1850,8 @@ impl<'a> Resolver<'a> {
 
         pat.walk(&mut |pat| {
             if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
-                if sub_pat.is_some() || match self.def_map.get(&pat.id) {
-                    Some(&PathResolution { base_def: Def::Local(..), .. }) => true,
+                if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) {
+                    Some(Def::Local(..)) => true,
                     _ => false,
                 } {
                     let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
@@ -2248,14 +2249,14 @@ impl<'a> Resolver<'a> {
         let resolution = match self.resolve_qpath_anywhere(id, qself, path, ns, span,
                                                            source.defer_to_typeck(),
                                                            source.global_by_default()) {
-            Some(resolution) if resolution.depth == 0 => {
-                if is_expected(resolution.base_def) || resolution.base_def == Def::Err {
+            Some(resolution) if resolution.unresolved_segments() == 0 => {
+                if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err {
                     resolution
                 } else {
                     // Add a temporary hack to smooth the transition to new struct ctor
                     // visibility rules. See #38932 for more details.
                     let mut res = None;
-                    if let Def::Struct(def_id) = resolution.base_def {
+                    if let Def::Struct(def_id) = resolution.base_def() {
                         if let Some((ctor_def, ctor_vis))
                                 = self.struct_constructors.get(&def_id).cloned() {
                             if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
@@ -2268,7 +2269,7 @@ impl<'a> Resolver<'a> {
                         }
                     }
 
-                    res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def)))
+                    res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def())))
                 }
             }
             Some(resolution) if source.defer_to_typeck() => {
@@ -2321,7 +2322,8 @@ impl<'a> Resolver<'a> {
                 match self.resolve_qpath(id, qself, path, ns, span, global_by_default) {
                     // If defer_to_typeck, then resolution > no resolution,
                     // otherwise full resolution > partial resolution > no resolution.
-                    Some(res) if res.depth == 0 || defer_to_typeck => return Some(res),
+                    Some(res) if res.unresolved_segments() == 0 || defer_to_typeck =>
+                        return Some(res),
                     res => if fin_res.is_none() { fin_res = res },
                 };
             }
@@ -2346,19 +2348,17 @@ impl<'a> Resolver<'a> {
         if let Some(qself) = qself {
             if qself.position == 0 {
                 // FIXME: Create some fake resolution that can't possibly be a type.
-                return Some(PathResolution {
-                    base_def: Def::Mod(DefId::local(CRATE_DEF_INDEX)),
-                    depth: path.len(),
-                });
+                return Some(PathResolution::with_unresolved_segments(
+                    Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len()
+                ));
             }
             // Make sure `A::B` in `<T as A>::B::C` is a trait item.
             let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
-            let mut res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
-                                                           span, PathSource::TraitItem(ns));
-            if res.base_def != Def::Err {
-                res.depth += path.len() - qself.position - 1;
-            }
-            return Some(res);
+            let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
+                                                       span, PathSource::TraitItem(ns));
+            return Some(PathResolution::with_unresolved_segments(
+                res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
+            ));
         }
 
         let result = match self.resolve_path(&path, Some(ns), Some(span)) {
@@ -2393,10 +2393,7 @@ impl<'a> Resolver<'a> {
                     }
                     _ => {}
                 }
-                PathResolution {
-                    base_def: Def::PrimTy(prim),
-                    depth: path.len() - 1,
-                }
+                PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
             }
             PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
             PathResult::Failed(msg, false) => {
@@ -2407,16 +2404,16 @@ impl<'a> Resolver<'a> {
             PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
         };
 
-        if path.len() > 1 && !global_by_default && result.base_def != Def::Err &&
+        if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
            path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
             let unqualified_result = {
                 match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
-                    PathResult::NonModule(path_res) => path_res.base_def,
+                    PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
                 }
             };
-            if result.base_def == unqualified_result {
+            if result.base_def() == unqualified_result {
                 let lint = lint::builtin::UNUSED_QUALIFICATIONS;
                 self.session.add_lint(lint, id, span, "unnecessary qualification".to_string());
             }
@@ -2470,10 +2467,9 @@ impl<'a> Resolver<'a> {
                     Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
                     Some(LexicalScopeBinding::Def(def))
                             if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
-                        return PathResult::NonModule(PathResolution {
-                            base_def: def,
-                            depth: path.len() - 1,
-                        });
+                        return PathResult::NonModule(PathResolution::with_unresolved_segments(
+                            def, path.len() - 1
+                        ));
                     }
                     _ => Err(if record_used.is_some() { Determined } else { Undetermined }),
                 }
@@ -2488,10 +2484,9 @@ impl<'a> Resolver<'a> {
                     } else if def == Def::Err {
                         return PathResult::NonModule(err_path_resolution());
                     } else if opt_ns.is_some() && (is_last || maybe_assoc) {
-                        return PathResult::NonModule(PathResolution {
-                            base_def: def,
-                            depth: path.len() - i - 1,
-                        });
+                        return PathResult::NonModule(PathResolution::with_unresolved_segments(
+                            def, path.len() - i - 1
+                        ));
                     } else {
                         return PathResult::Failed(format!("Not a module `{}`", ident), is_last);
                     }
@@ -2500,10 +2495,9 @@ impl<'a> Resolver<'a> {
                 Err(Determined) => {
                     if let Some(module) = module {
                         if opt_ns.is_some() && !module.is_normal() {
-                            return PathResult::NonModule(PathResolution {
-                                base_def: module.def().unwrap(),
-                                depth: path.len() - i,
-                            });
+                            return PathResult::NonModule(PathResolution::with_unresolved_segments(
+                                module.def().unwrap(), path.len() - i
+                            ));
                         }
                     }
                     let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
@@ -2672,8 +2666,9 @@ impl<'a> Resolver<'a> {
             if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
                 // Look for a field with the same name in the current self_type.
                 if let Some(resolution) = self.def_map.get(&node_id) {
-                    match resolution.base_def {
-                        Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
+                    match resolution.base_def() {
+                        Def::Struct(did) | Def::Union(did)
+                                if resolution.unresolved_segments() == 0 => {
                             if let Some(field_names) = self.field_names.get(&did) {
                                 if field_names.iter().any(|&field_name| name == field_name) {
                                     return Some(AssocSuggestion::Field);
@@ -3057,7 +3052,6 @@ impl<'a> Resolver<'a> {
 
     fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
-        assert!(resolution.depth == 0 || resolution.base_def != Def::Err);
         if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
             panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
         }
@@ -3071,7 +3065,8 @@ impl<'a> Resolver<'a> {
                 ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
             }
             ast::Visibility::Restricted { ref path, id } => {
-                let def = self.smart_resolve_path(id, None, path, PathSource::Visibility).base_def;
+                let def = self.smart_resolve_path(id, None, path,
+                                                  PathSource::Visibility).base_def();
                 if def == Def::Err {
                     ty::Visibility::Public
                 } else {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 880f5f388d0..8d563d20549 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -262,7 +262,7 @@ impl<'a> base::Resolver for Resolver<'a> {
             }
 
             let ext = match self.resolve_path(&path, Some(MacroNS), None) {
-                PathResult::NonModule(path_res) => match path_res.base_def {
+                PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => Ok(self.get_macro(def)),
                 },
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 89f5c00e9c1..b5f948442b7 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -1090,13 +1090,16 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
                                                    trait_ty: ty::Ty<'tcx>,
                                                    impl_ty: ty::Ty<'tcx>,
                                                    output: &mut Vec<TransItem<'tcx>>) {
-    assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
+    assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
+            !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
 
     if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
         if let Some(principal) = trait_ty.principal() {
             let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty);
             let param_substs = scx.tcx().intern_substs(&[]);
 
+            assert!(!poly_trait_ref.has_escaping_regions());
+
             // Walk all methods of the trait, including those of its supertraits
             let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
             let methods = methods.filter_map(|method| method)
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 5efdd129a32..799f502aadb 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -208,7 +208,8 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
                    _ => None,
                })
                .collect();
-        DepNode::TraitSelect(def_ids)
+
+        DepNode::ProjectionCache { def_ids: def_ids }
     }
 }
 
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 19139301bb0..7e17ae5f1d3 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -287,8 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                     mir::StatementKind::StorageLive(_) |
                     mir::StatementKind::StorageDead(_) |
                     mir::StatementKind::Nop => {}
+                    mir::StatementKind::InlineAsm { .. } |
                     mir::StatementKind::SetDiscriminant{ .. } => {
-                        span_bug!(span, "SetDiscriminant should not appear in constants?");
+                        span_bug!(span, "{:?} should not appear in constants?", statement.kind);
                     }
                 }
             }
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 38ee67796c6..7d4f542addb 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -16,7 +16,6 @@ use rustc::mir::tcx::LvalueTy;
 use rustc::mir;
 use middle::lang_items::ExchangeMallocFnLangItem;
 
-use asm;
 use base;
 use builder::Builder;
 use callee::Callee;
@@ -156,20 +155,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 bcx
             }
 
-            mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => {
-                let outputs = outputs.iter().map(|output| {
-                    let lvalue = self.trans_lvalue(&bcx, output);
-                    (lvalue.llval, lvalue.ty.to_ty(bcx.tcx()))
-                }).collect();
-
-                let input_vals = inputs.iter().map(|input| {
-                    self.trans_operand(&bcx, input).immediate()
-                }).collect();
-
-                asm::trans_inline_asm(&bcx, asm, outputs, input_vals);
-                bcx
-            }
-
             _ => {
                 assert!(rvalue_creates_operand(rvalue));
                 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
@@ -468,8 +453,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 (bcx, operand)
             }
             mir::Rvalue::Repeat(..) |
-            mir::Rvalue::Aggregate(..) |
-            mir::Rvalue::InlineAsm { .. } => {
+            mir::Rvalue::Aggregate(..) => {
                 bug!("cannot generate operand from rvalue {:?}", rvalue);
 
             }
@@ -669,8 +653,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool {
         mir::Rvalue::Use(..) =>
             true,
         mir::Rvalue::Repeat(..) |
-        mir::Rvalue::Aggregate(..) |
-        mir::Rvalue::InlineAsm { .. } =>
+        mir::Rvalue::Aggregate(..) =>
             false,
     }
 
diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs
index 48fc9720e4b..29a0648c8f8 100644
--- a/src/librustc_trans/mir/statement.rs
+++ b/src/librustc_trans/mir/statement.rs
@@ -11,6 +11,7 @@
 use rustc::mir;
 
 use base;
+use asm;
 use common;
 use builder::Builder;
 
@@ -73,6 +74,19 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
             mir::StatementKind::StorageDead(ref lvalue) => {
                 self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End)
             }
+            mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
+                let outputs = outputs.iter().map(|output| {
+                    let lvalue = self.trans_lvalue(&bcx, output);
+                    (lvalue.llval, lvalue.ty.to_ty(bcx.tcx()))
+                }).collect();
+
+                let input_vals = inputs.iter().map(|input| {
+                    self.trans_operand(&bcx, input).immediate()
+                }).collect();
+
+                asm::trans_inline_asm(&bcx, asm, outputs, input_vals);
+                bcx
+            }
             mir::StatementKind::Nop => bcx,
         }
     }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index fb6d28448a0..ab1897101eb 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -918,7 +918,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             (_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
                 // `Self` in an impl of a trait - we have a concrete self type and a
                 // trait reference.
-                let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+                // FIXME: Self type is not always computed when we are here because type parameter
+                // bounds may affect Self type and have to be converted before it.
+                let trait_ref = if impl_def_id.is_local() {
+                    tcx.impl_trait_refs.borrow().get(&impl_def_id).cloned().and_then(|x| x)
+                } else {
+                    tcx.impl_trait_ref(impl_def_id)
+                };
+                let trait_ref = if let Some(trait_ref) = trait_ref {
+                    trait_ref
+                } else {
+                    tcx.sess.span_err(span, "`Self` type is used before it's determined");
+                    return (tcx.types.err, Def::Err);
+                };
                 let trait_ref = if let Some(free_substs) = self.get_free_substs() {
                     trait_ref.subst(tcx, free_substs)
                 } else {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index ff9eaa012ba..2d90394025d 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -309,17 +309,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         // parameters from the type and those from the method.
         //
         // FIXME -- permit users to manually specify lifetimes
-        let supplied_start = substs.params().len() + method_generics.regions.len();
+        let supplied_start = substs.len() + method_generics.regions.len();
         Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
             let i = def.index as usize;
-            if i < substs.params().len() {
+            if i < substs.len() {
                 substs.region_at(i)
             } else {
                 self.region_var_for_def(self.span, def)
             }
         }, |def, cur_substs| {
             let i = def.index as usize;
-            if i < substs.params().len() {
+            if i < substs.len() {
                 substs.type_at(i)
             } else if supplied_method_types.is_empty() {
                 self.type_var_for_def(self.span, def, cur_substs)
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 201a223c15f..fd29ff0be43 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1326,7 +1326,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         } else {
             let substs = Substs::for_item(self.tcx, method, |def, _| {
                 let i = def.index as usize;
-                if i < substs.params().len() {
+                if i < substs.len() {
                     substs.region_at(i)
                 } else {
                     // In general, during probe we erase regions. See
@@ -1335,7 +1335,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 }
             }, |def, cur_substs| {
                 let i = def.index as usize;
-                if i < substs.params().len() {
+                if i < substs.len() {
                     substs.type_at(i)
                 } else {
                     self.type_var_for_def(self.span, def, cur_substs)
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 28156dd616b..a2922270583 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
         let gcx = fcx.tcx.global_tcx();
         let free_substs = fcx.parameter_environment.free_substs;
-        for (i, k) in free_substs.params().iter().enumerate() {
+        for (i, k) in free_substs.iter().enumerate() {
             let r = if let Some(r) = k.as_region() {
                 r
             } else {
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 1ef2cb4ed15..dd4f1ff4f5e 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -96,7 +96,9 @@ pub struct VarsOs { inner: os_imp::Env }
 ///
 /// While iterating, the returned iterator will panic if any key or value in the
 /// environment is not valid unicode. If this is not desired, consider using the
-/// `env::vars_os` function.
+/// [`env::vars_os`] function.
+///
+/// [`env::vars_os`]: fn.vars_os.html
 ///
 /// # Examples
 ///
@@ -171,9 +173,12 @@ impl fmt::Debug for VarsOs {
 
 /// Fetches the environment variable `key` from the current process.
 ///
-/// The returned result is `Ok(s)` if the environment variable is present and is
+/// The returned result is [`Ok(s)`] if the environment variable is present and is
 /// valid unicode. If the environment variable is not present, or it is not
-/// valid unicode, then `Err` will be returned.
+/// valid unicode, then [`Err`] will be returned.
+///
+/// [`Ok(s)`]: ../result/enum.Result.html#variant.Ok
+/// [`Err`]: ../result/enum.Result.html#variant.Err
 ///
 /// # Examples
 ///
@@ -199,7 +204,9 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 }
 
 /// Fetches the environment variable `key` from the current process, returning
-/// `None` if the variable isn't set.
+/// [`None`] if the variable isn't set.
+///
+/// [`None`]: ../option/enum.Option.html#variant.None
 ///
 /// # Examples
 ///
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index ba993751391..1e7394c0b09 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -316,7 +316,7 @@ impl Once {
                         }
 
                         // Once we've enqueued ourselves, wait in a loop.
-                        // Aftewards reload the state and continue with what we
+                        // Afterwards reload the state and continue with what we
                         // were doing from before.
                         while !node.signaled.load(Ordering::SeqCst) {
                             thread::park();
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 6992a17832e..e78928c2667 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -483,41 +483,21 @@ pub fn home_dir() -> Option<PathBuf> {
                   target_os = "nacl",
                   target_os = "emscripten")))]
     unsafe fn fallback() -> Option<OsString> {
-        #[cfg(not(target_os = "solaris"))]
-        unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd,
-                              buf: &mut Vec<c_char>) -> Option<()> {
-            let mut result = ptr::null_mut();
-            match libc::getpwuid_r(me, passwd, buf.as_mut_ptr(),
-                                   buf.capacity(),
-                                   &mut result) {
-                0 if !result.is_null() => Some(()),
-                _ => None
-            }
-        }
-
-        #[cfg(target_os = "solaris")]
-        unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd,
-                              buf: &mut Vec<c_char>) -> Option<()> {
-            // getpwuid_r semantics is different on Illumos/Solaris:
-            // http://illumos.org/man/3c/getpwuid_r
-            let result = libc::getpwuid_r(me, passwd, buf.as_mut_ptr(),
-                                          buf.capacity());
-            if result.is_null() { None } else { Some(()) }
-        }
-
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
             n if n < 0 => 512 as usize,
             n => n as usize,
         };
         let mut buf = Vec::with_capacity(amt);
         let mut passwd: libc::passwd = mem::zeroed();
-
-        if getpwduid_r(libc::getuid(), &mut passwd, &mut buf).is_some() {
-            let ptr = passwd.pw_dir as *const _;
-            let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
-            Some(OsStringExt::from_vec(bytes))
-        } else {
-            None
+        let mut result = ptr::null_mut();
+        match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(),
+                               buf.capacity(), &mut result) {
+            0 if !result.is_null() => {
+                let ptr = passwd.pw_dir as *const _;
+                let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
+                Some(OsStringExt::from_vec(bytes))
+            },
+            _ => None,
         }
     }
 }
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index 5166ddf8a21..66f09a7069c 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -28,8 +28,8 @@ use mem;
 /// # Initialization and Destruction
 ///
 /// Initialization is dynamically performed on the first call to `with()`
-/// within a thread, and values support destructors which will be run when a
-/// thread exits.
+/// within a thread, and values that implement `Drop` get destructed when a
+/// thread exits. Some caveats apply, which are explained below.
 ///
 /// # Examples
 ///
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index b74f4913858..ab36e9a2c2b 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.
-2016-12-19
+2017-02-15
diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs
new file mode 100644
index 00000000000..a56a5e85489
--- /dev/null
+++ b/src/test/compile-fail/issue-39559.rs
@@ -0,0 +1,31 @@
+// Copyright 2017 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 Dim {
+    fn dim() -> usize;
+}
+
+enum Dim3 {}
+
+impl Dim for Dim3 {
+    fn dim() -> usize {
+        3
+    }
+}
+
+pub struct Vector<T, D: Dim> {
+    entries: [T; D::dim()]
+    //~^ ERROR cannot use an outer type parameter in this context
+    //~| ERROR constant evaluation error
+}
+
+fn main() {
+    let array: [usize; Dim3::dim()] = [0; Dim3::dim()];
+}
diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs
index 82037b6c9ed..04f98c7ab32 100644
--- a/src/test/compile-fail/resolve-self-in-impl.rs
+++ b/src/test/compile-fail/resolve-self-in-impl.rs
@@ -18,9 +18,12 @@ impl<T: Tr<Self>> Tr<T> for S {} //~ ERROR `Self` type is used before it's deter
 impl<T = Self> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
 impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined
 impl Tr for S where S<Self>: Copy {} //~ ERROR `Self` type is used before it's determined
+impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined
+                                         //~^ ERROR `Self` type is used before it's determined
 impl Tr for Self {} //~ ERROR `Self` type is used before it's determined
 impl Tr for S<Self> {} //~ ERROR `Self` type is used before it's determined
 impl Self {} //~ ERROR `Self` type is used before it's determined
 impl S<Self> {} //~ ERROR `Self` type is used before it's determined
+impl Tr<Self::Assoc> for S {} //~ ERROR `Self` type is used before it's determined
 
 fn main() {}
diff --git a/src/test/run-pass/issue-39292.rs b/src/test/run-pass/issue-39292.rs
new file mode 100644
index 00000000000..dc2b21f3470
--- /dev/null
+++ b/src/test/run-pass/issue-39292.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// Regression test for issue #39292. The object vtable was being
+// incorrectly left with a null pointer.
+
+trait Foo<T> {
+    fn print<'a>(&'a self) where T: 'a { println!("foo"); }
+}
+
+impl<'a> Foo<&'a ()> for () { }
+
+trait Bar: for<'a> Foo<&'a ()> { }
+
+impl Bar for () {}
+
+fn main() {
+    (&() as &Bar).print(); // Segfault
+}