diff --git a/mk/tests.mk b/mk/tests.mk
index 87cfed2426e..2e7b85f5728 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -242,13 +242,13 @@ cleantestlibs:
 
 .PHONY: tidy
 tidy: $(HBIN0_H_$(CFG_BUILD))/tidy$(X_$(CFG_BUILD))
-	$< $(S)src
+	$(TARGET_RPATH_VAR0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $< $(S)src
 
 $(HBIN0_H_$(CFG_BUILD))/tidy$(X_$(CFG_BUILD)): \
 		$(TSREQ0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
 		$(TLIB0_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.std \
 		$(call rwildcard,$(S)src/tools/tidy/src,*.rs)
-	$(STAGE0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) src/tools/tidy/src/main.rs \
+	$(STAGE0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(S)src/tools/tidy/src/main.rs \
 		--out-dir $(@D) --crate-name tidy
 
 ######################################################################
diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs
index 626cf758631..45e0cb11010 100644
--- a/src/bootstrap/build/step.rs
+++ b/src/bootstrap/build/step.rs
@@ -323,8 +323,7 @@ impl<'a> Step<'a> {
             }
 
             Source::ToolLinkchecker { stage } |
-            Source::ToolTidy { stage } |
-            Source::ToolCargoTest { stage } => {
+            Source::ToolTidy { stage } => {
                 vec![self.libstd(self.compiler(stage))]
             }
             Source::ToolErrorIndex { stage } |
diff --git a/src/rustc/test_shim/lib.rs b/src/rustc/test_shim/lib.rs
index a626c9440d8..d614d967e3b 100644
--- a/src/rustc/test_shim/lib.rs
+++ b/src/rustc/test_shim/lib.rs
@@ -9,3 +9,7 @@
 // except according to those terms.
 
 // See comments in Cargo.toml for why this exists
+
+#![feature(test)]
+
+extern crate test;
diff --git a/src/tools/tidy/src/cargo.rs b/src/tools/tidy/src/cargo.rs
new file mode 100644
index 00000000000..a170ecfdce0
--- /dev/null
+++ b/src/tools/tidy/src/cargo.rs
@@ -0,0 +1,95 @@
+// 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.
+
+//! Tidy check to ensure that `[dependencies]` and `extern crate` are in sync.
+//!
+//! This tidy check ensures that all crates listed in the `[dependencies]`
+//! section of a `Cargo.toml` are present in the corresponding `lib.rs` as
+//! `extern crate` declarations. This should help us keep the DAG correctly
+//! structured through various refactorings to prune out unnecessary edges.
+
+use std::io::prelude::*;
+use std::fs::File;
+use std::path::Path;
+
+pub fn check(path: &Path, bad: &mut bool) {
+    for entry in t!(path.read_dir()).map(|e| t!(e)) {
+        // Look for `Cargo.toml` with a sibling `src/lib.rs` or `lib.rs`
+        if entry.file_name().to_str() == Some("Cargo.toml") {
+            if path.join("src/lib.rs").is_file() {
+                verify(&entry.path(), &path.join("src/lib.rs"), bad)
+            }
+            if path.join("lib.rs").is_file() {
+                verify(&entry.path(), &path.join("lib.rs"), bad)
+            }
+        } else if t!(entry.file_type()).is_dir() {
+            check(&entry.path(), bad);
+        }
+    }
+}
+
+// Verify that the dependencies in Cargo.toml at `tomlfile` are sync'd with the
+// `extern crate` annotations in the lib.rs at `libfile`.
+fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) {
+    let mut toml = String::new();
+    let mut librs = String::new();
+    t!(t!(File::open(tomlfile)).read_to_string(&mut toml));
+    t!(t!(File::open(libfile)).read_to_string(&mut librs));
+
+    if toml.contains("name = \"bootstrap\"") {
+        return
+    }
+
+    // "Poor man's TOML parser", just assume we use one syntax for now
+    //
+    // We just look for:
+    //
+    //      [dependencies]
+    //      name = ...
+    //      name2 = ...
+    //      name3 = ...
+    //
+    // If we encounter a line starting with `[` then we assume it's the end of
+    // the dependency section and bail out.
+    let deps = match toml.find("[dependencies]") {
+        Some(i) => &toml[i+1..],
+        None => return,
+    };
+    let mut lines = deps.lines().peekable();
+    while let Some(line) = lines.next() {
+        if line.starts_with("[") {
+            break
+        }
+
+        let mut parts = line.splitn(2, '=');
+        let krate = parts.next().unwrap().trim();
+        if parts.next().is_none() {
+            continue
+        }
+
+        // Don't worry about depending on core/std but not saying `extern crate
+        // core/std`, that's intentional.
+        if krate == "core" || krate == "std" {
+            continue
+        }
+
+        // This is intentional, this dependency just makes the crate available
+        // for others later on.
+        if krate == "alloc_jemalloc" && toml.contains("name = \"std\"") {
+            continue
+        }
+
+        if !librs.contains(&format!("extern crate {}", krate)) {
+            println!("{} doesn't have `extern crate {}`, but Cargo.toml \
+                      depends on it", libfile.display(), krate);
+            *bad = true;
+        }
+    }
+}
diff --git a/src/tools/tidy/src/errors.rs b/src/tools/tidy/src/errors.rs
index 21ec9270429..41869288cc9 100644
--- a/src/tools/tidy/src/errors.rs
+++ b/src/tools/tidy/src/errors.rs
@@ -71,8 +71,7 @@ pub fn check(path: &Path, bad: &mut bool) {
     });
 
     let mut max = 0;
-    println!("* {} error codes", map.len());
-    for (code, entries) in map {
+    for (&code, entries) in map.iter() {
         if code > max {
             max = code;
         }
@@ -81,10 +80,14 @@ pub fn check(path: &Path, bad: &mut bool) {
         }
 
         println!("duplicate error code: {}", code);
-        for (file, line_num, line) in entries {
+        for &(ref file, line_num, ref line) in entries.iter() {
             println!("{}:{}: {}", file.display(), line_num, line);
         }
         *bad = true;
     }
-    println!("* highest error code: E{:04}", max);
+
+    if !*bad {
+        println!("* {} error codes", map.len());
+        println!("* highest error code: E{:04}", max);
+    }
 }
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index c665b6e662f..991cf201d44 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -100,6 +100,10 @@ pub fn check(path: &Path, bad: &mut bool) {
         }
     });
 
+    if *bad {
+        return
+    }
+
     let mut lines = Vec::new();
     for feature in features {
         lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index d8acf3250df..85b9c345e19 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -29,6 +29,7 @@ mod bins;
 mod style;
 mod errors;
 mod features;
+mod cargo;
 
 fn main() {
     let path = env::args_os().skip(1).next().expect("need an argument");
@@ -38,6 +39,7 @@ fn main() {
     bins::check(&path, &mut bad);
     style::check(&path, &mut bad);
     errors::check(&path, &mut bad);
+    cargo::check(&path, &mut bad);
     features::check(&path, &mut bad);
 
     if bad {