about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-08-10 14:05:58 -0700
committerAlex Crichton <alex@alexcrichton.com>2017-08-10 14:05:58 -0700
commitb8aa595e6d159bfb5e0293659b69e0edc457a468 (patch)
tree01c3c1ef7415103c4d48a28cf57be47cba5cc624 /src
parentbe95ca4b17203a3aed27c17c1e93b76c9477e5bc (diff)
parentb6179602bea71607a9ea63197eca423fcce5f7b0 (diff)
downloadrust-b8aa595e6d159bfb5e0293659b69e0edc457a468.tar.gz
rust-b8aa595e6d159bfb5e0293659b69e0edc457a468.zip
Merge remote-tracking branch 'origin/master' into gen
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock72
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/etc/platform-intrinsics/generator.py10
-rw-r--r--src/etc/platform-intrinsics/powerpc.json49
-rw-r--r--src/liballoc/btree/node.rs4
-rw-r--r--src/liballoc/vec.rs2
-rw-r--r--src/liballoc/vec_deque.rs6
-rw-r--r--src/libcore/cmp.rs7
-rw-r--r--src/libcore/iter/range.rs13
-rw-r--r--src/libcore/macros.rs14
-rw-r--r--src/libcore/ops/function.rs2
-rw-r--r--src/libcore/option.rs2
-rw-r--r--src/libcore/result.rs2
-rw-r--r--src/libcore/tests/slice.rs12
-rw-r--r--src/librustc/dep_graph/dep_node.rs1
-rw-r--r--src/librustc/ich/impls_ty.rs2
-rw-r--r--src/librustc/infer/error_reporting/mod.rs4
-rw-r--r--src/librustc/lint/context.rs771
-rw-r--r--src/librustc/lint/levels.rs343
-rw-r--r--src/librustc/lint/mod.rs236
-rw-r--r--src/librustc/lint/table.rs71
-rw-r--r--src/librustc/middle/dead.rs52
-rw-r--r--src/librustc/middle/effect.rs10
-rw-r--r--src/librustc/middle/liveness.rs18
-rw-r--r--src/librustc/middle/stability.rs14
-rw-r--r--src/librustc/session/mod.rs29
-rw-r--r--src/librustc/traits/error_reporting.rs36
-rw-r--r--src/librustc/traits/mod.rs2
-rw-r--r--src/librustc/traits/select.rs18
-rw-r--r--src/librustc/traits/specialize/mod.rs3
-rw-r--r--src/librustc/ty/context.rs61
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs4
-rw-r--r--src/librustc/ty/maps.rs28
-rw-r--r--src/librustc/ty/mod.rs3
-rw-r--r--src/librustc/ty/trait_def.rs168
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc_allocator/expand.rs4
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs44
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs2
-rw-r--r--src/librustc_const_eval/check_match.rs26
-rw-r--r--src/librustc_data_structures/array_vec.rs2
-rw-r--r--src/librustc_data_structures/bitvec.rs2
-rw-r--r--src/librustc_data_structures/indexed_vec.rs2
-rw-r--r--src/librustc_driver/driver.rs45
-rw-r--r--src/librustc_driver/lib.rs38
-rw-r--r--src/librustc_driver/test.rs4
-rw-r--r--src/librustc_lint/builtin.rs18
-rw-r--r--src/librustc_lint/unused.rs34
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs3
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_passes/ast_validation.rs11
-rw-r--r--src/librustc_passes/consts.rs20
-rw-r--r--src/librustc_passes/diagnostics.rs35
-rw-r--r--src/librustc_platform_intrinsics/powerpc.rs140
-rw-r--r--src/librustc_privacy/lib.rs24
-rw-r--r--src/librustc_resolve/check_unused.rs13
-rw-r--r--src/librustc_resolve/lib.rs13
-rw-r--r--src/librustc_resolve/macros.rs4
-rw-r--r--src/librustc_resolve/resolve_imports.rs8
-rw-r--r--src/librustc_trans/base.rs2
-rw-r--r--src/librustc_trans/partitioning.rs2
-rw-r--r--src/librustc_trans/time_graph.rs4
-rw-r--r--src/librustc_typeck/astconv.rs6
-rw-r--r--src/librustc_typeck/check/cast.rs24
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/method/mod.rs5
-rw-r--r--src/librustc_typeck/check/method/probe.rs10
-rw-r--r--src/librustc_typeck/check/method/suggest.rs32
-rw-r--r--src/librustc_typeck/check/mod.rs75
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/check/writeback.rs5
-rw-r--r--src/librustc_typeck/check_unused.rs2
-rw-r--r--src/librustc_typeck/collect.rs6
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/html/markdown.rs16
-rw-r--r--src/librustdoc/test.rs4
-rw-r--r--src/libstd/collections/hash/map.rs2
-rw-r--r--src/libstd/collections/hash/table.rs2
-rw-r--r--src/libstd/error.rs2
-rw-r--r--src/libstd/io/cursor.rs2
-rw-r--r--src/libstd/macros.rs16
-rw-r--r--src/libstd/sync/barrier.rs2
-rw-r--r--src/libstd/sync/once.rs2
-rw-r--r--src/libstd/sys/unix/rand.rs4
-rw-r--r--src/libstd/sys/windows/fs.rs4
-rw-r--r--src/libstd_unicode/tables.rs29
-rwxr-xr-xsrc/libstd_unicode/unicode.py29
-rw-r--r--src/libsyntax/diagnostic_list.rs60
-rw-r--r--src/libsyntax/ext/source_util.rs10
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs4
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs2
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/libsyntax/parse/lexer/unicode_chars.rs144
-rw-r--r--src/libsyntax/parse/parser.rs23
-rw-r--r--src/libsyntax_ext/format.rs2
-rw-r--r--src/libsyntax_ext/lib.rs1
-rw-r--r--src/rustllvm/PassWrapper.cpp6
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs1
-rw-r--r--src/test/compile-fail/E0010.rs1
-rw-r--r--src/test/compile-fail/E0394.rs2
-rw-r--r--src/test/compile-fail/bad-lint-cap2.rs1
-rw-r--r--src/test/compile-fail/bad-lint-cap3.rs1
-rw-r--r--src/test/compile-fail/check-static-values-constraints.rs1
-rw-r--r--src/test/compile-fail/const-eval-overflow-2.rs2
-rw-r--r--src/test/compile-fail/const-match-pattern-arm.rs2
-rw-r--r--src/test/compile-fail/feature-gate-dropck-ugeh.rs1
-rw-r--r--src/test/compile-fail/issue-14227.rs2
-rw-r--r--src/test/compile-fail/issue-16538.rs2
-rw-r--r--src/test/compile-fail/issue-17450.rs2
-rw-r--r--src/test/compile-fail/issue-17718-const-naming.rs1
-rw-r--r--src/test/compile-fail/issue-17718-references.rs2
-rw-r--r--src/test/compile-fail/issue-18937.rs2
-rw-r--r--src/test/compile-fail/issue-28075.rs2
-rw-r--r--src/test/compile-fail/issue-28113.rs2
-rw-r--r--src/test/compile-fail/issue-28324.rs2
-rw-r--r--src/test/compile-fail/issue-30730.rs1
-rw-r--r--src/test/compile-fail/issue-37515.rs1
-rw-r--r--src/test/compile-fail/issue-7364.rs1
-rw-r--r--src/test/compile-fail/lint-removed-allow.rs3
-rw-r--r--src/test/compile-fail/lint-removed-cmdline.rs2
-rw-r--r--src/test/compile-fail/lint-renamed-allow.rs3
-rw-r--r--src/test/compile-fail/lint-stability-deprecated.rs222
-rw-r--r--src/test/compile-fail/lint-type-overflow2.rs20
-rw-r--r--src/test/compile-fail/lint-unused-mut-variables.rs20
-rw-r--r--src/test/compile-fail/lint-uppercase-variables.rs1
-rw-r--r--src/test/compile-fail/liveness-unused.rs1
-rw-r--r--src/test/compile-fail/never-assign-dead-code.rs14
-rw-r--r--src/test/compile-fail/private-inferred-type.rs1
-rw-r--r--src/test/compile-fail/private-type-in-interface.rs1
-rw-r--r--src/test/compile-fail/rust-unstable-column-gated.rs14
-rw-r--r--src/test/compile-fail/static-mut-not-constant.rs3
-rw-r--r--src/test/compile-fail/struct-path-self-type-mismatch.rs12
-rw-r--r--src/test/compile-fail/unreachable-try-pattern.rs15
-rw-r--r--src/test/run-pass/issue-43057.rs23
-rw-r--r--src/test/rustdoc/nul-error.rs18
-rw-r--r--src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs1
-rw-r--r--src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr11
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-res.stderr2
-rw-r--r--src/test/ui/block-result/issue-13624.stderr2
-rw-r--r--src/test/ui/block-result/issue-22645.stderr3
-rw-r--r--src/test/ui/block-result/issue-5500.stderr2
-rw-r--r--src/test/ui/check_match/issue-43253.rs3
-rw-r--r--src/test/ui/check_match/issue-43253.stderr18
-rw-r--r--src/test/ui/compare-method/proj-outlives-region.stderr2
-rw-r--r--src/test/ui/compare-method/region-unrelated.stderr2
-rw-r--r--src/test/ui/extern-const.rs19
-rw-r--r--src/test/ui/extern-const.stderr8
-rw-r--r--src/test/ui/lint/fn_must_use.rs34
-rw-r--r--src/test/ui/lint/fn_must_use.stderr18
-rw-r--r--src/test/ui/lint/outer-forbid.rs8
-rw-r--r--src/test/ui/lint/outer-forbid.stderr24
-rw-r--r--src/test/ui/mismatched_types/abridged.stderr14
-rw-r--r--src/test/ui/path-lookahead.rs2
-rw-r--r--src/test/ui/path-lookahead.stderr27
-rw-r--r--src/test/ui/reachable/expr_unary.stderr14
-rw-r--r--src/test/ui/span/issue-24690.rs7
-rw-r--r--src/test/ui/span/issue-24690.stderr49
-rw-r--r--src/test/ui/span/macro-span-replacement.rs2
-rw-r--r--src/test/ui/span/macro-span-replacement.stderr13
-rw-r--r--src/test/ui/span/multispan-import-lint.rs2
-rw-r--r--src/test/ui/span/multispan-import-lint.stderr11
-rw-r--r--src/test/ui/trait-method-private.rs30
-rw-r--r--src/test/ui/trait-method-private.stderr12
m---------src/tools/cargo0
-rw-r--r--src/tools/compiletest/src/runtest.rs18
167 files changed, 2445 insertions, 1438 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 398b23061ea..38897993d43 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -75,7 +75,7 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -88,7 +88,7 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -99,7 +99,7 @@ version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -135,7 +135,7 @@ dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -200,7 +200,7 @@ dependencies = [
  "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -234,7 +234,7 @@ dependencies = [
  "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -302,7 +302,7 @@ dependencies = [
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -341,7 +341,7 @@ version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -354,7 +354,7 @@ version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -456,7 +456,7 @@ name = "filetime"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -472,7 +472,7 @@ name = "flate2"
 version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -496,7 +496,7 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -521,7 +521,7 @@ version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -662,7 +662,7 @@ name = "jobserver"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -714,7 +714,7 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.27"
+version = "0.2.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -725,7 +725,7 @@ dependencies = [
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -738,7 +738,7 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -750,7 +750,7 @@ version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -771,7 +771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -801,7 +801,7 @@ name = "memchr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -809,7 +809,7 @@ name = "memchr"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -818,7 +818,7 @@ version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -843,7 +843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -919,7 +919,7 @@ name = "num_cpus"
 version = "1.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -935,7 +935,7 @@ dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -950,7 +950,7 @@ version = "0.9.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1072,7 +1072,7 @@ name = "rand"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1604,7 +1604,7 @@ dependencies = [
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1709,7 +1709,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1828,7 +1828,7 @@ name = "syntex_errors"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1850,7 +1850,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1865,7 +1865,7 @@ version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1896,7 +1896,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1931,7 +1931,7 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2120,7 +2120,7 @@ name = "xattr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2189,7 +2189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf"
 "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
-"checksum libc 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "719aa0af4c241fa71d396ffdfe584aa758f08f35b4680ec3f03ecc2c3fe69b76"
+"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264"
 "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d"
 "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
 "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 811c7df5d99..d7f795e4055 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -427,7 +427,7 @@ impl<'a> Builder<'a> {
             } else {
                 self.sysroot(compiler)
             })
-            .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
+            .env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
             .env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
             .env("RUSTDOC_REAL", self.rustdoc(compiler));
         cmd
diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py
index e3c08bb35e0..e9cf71c32fe 100644
--- a/src/etc/platform-intrinsics/generator.py
+++ b/src/etc/platform-intrinsics/generator.py
@@ -19,7 +19,7 @@ import itertools
 SPEC = re.compile(
     r'^(?:(?P<void>V)|(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
     r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
-    r'|(?P<reference>\d+))(?P<index>\.\d+)?(?P<modifiers>[vShdnwusfDMC]*)(?P<force_width>x\d+)?'
+    r'|(?P<reference>\d+))(?P<index>\.\d+)?(?P<modifiers>[vShdnwusfDMCNW]*)(?P<force_width>x\d+)?'
     r'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?|(?P<bitcast>->.*))?$'
 )
 
@@ -246,6 +246,12 @@ class Vector(Type):
             return Vector(self._elem, self._length // 2)
         elif spec == 'd':
             return Vector(self._elem, self._length * 2)
+        elif spec == 'N':
+            elem = self._elem.__class__(self._elem.bitwidth() // 2)
+            return Vector(elem, self._length * 2)
+        elif spec == 'W':
+            elem = self._elem.__class__(self._elem.bitwidth() * 2)
+            return Vector(elem, self._length // 2)
         elif spec.startswith('x'):
             new_bitwidth = int(spec[1:])
             return Vector(self._elem, new_bitwidth // self._elem.bitwidth())
@@ -714,6 +720,8 @@ def parse_args():
         - 'd': double the length of the vector (u32x2 -> u32x4)
         - 'n': narrow the element of the vector (u32x4 -> u16x4)
         - 'w': widen the element of the vector (u16x4 -> u32x4)
+        - 'N': half the length of the vector element (u32x4 -> u16x8)
+        - 'W': double the length of the vector element (u16x8 -> u32x4)
         - 'u': force a number (vector or scalar) to be unsigned int (f32x4 -> u32x4)
         - 's': force a number (vector or scalar) to be signed int (u32x4 -> i32x4)
         - 'f': force a number (vector or scalar) to be float (u32x4 -> f32x4)
diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json
index 7f01aaa3ac1..c70791be030 100644
--- a/src/etc/platform-intrinsics/powerpc.json
+++ b/src/etc/platform-intrinsics/powerpc.json
@@ -72,6 +72,55 @@
             "llvm": "vmin{0.kind}{0.data_type_short}",
             "ret": "i(8-32)",
             "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "sub{0.kind}{0.data_type_short}s",
+            "width": [128],
+            "llvm": "vsub{0.kind}{0.data_type_short}s",
+            "ret": "i(8-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "subc",
+            "width": [128],
+            "llvm": "vsubcuw",
+            "ret": "u32",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "add{0.kind}{0.data_type_short}s",
+            "width": [128],
+            "llvm": "vadd{0.kind}{0.data_type_short}s",
+            "ret": "i(8-32)",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "addc",
+            "width": [128],
+            "llvm": "vaddcuw",
+            "ret": "u32",
+            "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "mule{1.kind}{1.data_type_short}",
+            "width": [128],
+            "llvm": "vmule{0.kind}{1.data_type_short}",
+            "ret": "i(16-32)",
+            "args": ["0N", "1"]
+        },
+        {
+            "intrinsic": "mulo{1.kind}{1.data_type_short}",
+            "width": [128],
+            "llvm": "vmulo{0.kind}{1.data_type_short}",
+            "ret": "i(16-32)",
+            "args": ["0N", "1"]
+        },
+        {
+            "intrinsic": "avg{0.kind}{0.data_type_short}",
+            "width": [128],
+            "llvm": "vavg{0.kind}{0.data_type_short}",
+            "ret": "i(8-32)",
+            "args": ["0", "0"]
         }
     ]
 }
diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs
index 06d3a113b94..8cea6c482c3 100644
--- a/src/liballoc/btree/node.rs
+++ b/src/liballoc/btree/node.rs
@@ -1037,7 +1037,7 @@ impl<'a, K: 'a, V: 'a, NodeType>
         Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
 
     pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
-        let (mut keys, mut vals) = self.node.into_slices_mut();
+        let (keys, vals) = self.node.into_slices_mut();
         unsafe {
             (keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
         }
@@ -1047,7 +1047,7 @@ impl<'a, K: 'a, V: 'a, NodeType>
 impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
     pub fn kv_mut(&mut self) -> (&mut K, &mut V) {
         unsafe {
-            let (mut keys, mut vals) = self.node.reborrow_mut().into_slices_mut();
+            let (keys, vals) = self.node.reborrow_mut().into_slices_mut();
             (keys.get_unchecked_mut(self.idx), vals.get_unchecked_mut(self.idx))
         }
     }
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index da47ca50983..160c0ba2ab0 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1751,7 +1751,7 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
     type Item = &'a mut T;
     type IntoIter = slice::IterMut<'a, T>;
 
-    fn into_iter(mut self) -> slice::IterMut<'a, T> {
+    fn into_iter(self) -> slice::IterMut<'a, T> {
         self.iter_mut()
     }
 }
diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs
index fdd6c79ef2e..2068c2c9c5f 100644
--- a/src/liballoc/vec_deque.rs
+++ b/src/liballoc/vec_deque.rs
@@ -2394,7 +2394,7 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
     type Item = &'a mut T;
     type IntoIter = IterMut<'a, T>;
 
-    fn into_iter(mut self) -> IterMut<'a, T> {
+    fn into_iter(self) -> IterMut<'a, T> {
         self.iter_mut()
     }
 }
@@ -2558,7 +2558,7 @@ impl<'a, T> Place<T> for PlaceBack<'a, T> {
 impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
     type Owner = &'a mut T;
 
-    unsafe fn finalize(mut self) -> &'a mut T {
+    unsafe fn finalize(self) -> &'a mut T {
         let head = self.vec_deque.head;
         self.vec_deque.head = self.vec_deque.wrap_add(head, 1);
         &mut *(self.vec_deque.ptr().offset(head as isize))
@@ -2605,7 +2605,7 @@ impl<'a, T> Place<T> for PlaceFront<'a, T> {
 impl<'a, T> InPlace<T> for PlaceFront<'a, T> {
     type Owner = &'a mut T;
 
-    unsafe fn finalize(mut self) -> &'a mut T {
+    unsafe fn finalize(self) -> &'a mut T {
         self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
         &mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize))
     }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index a9f55dc2788..ec6525485f7 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -110,11 +110,13 @@ use self::Ordering::*;
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
     /// by `==`.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq(&self, other: &Rhs) -> bool;
 
     /// This method tests for `!=`.
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
 }
@@ -625,6 +627,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// let result = std::f64::NAN.partial_cmp(&1.0);
     /// assert_eq!(result, None);
     /// ```
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
 
@@ -640,6 +643,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// assert_eq!(result, false);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lt(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
@@ -661,6 +665,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// assert_eq!(result, true);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn le(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
@@ -681,6 +686,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// assert_eq!(result, false);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn gt(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
@@ -702,6 +708,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// assert_eq!(result, true);
     /// ```
     #[inline]
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn ge(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index 32c32e327eb..73d518b570a 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -214,9 +214,16 @@ impl<A: Step> Iterator for ops::Range<A> {
     #[inline]
     fn next(&mut self) -> Option<A> {
         if self.start < self.end {
-            let mut n = self.start.add_one();
-            mem::swap(&mut n, &mut self.start);
-            Some(n)
+            // We check for overflow here, even though it can't actually
+            // happen. Adding this check does however help llvm vectorize loops
+            // for some ranges that don't get vectorized otherwise,
+            // and this won't actually result in an extra check in an optimized build.
+            if let Some(mut n) = self.start.add_usize(1) {
+                mem::swap(&mut n, &mut self.start);
+                Some(n)
+            } else {
+                None
+            }
         } else {
             None
         }
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 2edf8e1fa88..684b81a27f8 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -8,6 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[macro_export]
+// This stability attribute is totally useless.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+macro_rules! __rust_unstable_column {
+    () => {
+        column!()
+    }
+}
+
 /// Entry point of thread panic, for details, see std::macros
 #[macro_export]
 #[allow_internal_unstable]
@@ -18,7 +28,7 @@ macro_rules! panic {
     );
     ($msg:expr) => ({
         static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) =
-            ($msg, file!(), line!(), column!());
+            ($msg, file!(), line!(), __rust_unstable_column!());
         $crate::panicking::panic(&_MSG_FILE_LINE_COL)
     });
     ($fmt:expr, $($arg:tt)*) => ({
@@ -27,7 +37,7 @@ macro_rules! panic {
         // insufficient, since the user may have
         // `#[forbid(dead_code)]` and which cannot be overridden.
         static _MSG_FILE_LINE_COL: (&'static str, u32, u32) =
-            (file!(), line!(), column!());
+            (file!(), line!(), __rust_unstable_column!());
         $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL)
     });
 }
diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs
index 62bf69336a3..c5b3fbca1a6 100644
--- a/src/libcore/ops/function.rs
+++ b/src/libcore/ops/function.rs
@@ -187,7 +187,7 @@ mod impls {
         where F : FnMut<A>
     {
         type Output = F::Output;
-        extern "rust-call" fn call_once(mut self, args: A) -> F::Output {
+        extern "rust-call" fn call_once(self, args: A) -> F::Output {
             (*self).call_mut(args)
         }
     }
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index ef41b679410..aecf2ee9325 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -872,7 +872,7 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
     type Item = &'a mut T;
     type IntoIter = IterMut<'a, T>;
 
-    fn into_iter(mut self) -> IterMut<'a, T> {
+    fn into_iter(self) -> IterMut<'a, T> {
         self.iter_mut()
     }
 }
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 88a93492de9..20cfb02afcc 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -909,7 +909,7 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
     type Item = &'a mut T;
     type IntoIter = IterMut<'a, T>;
 
-    fn into_iter(mut self) -> IterMut<'a, T> {
+    fn into_iter(self) -> IterMut<'a, T> {
         self.iter_mut()
     }
 }
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index e5d6b53b570..8c31d2e83d3 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -105,27 +105,27 @@ fn test_chunks_last() {
 
 #[test]
 fn test_chunks_mut_count() {
-    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     let c = v.chunks_mut(3);
     assert_eq!(c.count(), 2);
 
-    let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
     let c2 = v2.chunks_mut(2);
     assert_eq!(c2.count(), 3);
 
-    let mut v3: &mut [i32] = &mut [];
+    let v3: &mut [i32] = &mut [];
     let c3 = v3.chunks_mut(2);
     assert_eq!(c3.count(), 0);
 }
 
 #[test]
 fn test_chunks_mut_nth() {
-    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     let mut c = v.chunks_mut(2);
     assert_eq!(c.nth(1).unwrap()[1], 3);
     assert_eq!(c.next().unwrap()[0], 4);
 
-    let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
     let mut c2 = v2.chunks_mut(3);
     assert_eq!(c2.nth(1).unwrap()[1], 4);
     assert_eq!(c2.next(), None);
@@ -194,7 +194,7 @@ fn get_range() {
 
 #[test]
 fn get_mut_range() {
-    let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
     assert_eq!(v.get_mut(..), Some(&mut [0, 1, 2, 3, 4, 5][..]));
     assert_eq!(v.get_mut(..2), Some(&mut [0, 1][..]));
     assert_eq!(v.get_mut(2..), Some(&mut [2, 3, 4, 5][..]));
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index c6f9cb2fcea..5b609f192e1 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -521,6 +521,7 @@ define_dep_nodes!( <'tcx>
     [] IsAllocator(DefId),
     [] IsPanicRuntime(DefId),
     [] ExternCrate(DefId),
+    [] LintLevels,
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index e316fd5f3e6..352d25dad65 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -640,8 +640,6 @@ for ty::TypeckTables<'tcx> {
 
             ref cast_kinds,
 
-            // FIXME(#41184): This is still ignored at the moment.
-            lints: _,
             ref used_trait_imports,
             tainted_by_errors,
             ref free_region_map,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 8e8576b83e4..9f70b4834dd 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -415,8 +415,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// -------- this type is the same as a type argument in the other type, not highlighted
     /// ```
     fn highlight_outer(&self,
-                       mut value: &mut DiagnosticStyledString,
-                       mut other_value: &mut DiagnosticStyledString,
+                       value: &mut DiagnosticStyledString,
+                       other_value: &mut DiagnosticStyledString,
                        name: String,
                        sub: &ty::subst::Substs<'tcx>,
                        pos: usize,
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index d67bca1df30..6ee06dc0a81 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -23,29 +23,25 @@
 //! previous lint state is pushed onto a stack and the ast is then recursed
 //! upon.  As the ast is traversed, this keeps track of the current lint level
 //! for all lint attributes.
+
 use self::TargetLint::*;
 
+use rustc_back::slice;
+use lint::{EarlyLintPassObject, LateLintPassObject};
+use lint::{Level, Lint, LintId, LintPass, LintBuffer};
+use lint::levels::{LintLevelSets, LintLevelsBuilder};
 use middle::privacy::AccessLevels;
+use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
+use session::{config, early_error, Session};
 use traits::Reveal;
 use ty::{self, TyCtxt};
-use session::{config, early_error, Session};
-use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource};
-use lint::{EarlyLintPassObject, LateLintPassObject};
-use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
-use lint::builtin;
-use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
 use util::nodemap::FxHashMap;
 
-use std::cmp;
 use std::default::Default as StdDefault;
-use std::mem;
-use std::fmt;
 use std::cell::{Ref, RefCell};
-use syntax::attr;
 use syntax::ast;
-use syntax::symbol::Symbol;
 use syntax_pos::{MultiSpan, Span};
-use errors::{self, Diagnostic, DiagnosticBuilder};
+use errors::DiagnosticBuilder;
 use hir;
 use hir::def_id::LOCAL_CRATE;
 use hir::intravisit as hir_visit;
@@ -69,9 +65,6 @@ pub struct LintStore {
     /// Lints indexed by name.
     by_name: FxHashMap<String, TargetLint>,
 
-    /// Current levels of each lint, and where they were set.
-    levels: LintLevels,
-
     /// Map of registered lint groups to what lints they expand to. The bool
     /// is true if the lint group was added by a plugin.
     lint_groups: FxHashMap<&'static str, (Vec<LintId>, bool)>,
@@ -81,78 +74,23 @@ pub struct LintStore {
     future_incompatible: FxHashMap<LintId, FutureIncompatibleInfo>,
 }
 
-
-#[derive(Default)]
-struct LintLevels {
-    /// Current levels of each lint, and where they were set.
-    levels: FxHashMap<LintId, LevelSource>,
-
-    /// Maximum level a lint can be
-    lint_cap: Option<Level>,
-}
-
-
 pub struct LintSession<'a, PassObject> {
     /// Reference to the store of registered lints.
     lints: Ref<'a, LintStore>,
 
-    /// The current lint levels.
-    levels: LintLevels,
-
-    /// When recursing into an attributed node of the ast which modifies lint
-    /// levels, this stack keeps track of the previous lint levels of whatever
-    /// was modified.
-    stack: Vec<(LintId, LevelSource)>,
-
     /// Trait objects for each lint pass.
     passes: Option<Vec<PassObject>>,
 }
 
 
-/// When you call `add_lint` on the session, you wind up storing one
-/// of these, which records a "potential lint" at a particular point.
-#[derive(PartialEq, RustcEncodable, RustcDecodable)]
-pub struct EarlyLint {
-    /// what lint is this? (e.g., `dead_code`)
-    pub id: LintId,
-
-    /// the main message
-    pub diagnostic: Diagnostic,
-}
-
-impl fmt::Debug for EarlyLint {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("EarlyLint")
-            .field("id", &self.id)
-            .field("span", &self.diagnostic.span)
-            .field("diagnostic", &self.diagnostic)
-            .finish()
-    }
-}
-
-pub trait IntoEarlyLint {
-    fn into_early_lint(self, id: LintId) -> EarlyLint;
-}
-
-impl<'a, S: Into<MultiSpan>> IntoEarlyLint for (S, &'a str) {
-    fn into_early_lint(self, id: LintId) -> EarlyLint {
-        let (span, msg) = self;
-        let mut diagnostic = Diagnostic::new(errors::Level::Warning, msg);
-        diagnostic.set_span(span);
-        EarlyLint {
-            id,
-            diagnostic,
-        }
-    }
-}
-
-impl IntoEarlyLint for Diagnostic {
-    fn into_early_lint(self, id: LintId) -> EarlyLint {
-        EarlyLint {
-            id,
-            diagnostic: self,
-        }
-    }
+/// Lints that are buffered up early on in the `Session` before the
+/// `LintLevels` is calculated
+#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+pub struct BufferedEarlyLint {
+    pub lint_id: LintId,
+    pub ast_id: ast::NodeId,
+    pub span: MultiSpan,
+    pub msg: String,
 }
 
 /// Extra information for a future incompatibility lint. See the call
@@ -176,11 +114,20 @@ enum TargetLint {
     Removed(String),
 }
 
-enum FindLintError {
+pub enum FindLintError {
     NotFound,
     Removed,
 }
 
+pub enum CheckLintNameResult<'a> {
+    Ok(&'a [LintId]),
+    // Lint doesn't exist
+    NoLint,
+    // The lint is either renamed or removed. This is the warning
+    // message.
+    Warning(String),
+}
+
 impl LintStore {
     pub fn new() -> LintStore {
         LintStore {
@@ -188,7 +135,6 @@ impl LintStore {
             early_passes: Some(vec![]),
             late_passes: Some(vec![]),
             by_name: FxHashMap(),
-            levels: LintLevels::default(),
             future_incompatible: FxHashMap(),
             lint_groups: FxHashMap(),
         }
@@ -241,8 +187,6 @@ impl LintStore {
                     (Some(sess), true)  => sess.err(&msg[..]),
                 }
             }
-
-            self.levels.set(id, (lint.default_level, Default));
         }
     }
 
@@ -291,96 +235,93 @@ impl LintStore {
         self.by_name.insert(name.into(), Removed(reason.into()));
     }
 
-    fn find_lint(&self, lint_name: &str) -> Result<LintId, FindLintError> {
+    pub fn find_lints(&self, lint_name: &str) -> Result<Vec<LintId>, FindLintError> {
         match self.by_name.get(lint_name) {
-            Some(&Id(lint_id)) => Ok(lint_id),
+            Some(&Id(lint_id)) => Ok(vec![lint_id]),
             Some(&Renamed(_, lint_id)) => {
-                Ok(lint_id)
+                Ok(vec![lint_id])
             },
             Some(&Removed(_)) => {
                 Err(FindLintError::Removed)
             },
-            None => Err(FindLintError::NotFound)
-        }
-    }
-
-    pub fn process_command_line(&mut self, sess: &Session) {
-        for &(ref lint_name, level) in &sess.opts.lint_opts {
-            check_lint_name_cmdline(sess, self,
-                                    &lint_name[..], level);
-
-            let lint_flag_val = Symbol::intern(&lint_name);
-            match self.find_lint(&lint_name[..]) {
-                Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))),
-                Err(FindLintError::Removed) => { }
-                Err(_) => {
-                    match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
-                                                 .collect::<FxHashMap<&'static str,
-                                                                      Vec<LintId>>>()
-                                                 .get(&lint_name[..]) {
-                        Some(v) => {
-                            for lint_id in v {
-                                self.levels.set(*lint_id, (level, CommandLine(lint_flag_val)));
-                            }
-                        }
-                        None => {
-                            // The lint or lint group doesn't exist.
-                            // This is an error, but it was handled
-                            // by check_lint_name_cmdline.
-                        }
-                    }
+            None => {
+                match self.lint_groups.get(lint_name) {
+                    Some(v) => Ok(v.0.clone()),
+                    None => Err(FindLintError::Removed)
                 }
             }
         }
-
-        self.levels.set_lint_cap(sess.opts.lint_cap);
     }
-}
-
 
-impl LintLevels {
-    fn get_source(&self, lint: LintId) -> LevelSource {
-        match self.levels.get(&lint) {
-            Some(&s) => s,
-            None => (Allow, Default),
-        }
-    }
+    // Checks the validity of lint names derived from the command line
+    pub fn check_lint_name_cmdline(&self,
+                                   sess: &Session,
+                                   lint_name: &str,
+                                   level: Level) {
+        let db = match self.check_lint_name(lint_name) {
+            CheckLintNameResult::Ok(_) => None,
+            CheckLintNameResult::Warning(ref msg) => {
+                Some(sess.struct_warn(msg))
+            },
+            CheckLintNameResult::NoLint => {
+                Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
+            }
+        };
 
-    fn set(&mut self, lint: LintId, mut lvlsrc: LevelSource) {
-        if let Some(cap) = self.lint_cap {
-            lvlsrc.0 = cmp::min(lvlsrc.0, cap);
-        }
-        if lvlsrc.0 == Allow {
-            self.levels.remove(&lint);
-        } else {
-            self.levels.insert(lint, lvlsrc);
+        if let Some(mut db) = db {
+            let msg = format!("requested on the command line with `{} {}`",
+                              match level {
+                                  Level::Allow => "-A",
+                                  Level::Warn => "-W",
+                                  Level::Deny => "-D",
+                                  Level::Forbid => "-F",
+                              },
+                              lint_name);
+            db.note(&msg);
+            db.emit();
         }
     }
 
-    fn set_lint_cap(&mut self, lint_cap: Option<Level>) {
-        self.lint_cap = lint_cap;
-        if let Some(cap) = lint_cap {
-            for (_, level) in &mut self.levels {
-                level.0 = cmp::min(level.0, cap);
+    /// Checks the name of a lint for its existence, and whether it was
+    /// renamed or removed. Generates a DiagnosticBuilder containing a
+    /// warning for renamed and removed lints. This is over both lint
+    /// names from attributes and those passed on the command line. Since
+    /// it emits non-fatal warnings and there are *two* lint passes that
+    /// inspect attributes, this is only run from the late pass to avoid
+    /// printing duplicate warnings.
+    pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult {
+        match self.by_name.get(lint_name) {
+            Some(&Renamed(ref new_name, _)) => {
+                CheckLintNameResult::Warning(
+                    format!("lint {} has been renamed to {}", lint_name, new_name)
+                )
+            },
+            Some(&Removed(ref reason)) => {
+                CheckLintNameResult::Warning(
+                    format!("lint {} has been removed: {}", lint_name, reason)
+                )
+            },
+            None => {
+                match self.lint_groups.get(lint_name) {
+                    None => CheckLintNameResult::NoLint,
+                    Some(ids) => CheckLintNameResult::Ok(&ids.0),
+                }
             }
+            Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::ref_slice(id)),
         }
     }
 }
 
-
 impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> {
     /// Creates a new `LintSession`, by moving out the `LintStore`'s initial
     /// lint levels and pass objects. These can be restored using the `restore`
     /// method.
     fn new(store: &'a RefCell<LintStore>) -> LintSession<'a, PassObject> {
         let mut s = store.borrow_mut();
-        let levels = mem::replace(&mut s.levels, LintLevels::default());
         let passes = PassObject::take_passes(&mut *s);
         drop(s);
         LintSession {
             lints: store.borrow(),
-            stack: Vec::new(),
-            levels,
             passes,
         }
     }
@@ -389,17 +330,10 @@ impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> {
     fn restore(self, store: &RefCell<LintStore>) {
         drop(self.lints);
         let mut s = store.borrow_mut();
-        s.levels = self.levels;
         PassObject::restore_passes(&mut *s, self.passes);
     }
-
-    fn get_source(&self, lint_id: LintId) -> LevelSource {
-        self.levels.get_source(lint_id)
-    }
 }
 
-
-
 /// Context for lint checking after type checking.
 pub struct LateContext<'a, 'tcx: 'a> {
     /// Type context we're checking in.
@@ -416,6 +350,8 @@ pub struct LateContext<'a, 'tcx: 'a> {
 
     /// The store of registered lints and the lint levels.
     lint_sess: LintSession<'tcx, LateLintPassObject>,
+
+    last_ast_node_with_lint_attrs: ast::NodeId,
 }
 
 /// Context for lint checking of the AST, after expansion, before lowering to
@@ -427,8 +363,12 @@ pub struct EarlyContext<'a> {
     /// The crate being checked.
     pub krate: &'a ast::Crate,
 
+    builder: LintLevelsBuilder<'a>,
+
     /// The store of registered lints and the lint levels.
     lint_sess: LintSession<'a, EarlyLintPassObject>,
+
+    buffered: LintBuffer,
 }
 
 /// Convenience macro for calling a `LintPass` method on every pass in the context.
@@ -442,135 +382,6 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({
     $cx.lint_sess_mut().passes = Some(passes);
 }) }
 
-/// Parse the lint attributes into a vector, with `Err`s for malformed lint
-/// attributes. Writing this as an iterator is an enormous mess.
-// See also the hir version just below.
-pub fn gather_attrs(attrs: &[ast::Attribute]) -> Vec<Result<(ast::Name, Level, Span), Span>> {
-    let mut out = vec![];
-    for attr in attrs {
-        let r = gather_attr(attr);
-        out.extend(r.into_iter());
-    }
-    out
-}
-
-pub fn gather_attr(attr: &ast::Attribute) -> Vec<Result<(ast::Name, Level, Span), Span>> {
-    let mut out = vec![];
-
-    let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) {
-        None => return out,
-        Some(lvl) => lvl,
-    };
-
-    let meta = unwrap_or!(attr.meta(), return out);
-    attr::mark_used(attr);
-
-    let metas = if let Some(metas) = meta.meta_item_list() {
-        metas
-    } else {
-        out.push(Err(meta.span));
-        return out;
-    };
-
-    for li in metas {
-        out.push(li.word().map_or(Err(li.span), |word| Ok((word.name(), level, word.span))));
-    }
-
-    out
-}
-
-/// Emit a lint as a warning or an error (or not at all)
-/// according to `level`.
-///
-/// This lives outside of `Context` so it can be used by checks
-/// in trans that run after the main lint pass is finished. Most
-/// lints elsewhere in the compiler should call
-/// `Session::add_lint()` instead.
-pub fn raw_emit_lint<S: Into<MultiSpan>>(sess: &Session,
-                                         lints: &LintStore,
-                                         lint: &'static Lint,
-                                         lvlsrc: LevelSource,
-                                         span: Option<S>,
-                                         msg: &str) {
-    raw_struct_lint(sess, lints, lint, lvlsrc, span, msg).emit();
-}
-
-pub fn raw_struct_lint<'a, S>(sess: &'a Session,
-                              lints: &LintStore,
-                              lint: &'static Lint,
-                              lvlsrc: LevelSource,
-                              span: Option<S>,
-                              msg: &str)
-                              -> DiagnosticBuilder<'a>
-    where S: Into<MultiSpan>
-{
-    let (level, source) = lvlsrc;
-    if level == Allow {
-        return sess.diagnostic().struct_dummy();
-    }
-
-    let name = lint.name_lower();
-
-    // Except for possible note details, forbid behaves like deny.
-    let effective_level = if level == Forbid { Deny } else { level };
-
-    let mut err = match (effective_level, span) {
-        (Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]),
-        (Warn, None)     => sess.struct_warn(&msg[..]),
-        (Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]),
-        (Deny, None)     => sess.struct_err(&msg[..]),
-        _ => bug!("impossible level in raw_emit_lint"),
-    };
-
-    match source {
-        Default => {
-            sess.diag_note_once(&mut err, lint,
-                                &format!("#[{}({})] on by default", level.as_str(), name));
-        },
-        CommandLine(lint_flag_val) => {
-            let flag = match level {
-                Warn => "-W", Deny => "-D", Forbid => "-F",
-                Allow => bug!("earlier conditional return should handle Allow case")
-            };
-            let hyphen_case_lint_name = name.replace("_", "-");
-            if lint_flag_val.as_str() == name {
-                sess.diag_note_once(&mut err, lint,
-                                    &format!("requested on the command line with `{} {}`",
-                                             flag, hyphen_case_lint_name));
-            } else {
-                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
-                sess.diag_note_once(&mut err, lint,
-                                    &format!("`{} {}` implied by `{} {}`",
-                                             flag, hyphen_case_lint_name, flag,
-                                             hyphen_case_flag_val));
-            }
-        },
-        Node(lint_attr_name, src) => {
-            sess.diag_span_note_once(&mut err, lint, src, "lint level defined here");
-            if lint_attr_name.as_str() != name {
-                let level_str = level.as_str();
-                sess.diag_note_once(&mut err, lint,
-                                    &format!("#[{}({})] implied by #[{}({})]",
-                                             level_str, name, level_str, lint_attr_name));
-            }
-        }
-    }
-
-    // Check for future incompatibility lints and issue a stronger warning.
-    if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
-        let explanation = format!("this was previously accepted by the compiler \
-                                   but is being phased out; \
-                                   it will become a hard error in a future release!");
-        let citation = format!("for more information, see {}",
-                               future_incompatible.reference);
-        err.warn(&explanation);
-        err.note(&citation);
-    }
-
-    err
-}
-
-
 pub trait LintPassObject: Sized {
     fn take_passes(store: &mut LintStore) -> Option<Vec<Self>>;
     fn restore_passes(store: &mut LintStore, passes: Option<Vec<Self>>);
@@ -607,67 +418,24 @@ pub trait LintContext<'tcx>: Sized {
     fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]);
     fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]);
 
-    /// Get the level of `lint` at the current position of the lint
-    /// traversal.
-    fn current_level(&self, lint: &'static Lint) -> Level {
-        self.lint_sess().get_source(LintId::of(lint)).0
-    }
-
-    fn level_src(&self, lint: &'static Lint) -> Option<LevelSource> {
-        let ref levels = self.lint_sess().levels;
-        levels.levels.get(&LintId::of(lint)).map(|ls| match ls {
-            &(Warn, _) => {
-                let lint_id = LintId::of(builtin::WARNINGS);
-                let warn_src = levels.get_source(lint_id);
-                if warn_src.0 != Warn {
-                    warn_src
-                } else {
-                    *ls
-                }
-            }
-            _ => *ls
-        })
-    }
-
     fn lookup_and_emit<S: Into<MultiSpan>>(&self,
                                            lint: &'static Lint,
                                            span: Option<S>,
                                            msg: &str) {
-        let (level, src) = match self.level_src(lint) {
-            None => return,
-            Some(pair) => pair,
-        };
-
-        raw_emit_lint(&self.sess(), self.lints(), lint, (level, src), span, msg);
+        self.lookup(lint, span, msg).emit();
     }
 
     fn lookup<S: Into<MultiSpan>>(&self,
                                   lint: &'static Lint,
                                   span: Option<S>,
                                   msg: &str)
-                                  -> DiagnosticBuilder {
-        let (level, src) = match self.level_src(lint) {
-            None => return self.sess().diagnostic().struct_dummy(),
-            Some(pair) => pair,
-        };
-
-        raw_struct_lint(&self.sess(), self.lints(), lint, (level, src), span, msg)
-    }
+                                  -> DiagnosticBuilder;
 
     /// Emit a lint at the appropriate level, for a particular span.
     fn span_lint<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: S, msg: &str) {
         self.lookup_and_emit(lint, Some(span), msg);
     }
 
-    fn early_lint(&self, early_lint: &EarlyLint) {
-        let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span");
-        let mut err = self.struct_span_lint(early_lint.id.lint,
-                                            span,
-                                            &early_lint.diagnostic.message());
-        err.copy_details_not_message(&early_lint.diagnostic);
-        err.emit();
-    }
-
     fn struct_span_lint<S: Into<MultiSpan>>(&self,
                                             lint: &'static Lint,
                                             span: S,
@@ -680,12 +448,10 @@ pub trait LintContext<'tcx>: Sized {
     fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str,
                       note_span: Span, note: &str) {
         let mut err = self.lookup(lint, Some(span), msg);
-        if self.current_level(lint) != Level::Allow {
-            if note_span == span {
-                err.note(note);
-            } else {
-                err.span_note(note_span, note);
-            }
+        if note_span == span {
+            err.note(note);
+        } else {
+            err.span_note(note_span, note);
         }
         err.emit();
     }
@@ -695,9 +461,7 @@ pub trait LintContext<'tcx>: Sized {
                       msg: &str, help: &str) {
         let mut err = self.lookup(lint, Some(span), msg);
         self.span_lint(lint, span, msg);
-        if self.current_level(lint) != Level::Allow {
-            err.span_help(span, help);
-        }
+        err.span_help(span, help);
         err.emit();
     }
 
@@ -710,94 +474,10 @@ pub trait LintContext<'tcx>: Sized {
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
     fn with_lint_attrs<F>(&mut self,
+                          id: ast::NodeId,
                           attrs: &'tcx [ast::Attribute],
                           f: F)
-        where F: FnOnce(&mut Self),
-    {
-        // Parse all of the lint attributes, and then add them all to the
-        // current dictionary of lint information. Along the way, keep a history
-        // of what we changed so we can roll everything back after invoking the
-        // specified closure
-        let mut pushed = 0;
-
-        for result in gather_attrs(attrs) {
-            let (is_group, lint_level_spans) = match result {
-                Err(span) => {
-                    span_err!(self.sess(), span, E0452,
-                              "malformed lint attribute");
-                    continue;
-                }
-                Ok((lint_name, level, span)) => {
-                    match self.lints().find_lint(&lint_name.as_str()) {
-                        Ok(lint_id) => (false, vec![(lint_id, level, span)]),
-                        Err(FindLintError::NotFound) => {
-                            match self.lints().lint_groups.get(&*lint_name.as_str()) {
-                                Some(&(ref v, _)) => (true,
-                                                      v.iter()
-                                                      .map(|lint_id: &LintId|
-                                                           (*lint_id, level, span))
-                                                      .collect()),
-                                None => {
-                                    // The lint or lint group doesn't exist.
-                                    // This is an error, but it was handled
-                                    // by check_lint_name_attribute.
-                                    continue;
-                                }
-                            }
-                        }
-                        Err(FindLintError::Removed) => continue,
-                    }
-                }
-            };
-
-            let lint_attr_name = result.expect("lint attribute should be well-formed").0;
-
-            for (lint_id, level, span) in lint_level_spans {
-                let (now, now_source) = self.lint_sess().get_source(lint_id);
-                if now == Forbid && level != Forbid {
-                    let forbidden_lint_name = match now_source {
-                        LintSource::Default => lint_id.to_string(),
-                        LintSource::Node(name, _) => name.to_string(),
-                        LintSource::CommandLine(name) => name.to_string(),
-                    };
-                    let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
-                                                            "{}({}) overruled by outer forbid({})",
-                                                            level.as_str(), lint_attr_name,
-                                                            forbidden_lint_name);
-                    diag_builder.span_label(span, "overruled by previous forbid");
-                    match now_source {
-                        LintSource::Default => &mut diag_builder,
-                        LintSource::Node(_, forbid_source_span) => {
-                            diag_builder.span_label(forbid_source_span,
-                                                    "`forbid` level set here")
-                        },
-                        LintSource::CommandLine(_) => {
-                            diag_builder.note("`forbid` lint level was set on command line")
-                        }
-                    }.emit();
-                    if is_group { // don't set a separate error for every lint in the group
-                        break;
-                    }
-                } else if now != level {
-                    let cx = self.lint_sess_mut();
-                    cx.stack.push((lint_id, (now, now_source)));
-                    pushed += 1;
-                    cx.levels.set(lint_id, (level, Node(lint_attr_name, span)));
-                }
-            }
-        }
-
-        self.enter_attrs(attrs);
-        f(self);
-        self.exit_attrs(attrs);
-
-        // rollback
-        let cx = self.lint_sess_mut();
-        for _ in 0..pushed {
-            let (lint, lvlsrc) = cx.stack.pop().unwrap();
-            cx.levels.set(lint, lvlsrc);
-        }
-    }
+        where F: FnOnce(&mut Self);
 }
 
 
@@ -808,6 +488,16 @@ impl<'a> EarlyContext<'a> {
             sess,
             krate,
             lint_sess: LintSession::new(&sess.lint_store),
+            builder: LintLevelSets::builder(sess),
+            buffered: sess.buffered_lints.borrow_mut().take().unwrap(),
+        }
+    }
+
+    fn check_id(&mut self, id: ast::NodeId) {
+        for early_lint in self.buffered.take(id) {
+            self.lookup_and_emit(early_lint.lint_id.lint,
+                                 Some(early_lint.span.clone()),
+                                 &early_lint.msg);
         }
     }
 }
@@ -841,6 +531,32 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> {
         debug!("late context: exit_attrs({:?})", attrs);
         run_lints!(self, exit_lint_attrs, late_passes, attrs);
     }
+
+    fn lookup<S: Into<MultiSpan>>(&self,
+                                  lint: &'static Lint,
+                                  span: Option<S>,
+                                  msg: &str)
+                                  -> DiagnosticBuilder {
+        let id = self.last_ast_node_with_lint_attrs;
+        match span {
+            Some(s) => self.tcx.struct_span_lint_node(lint, id, s, msg),
+            None => self.tcx.struct_lint_node(lint, id, msg),
+        }
+    }
+
+    fn with_lint_attrs<F>(&mut self,
+                          id: ast::NodeId,
+                          attrs: &'tcx [ast::Attribute],
+                          f: F)
+        where F: FnOnce(&mut Self)
+    {
+        let prev = self.last_ast_node_with_lint_attrs;
+        self.last_ast_node_with_lint_attrs = id;
+        self.enter_attrs(attrs);
+        f(self);
+        self.exit_attrs(attrs);
+        self.last_ast_node_with_lint_attrs = prev;
+    }
 }
 
 impl<'a> LintContext<'a> for EarlyContext<'a> {
@@ -872,6 +588,28 @@ impl<'a> LintContext<'a> for EarlyContext<'a> {
         debug!("early context: exit_attrs({:?})", attrs);
         run_lints!(self, exit_lint_attrs, early_passes, attrs);
     }
+
+    fn lookup<S: Into<MultiSpan>>(&self,
+                                  lint: &'static Lint,
+                                  span: Option<S>,
+                                  msg: &str)
+                                  -> DiagnosticBuilder {
+        self.builder.struct_lint(lint, span.map(|s| s.into()), msg)
+    }
+
+    fn with_lint_attrs<F>(&mut self,
+                          id: ast::NodeId,
+                          attrs: &'a [ast::Attribute],
+                          f: F)
+        where F: FnOnce(&mut Self)
+    {
+        let push = self.builder.push(attrs);
+        self.check_id(id);
+        self.enter_attrs(attrs);
+        f(self);
+        self.exit_attrs(attrs);
+        self.builder.pop(push);
+    }
 }
 
 impl<'a, 'tcx> LateContext<'a, 'tcx> {
@@ -893,15 +631,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
         hir_visit::NestedVisitorMap::All(&self.tcx.hir)
     }
 
-    // Output any lints that were previously added to the session.
-    fn visit_id(&mut self, id: ast::NodeId) {
-        let lints = self.sess().lints.borrow_mut().take(id);
-        for early_lint in lints.iter().chain(self.tables.lints.get(id)) {
-            debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint);
-            self.early_lint(early_lint);
-        }
-    }
-
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         let old_tables = self.tables;
         self.tables = self.tcx.body_tables(body);
@@ -917,7 +646,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_item(&mut self, it: &'tcx hir::Item) {
-        self.with_lint_attrs(&it.attrs, |cx| {
+        self.with_lint_attrs(it.id, &it.attrs, |cx| {
             cx.with_param_env(it.id, |cx| {
                 run_lints!(cx, check_item, late_passes, it);
                 hir_visit::walk_item(cx, it);
@@ -927,7 +656,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
-        self.with_lint_attrs(&it.attrs, |cx| {
+        self.with_lint_attrs(it.id, &it.attrs, |cx| {
             cx.with_param_env(it.id, |cx| {
                 run_lints!(cx, check_foreign_item, late_passes, it);
                 hir_visit::walk_foreign_item(cx, it);
@@ -942,7 +671,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_expr(&mut self, e: &'tcx hir::Expr) {
-        self.with_lint_attrs(&e.attrs, |cx| {
+        self.with_lint_attrs(e.id, &e.attrs, |cx| {
             run_lints!(cx, check_expr, late_passes, e);
             hir_visit::walk_expr(cx, e);
             run_lints!(cx, check_expr_post, late_passes, e);
@@ -984,7 +713,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
-        self.with_lint_attrs(&s.attrs, |cx| {
+        self.with_lint_attrs(s.id, &s.attrs, |cx| {
             run_lints!(cx, check_struct_field, late_passes, s);
             hir_visit::walk_struct_field(cx, s);
         })
@@ -994,7 +723,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: ast::NodeId) {
-        self.with_lint_attrs(&v.node.attrs, |cx| {
+        self.with_lint_attrs(v.node.data.id(), &v.node.attrs, |cx| {
             run_lints!(cx, check_variant, late_passes, v, g);
             hir_visit::walk_variant(cx, v, g, item_id);
             run_lints!(cx, check_variant_post, late_passes, v, g);
@@ -1017,7 +746,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_local(&mut self, l: &'tcx hir::Local) {
-        self.with_lint_attrs(&l.attrs, |cx| {
+        self.with_lint_attrs(l.id, &l.attrs, |cx| {
             run_lints!(cx, check_local, late_passes, l);
             hir_visit::walk_local(cx, l);
         })
@@ -1045,7 +774,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        self.with_lint_attrs(&trait_item.attrs, |cx| {
+        self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| {
             cx.with_param_env(trait_item.id, |cx| {
                 run_lints!(cx, check_trait_item, late_passes, trait_item);
                 hir_visit::walk_trait_item(cx, trait_item);
@@ -1055,7 +784,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
-        self.with_lint_attrs(&impl_item.attrs, |cx| {
+        self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| {
             cx.with_param_env(impl_item.id, |cx| {
                 run_lints!(cx, check_impl_item, late_passes, impl_item);
                 hir_visit::walk_impl_item(cx, impl_item);
@@ -1080,14 +809,13 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
     }
 
     fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) {
-        check_lint_name_attribute(self, attr);
         run_lints!(self, check_attribute, late_passes, attr);
     }
 }
 
 impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     fn visit_item(&mut self, it: &'a ast::Item) {
-        self.with_lint_attrs(&it.attrs, |cx| {
+        self.with_lint_attrs(it.id, &it.attrs, |cx| {
             run_lints!(cx, check_item, early_passes, it);
             ast_visit::walk_item(cx, it);
             run_lints!(cx, check_item_post, early_passes, it);
@@ -1095,7 +823,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     }
 
     fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) {
-        self.with_lint_attrs(&it.attrs, |cx| {
+        self.with_lint_attrs(it.id, &it.attrs, |cx| {
             run_lints!(cx, check_foreign_item, early_passes, it);
             ast_visit::walk_foreign_item(cx, it);
             run_lints!(cx, check_foreign_item_post, early_passes, it);
@@ -1104,11 +832,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_pat(&mut self, p: &'a ast::Pat) {
         run_lints!(self, check_pat, early_passes, p);
+        self.check_id(p.id);
         ast_visit::walk_pat(self, p);
     }
 
     fn visit_expr(&mut self, e: &'a ast::Expr) {
-        self.with_lint_attrs(&e.attrs, |cx| {
+        self.with_lint_attrs(e.id, &e.attrs, |cx| {
             run_lints!(cx, check_expr, early_passes, e);
             ast_visit::walk_expr(cx, e);
         })
@@ -1116,12 +845,14 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_stmt(&mut self, s: &'a ast::Stmt) {
         run_lints!(self, check_stmt, early_passes, s);
+        self.check_id(s.id);
         ast_visit::walk_stmt(self, s);
     }
 
     fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, decl: &'a ast::FnDecl,
                 span: Span, id: ast::NodeId) {
         run_lints!(self, check_fn, early_passes, fk, decl, span, id);
+        self.check_id(id);
         ast_visit::walk_fn(self, fk, decl, span);
         run_lints!(self, check_fn_post, early_passes, fk, decl, span, id);
     }
@@ -1133,19 +864,20 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
                         item_id: ast::NodeId,
                         _: Span) {
         run_lints!(self, check_struct_def, early_passes, s, ident, g, item_id);
+        self.check_id(s.id());
         ast_visit::walk_struct_def(self, s);
         run_lints!(self, check_struct_def_post, early_passes, s, ident, g, item_id);
     }
 
     fn visit_struct_field(&mut self, s: &'a ast::StructField) {
-        self.with_lint_attrs(&s.attrs, |cx| {
+        self.with_lint_attrs(s.id, &s.attrs, |cx| {
             run_lints!(cx, check_struct_field, early_passes, s);
             ast_visit::walk_struct_field(cx, s);
         })
     }
 
     fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) {
-        self.with_lint_attrs(&v.node.attrs, |cx| {
+        self.with_lint_attrs(item_id, &v.node.attrs, |cx| {
             run_lints!(cx, check_variant, early_passes, v, g);
             ast_visit::walk_variant(cx, v, g, item_id);
             run_lints!(cx, check_variant_post, early_passes, v, g);
@@ -1154,6 +886,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_ty(&mut self, t: &'a ast::Ty) {
         run_lints!(self, check_ty, early_passes, t);
+        self.check_id(t.id);
         ast_visit::walk_ty(self, t);
     }
 
@@ -1163,12 +896,13 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
         run_lints!(self, check_mod, early_passes, m, s, n);
+        self.check_id(n);
         ast_visit::walk_mod(self, m);
         run_lints!(self, check_mod_post, early_passes, m, s, n);
     }
 
     fn visit_local(&mut self, l: &'a ast::Local) {
-        self.with_lint_attrs(&l.attrs, |cx| {
+        self.with_lint_attrs(l.id, &l.attrs, |cx| {
             run_lints!(cx, check_local, early_passes, l);
             ast_visit::walk_local(cx, l);
         })
@@ -1176,6 +910,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_block(&mut self, b: &'a ast::Block) {
         run_lints!(self, check_block, early_passes, b);
+        self.check_id(b.id);
         ast_visit::walk_block(self, b);
         run_lints!(self, check_block_post, early_passes, b);
     }
@@ -1195,7 +930,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     }
 
     fn visit_trait_item(&mut self, trait_item: &'a ast::TraitItem) {
-        self.with_lint_attrs(&trait_item.attrs, |cx| {
+        self.with_lint_attrs(trait_item.id, &trait_item.attrs, |cx| {
             run_lints!(cx, check_trait_item, early_passes, trait_item);
             ast_visit::walk_trait_item(cx, trait_item);
             run_lints!(cx, check_trait_item_post, early_passes, trait_item);
@@ -1203,7 +938,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     }
 
     fn visit_impl_item(&mut self, impl_item: &'a ast::ImplItem) {
-        self.with_lint_attrs(&impl_item.attrs, |cx| {
+        self.with_lint_attrs(impl_item.id, &impl_item.attrs, |cx| {
             run_lints!(cx, check_impl_item, early_passes, impl_item);
             ast_visit::walk_impl_item(cx, impl_item);
             run_lints!(cx, check_impl_item_post, early_passes, impl_item);
@@ -1212,6 +947,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
         run_lints!(self, check_lifetime, early_passes, lt);
+        self.check_id(lt.id);
     }
 
     fn visit_lifetime_def(&mut self, lt: &'a ast::LifetimeDef) {
@@ -1220,11 +956,13 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
 
     fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) {
         run_lints!(self, check_path, early_passes, p, id);
+        self.check_id(id);
         ast_visit::walk_path(self, p);
     }
 
     fn visit_path_list_item(&mut self, prefix: &'a ast::Path, item: &'a ast::PathListItem) {
         run_lints!(self, check_path_list_item, early_passes, item);
+        self.check_id(item.node.id);
         ast_visit::walk_path_list_item(self, prefix, item);
     }
 
@@ -1233,110 +971,7 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
     }
 
     fn visit_mac_def(&mut self, _mac: &'a ast::MacroDef, id: ast::NodeId) {
-        let lints = self.sess.lints.borrow_mut().take(id);
-        for early_lint in lints {
-            self.early_lint(&early_lint);
-        }
-    }
-}
-
-enum CheckLintNameResult {
-    Ok,
-    // Lint doesn't exist
-    NoLint,
-    // The lint is either renamed or removed. This is the warning
-    // message.
-    Warning(String),
-}
-
-/// Checks the name of a lint for its existence, and whether it was
-/// renamed or removed. Generates a DiagnosticBuilder containing a
-/// warning for renamed and removed lints. This is over both lint
-/// names from attributes and those passed on the command line. Since
-/// it emits non-fatal warnings and there are *two* lint passes that
-/// inspect attributes, this is only run from the late pass to avoid
-/// printing duplicate warnings.
-fn check_lint_name(lint_cx: &LintStore,
-                   lint_name: &str) -> CheckLintNameResult {
-    match lint_cx.by_name.get(lint_name) {
-        Some(&Renamed(ref new_name, _)) => {
-            CheckLintNameResult::Warning(
-                format!("lint {} has been renamed to {}", lint_name, new_name)
-            )
-        },
-        Some(&Removed(ref reason)) => {
-            CheckLintNameResult::Warning(
-                format!("lint {} has been removed: {}", lint_name, reason)
-            )
-        },
-        None => {
-            match lint_cx.lint_groups.get(lint_name) {
-                None => {
-                    CheckLintNameResult::NoLint
-                }
-                Some(_) => {
-                    /* lint group exists */
-                    CheckLintNameResult::Ok
-                }
-            }
-        }
-        Some(_) => {
-            /* lint exists */
-            CheckLintNameResult::Ok
-        }
-    }
-}
-
-// Checks the validity of lint names derived from attributes
-fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) {
-    for result in gather_attr(attr) {
-        match result {
-            Err(_) => {
-                // Malformed lint attr. Reported by with_lint_attrs
-                continue;
-            }
-            Ok((lint_name, _, span)) => {
-                match check_lint_name(&cx.lint_sess.lints, &lint_name.as_str()) {
-                    CheckLintNameResult::Ok => (),
-                    CheckLintNameResult::Warning(ref msg) => {
-                        cx.span_lint(builtin::RENAMED_AND_REMOVED_LINTS,
-                                     span, msg);
-                    }
-                    CheckLintNameResult::NoLint => {
-                        cx.span_lint(builtin::UNKNOWN_LINTS, span,
-                                     &format!("unknown lint: `{}`",
-                                              lint_name));
-                    }
-                }
-            }
-        }
-    }
-}
-
-// Checks the validity of lint names derived from the command line
-fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
-                           lint_name: &str, level: Level) {
-    let db = match check_lint_name(lint_cx, lint_name) {
-        CheckLintNameResult::Ok => None,
-        CheckLintNameResult::Warning(ref msg) => {
-            Some(sess.struct_warn(msg))
-        },
-        CheckLintNameResult::NoLint => {
-            Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
-        }
-    };
-
-    if let Some(mut db) = db {
-        let msg = format!("requested on the command line with `{} {}`",
-                          match level {
-                              Level::Allow => "-A",
-                              Level::Warn => "-W",
-                              Level::Deny => "-D",
-                              Level::Forbid => "-F",
-                          },
-                          lint_name);
-        db.note(&msg);
-        db.emit();
+        self.check_id(id);
     }
 }
 
@@ -1355,10 +990,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         param_env: ty::ParamEnv::empty(Reveal::UserFacing),
         access_levels,
         lint_sess: LintSession::new(&tcx.sess.lint_store),
+        last_ast_node_with_lint_attrs: ast::CRATE_NODE_ID,
     };
 
     // Visit the whole crate.
-    cx.with_lint_attrs(&krate.attrs, |cx| {
+    cx.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |cx| {
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
         run_lints!(cx, check_crate, late_passes, krate);
@@ -1368,16 +1004,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         run_lints!(cx, check_crate_post, late_passes, krate);
     });
 
-    // If we missed any lints added to the session, then there's a bug somewhere
-    // in the iteration code.
-    if let Some((id, v)) = tcx.sess.lints.borrow().get_any() {
-        for early_lint in v {
-            span_bug!(early_lint.diagnostic.span.clone(),
-                      "unprocessed lint {:?} at {}",
-                      early_lint, tcx.hir.node_to_string(*id));
-        }
-    }
-
     // Put the lint store levels and passes back in the session.
     cx.lint_sess.restore(&tcx.sess.lint_store);
 }
@@ -1386,13 +1012,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
     let mut cx = EarlyContext::new(sess, krate);
 
     // Visit the whole crate.
-    cx.with_lint_attrs(&krate.attrs, |cx| {
-        // Lints may be assigned to the whole crate.
-        let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID);
-        for early_lint in lints {
-            cx.early_lint(&early_lint);
-        }
-
+    cx.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |cx| {
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
         run_lints!(cx, check_crate, early_passes, krate);
@@ -1405,11 +1025,11 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
     // Put the lint store levels and passes back in the session.
     cx.lint_sess.restore(&sess.lint_store);
 
-    // If we missed any lints added to the session, then there's a bug somewhere
-    // in the iteration code.
-    for (_, v) in sess.lints.borrow().get_any() {
-        for early_lint in v {
-            span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint);
+    // Emit all buffered lints from early on in the session now that we've
+    // calculated the lint levels for all AST nodes.
+    for (_id, lints) in cx.buffered.map {
+        for early_lint in lints {
+            span_bug!(early_lint.span, "failed to process bufferd lint here");
         }
     }
 }
@@ -1425,8 +1045,13 @@ impl Decodable for LintId {
     fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
         let s = d.read_str()?;
         ty::tls::with(|tcx| {
-            match tcx.sess.lint_store.borrow().find_lint(&s) {
-                Ok(id) => Ok(id),
+            match tcx.sess.lint_store.borrow().find_lints(&s) {
+                Ok(ids) => {
+                    if ids.len() != 0 {
+                        panic!("invalid lint-id `{}`", s);
+                    }
+                    Ok(ids[0])
+                }
                 Err(_) => panic!("invalid lint-id `{}`", s),
             }
         })
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
new file mode 100644
index 00000000000..ab9d4f75597
--- /dev/null
+++ b/src/librustc/lint/levels.rs
@@ -0,0 +1,343 @@
+// 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.
+
+use std::cmp;
+
+use errors::DiagnosticBuilder;
+use hir::HirId;
+use lint::builtin;
+use lint::context::CheckLintNameResult;
+use lint::{self, Lint, LintId, Level, LintSource};
+use session::Session;
+use syntax::ast;
+use syntax::attr;
+use syntax::codemap::MultiSpan;
+use syntax::symbol::Symbol;
+use util::nodemap::FxHashMap;
+
+pub struct LintLevelSets {
+    list: Vec<LintSet>,
+    lint_cap: Level,
+}
+
+enum LintSet {
+    CommandLine {
+        // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+        // flag.
+        specs: FxHashMap<LintId, (Level, LintSource)>,
+    },
+
+    Node {
+        specs: FxHashMap<LintId, (Level, LintSource)>,
+        parent: u32,
+    },
+}
+
+impl LintLevelSets {
+    pub fn new(sess: &Session) -> LintLevelSets {
+        let mut me = LintLevelSets {
+            list: Vec::new(),
+            lint_cap: Level::Forbid,
+        };
+        me.process_command_line(sess);
+        return me
+    }
+
+    pub fn builder(sess: &Session) -> LintLevelsBuilder {
+        LintLevelsBuilder::new(sess, LintLevelSets::new(sess))
+    }
+
+    fn process_command_line(&mut self, sess: &Session) {
+        let store = sess.lint_store.borrow();
+        let mut specs = FxHashMap();
+        self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
+
+        for &(ref lint_name, level) in &sess.opts.lint_opts {
+            store.check_lint_name_cmdline(sess, &lint_name, level);
+
+            // If the cap is less than this specified level, e.g. if we've got
+            // `--cap-lints allow` but we've also got `-D foo` then we ignore
+            // this specification as the lint cap will set it to allow anyway.
+            let level = cmp::min(level, self.lint_cap);
+
+            let lint_flag_val = Symbol::intern(lint_name);
+            let ids = match store.find_lints(&lint_name) {
+                Ok(ids) => ids,
+                Err(_) => continue, // errors handled in check_lint_name_cmdline above
+            };
+            for id in ids {
+                let src = LintSource::CommandLine(lint_flag_val);
+                specs.insert(id, (level, src));
+            }
+        }
+
+        self.list.push(LintSet::CommandLine {
+            specs: specs,
+        });
+    }
+
+    fn get_lint_level(&self, lint: &'static Lint, idx: u32)
+        -> (Level, LintSource)
+    {
+        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx);
+
+        // If `level` is none then we actually assume the default level for this
+        // lint.
+        let mut level = level.unwrap_or(lint.default_level);
+
+        // If we're about to issue a warning, check at the last minute for any
+        // directives against the warnings "lint". If, for example, there's an
+        // `allow(warnings)` in scope then we want to respect that instead.
+        if level == Level::Warn {
+            let (warnings_level, warnings_src) =
+                self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), idx);
+            if let Some(configured_warning_level) = warnings_level {
+                if configured_warning_level != Level::Warn {
+                    level = configured_warning_level;
+                    src = warnings_src;
+                }
+            }
+        }
+
+        // Ensure that we never exceed the `--cap-lints` argument.
+        level = cmp::min(level, self.lint_cap);
+
+        return (level, src)
+    }
+
+    fn get_lint_id_level(&self, id: LintId, mut idx: u32)
+        -> (Option<Level>, LintSource)
+    {
+        loop {
+            match self.list[idx as usize] {
+                LintSet::CommandLine { ref specs } => {
+                    if let Some(&(level, src)) = specs.get(&id) {
+                        return (Some(level), src)
+                    }
+                    return (None, LintSource::Default)
+                }
+                LintSet::Node { ref specs, parent } => {
+                    if let Some(&(level, src)) = specs.get(&id) {
+                        return (Some(level), src)
+                    }
+                    idx = parent;
+                }
+            }
+        }
+    }
+}
+
+pub struct LintLevelsBuilder<'a> {
+    sess: &'a Session,
+    sets: LintLevelSets,
+    id_to_set: FxHashMap<HirId, u32>,
+    cur: u32,
+    warn_about_weird_lints: bool,
+}
+
+pub struct BuilderPush {
+    prev: u32,
+}
+
+impl<'a> LintLevelsBuilder<'a> {
+    pub fn new(sess: &'a Session, sets: LintLevelSets) -> LintLevelsBuilder<'a> {
+        assert_eq!(sets.list.len(), 1);
+        LintLevelsBuilder {
+            sess,
+            sets,
+            cur: 0,
+            id_to_set: FxHashMap(),
+            warn_about_weird_lints: sess.buffered_lints.borrow().is_some(),
+        }
+    }
+
+    /// Pushes a list of AST lint attributes onto this context.
+    ///
+    /// This function will return a `BuilderPush` object which should be be
+    /// passed to `pop` when this scope for the attributes provided is exited.
+    ///
+    /// This function will perform a number of tasks:
+    ///
+    /// * It'll validate all lint-related attributes in `attrs`
+    /// * It'll mark all lint-related attriutes as used
+    /// * Lint levels will be updated based on the attributes provided
+    /// * Lint attributes are validated, e.g. a #[forbid] can't be switched to
+    ///   #[allow]
+    ///
+    /// Don't forget to call `pop`!
+    pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
+        let mut specs = FxHashMap();
+        let store = self.sess.lint_store.borrow();
+        let sess = self.sess;
+        let bad_attr = |span| {
+            span_err!(sess, span, E0452,
+                      "malformed lint attribute");
+        };
+        for attr in attrs {
+            let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) {
+                None => continue,
+                Some(lvl) => lvl,
+            };
+
+            let meta = unwrap_or!(attr.meta(), continue);
+            attr::mark_used(attr);
+
+            let metas = if let Some(metas) = meta.meta_item_list() {
+                metas
+            } else {
+                bad_attr(meta.span);
+                continue
+            };
+
+            for li in metas {
+                let word = match li.word() {
+                    Some(word) => word,
+                    None => {
+                        bad_attr(li.span);
+                        continue
+                    }
+                };
+                let name = word.name();
+                match store.check_lint_name(&name.as_str()) {
+                    CheckLintNameResult::Ok(ids) => {
+                        let src = LintSource::Node(name, li.span);
+                        for id in ids {
+                            specs.insert(*id, (level, src));
+                        }
+                    }
+                    CheckLintNameResult::Warning(ref msg) => {
+                        if self.warn_about_weird_lints {
+                            self.struct_lint(builtin::RENAMED_AND_REMOVED_LINTS,
+                                             Some(li.span.into()),
+                                             msg)
+                                .emit();
+                        }
+                    }
+                    CheckLintNameResult::NoLint => {
+                        if self.warn_about_weird_lints {
+                            self.struct_lint(builtin::UNKNOWN_LINTS,
+                                             Some(li.span.into()),
+                                             &format!("unknown lint: `{}`", name))
+                                .emit();
+                        }
+                    }
+                }
+            }
+        }
+
+        for (id, &(level, ref src)) in specs.iter() {
+            if level == Level::Forbid {
+                continue
+            }
+            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur) {
+                (Some(Level::Forbid), src) => src,
+                _ => continue,
+            };
+            let forbidden_lint_name = match forbid_src {
+                LintSource::Default => id.to_string(),
+                LintSource::Node(name, _) => name.to_string(),
+                LintSource::CommandLine(name) => name.to_string(),
+            };
+            let (lint_attr_name, lint_attr_span) = match *src {
+                LintSource::Node(name, span) => (name, span),
+                _ => continue,
+            };
+            let mut diag_builder = struct_span_err!(self.sess,
+                                                    lint_attr_span,
+                                                    E0453,
+                                                    "{}({}) overruled by outer forbid({})",
+                                                    level.as_str(),
+                                                    lint_attr_name,
+                                                    forbidden_lint_name);
+            diag_builder.span_label(lint_attr_span, "overruled by previous forbid");
+            match forbid_src {
+                LintSource::Default => &mut diag_builder,
+                LintSource::Node(_, forbid_source_span) => {
+                    diag_builder.span_label(forbid_source_span,
+                                            "`forbid` level set here")
+                },
+                LintSource::CommandLine(_) => {
+                    diag_builder.note("`forbid` lint level was set on command line")
+                }
+            }.emit();
+            // don't set a separate error for every lint in the group
+            break
+        }
+
+        let prev = self.cur;
+        if specs.len() > 0 {
+            self.cur = self.sets.list.len() as u32;
+            self.sets.list.push(LintSet::Node {
+                specs: specs,
+                parent: prev,
+            });
+        }
+
+        BuilderPush {
+            prev: prev,
+        }
+    }
+
+    /// Called after `push` when the scope of a set of attributes are exited.
+    pub fn pop(&mut self, push: BuilderPush) {
+        self.cur = push.prev;
+    }
+
+    /// Used to emit a lint-related diagnostic based on the current state of
+    /// this lint context.
+    pub fn struct_lint(&self,
+                       lint: &'static Lint,
+                       span: Option<MultiSpan>,
+                       msg: &str)
+        -> DiagnosticBuilder<'a>
+    {
+        let (level, src) = self.sets.get_lint_level(lint, self.cur);
+        lint::struct_lint_level(self.sess, lint, level, src, span, msg)
+    }
+
+    /// Registers the ID provided with the current set of lints stored in
+    /// this context.
+    pub fn register_id(&mut self, id: HirId) {
+        self.id_to_set.insert(id, self.cur);
+    }
+
+    pub fn build(self) -> LintLevelSets {
+        self.sets
+    }
+
+    pub fn build_map(self) -> LintLevelMap {
+        LintLevelMap {
+            sets: self.sets,
+            id_to_set: self.id_to_set,
+        }
+    }
+}
+
+pub struct LintLevelMap {
+    sets: LintLevelSets,
+    id_to_set: FxHashMap<HirId, u32>,
+}
+
+impl LintLevelMap {
+    /// If the `id` was previously registered with `register_id` when building
+    /// this `LintLevelMap` this returns the corresponding lint level and source
+    /// of the lint level for the lint provided.
+    ///
+    /// If the `id` was not previously registered, returns `None`. If `None` is
+    /// returned then the parent of `id` should be acquired and this function
+    /// should be called again.
+    pub fn level_and_source(&self, lint: &'static Lint, id: HirId)
+        -> Option<(Level, LintSource)>
+    {
+        self.id_to_set.get(&id).map(|idx| {
+            self.sets.get_lint_level(lint, *idx)
+        })
+    }
+}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index f9222ac9400..c64e1c08082 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -31,20 +31,27 @@
 pub use self::Level::*;
 pub use self::LintSource::*;
 
+use std::rc::Rc;
+
+use errors::DiagnosticBuilder;
+use hir::def_id::{CrateNum, LOCAL_CRATE};
+use hir::intravisit::{self, FnKind};
 use hir;
-use hir::intravisit::FnKind;
-use std::hash;
+use session::Session;
 use std::ascii::AsciiExt;
-use syntax_pos::Span;
-use syntax::visit as ast_visit;
+use std::hash;
 use syntax::ast;
+use syntax::codemap::MultiSpan;
 use syntax::symbol::Symbol;
+use syntax::visit as ast_visit;
+use syntax_pos::Span;
+use ty::TyCtxt;
+use ty::maps::Providers;
+use util::nodemap::NodeMap;
 
 pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
-                        raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
-                        raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint};
-
-pub use lint::table::LintTable;
+                        check_crate, check_ast_crate,
+                        FutureIncompatibleInfo, BufferedEarlyLint};
 
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
@@ -351,4 +358,215 @@ pub type LevelSource = (Level, LintSource);
 
 pub mod builtin;
 mod context;
-mod table;
+mod levels;
+
+pub use self::levels::{LintLevelSets, LintLevelMap};
+
+pub struct LintBuffer {
+    map: NodeMap<Vec<BufferedEarlyLint>>,
+}
+
+impl LintBuffer {
+    pub fn new() -> LintBuffer {
+        LintBuffer { map: NodeMap() }
+    }
+
+    pub fn add_lint(&mut self,
+                    lint: &'static Lint,
+                    id: ast::NodeId,
+                    sp: MultiSpan,
+                    msg: &str) {
+        let early_lint = BufferedEarlyLint {
+            lint_id: LintId::of(lint),
+            ast_id: id,
+            span: sp,
+            msg: msg.to_string(),
+        };
+        let arr = self.map.entry(id).or_insert(Vec::new());
+        if !arr.contains(&early_lint) {
+            arr.push(early_lint);
+        }
+    }
+
+    pub fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> {
+        self.map.remove(&id).unwrap_or(Vec::new())
+    }
+
+    pub fn get_any(&self) -> Option<&[BufferedEarlyLint]> {
+        let key = self.map.keys().next().map(|k| *k);
+        key.map(|k| &self.map[&k][..])
+    }
+}
+
+pub fn struct_lint_level<'a>(sess: &'a Session,
+                             lint: &'static Lint,
+                             level: Level,
+                             src: LintSource,
+                             span: Option<MultiSpan>,
+                             msg: &str)
+    -> DiagnosticBuilder<'a>
+{
+    let mut err = match (level, span) {
+        (Level::Allow, _) => return sess.diagnostic().struct_dummy(),
+        (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg),
+        (Level::Warn, None) => sess.struct_warn(msg),
+        (Level::Deny, Some(span)) |
+        (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg),
+        (Level::Deny, None) |
+        (Level::Forbid, None) => sess.struct_err(msg),
+    };
+
+    let name = lint.name_lower();
+    match src {
+        LintSource::Default => {
+            sess.diag_note_once(
+                &mut err,
+                lint,
+                &format!("#[{}({})] on by default", level.as_str(), name));
+        }
+        LintSource::CommandLine(lint_flag_val) => {
+            let flag = match level {
+                Level::Warn => "-W",
+                Level::Deny => "-D",
+                Level::Forbid => "-F",
+                Level::Allow => panic!(),
+            };
+            let hyphen_case_lint_name = name.replace("_", "-");
+            if lint_flag_val.as_str() == name {
+                sess.diag_note_once(
+                    &mut err,
+                    lint,
+                    &format!("requested on the command line with `{} {}`",
+                             flag, hyphen_case_lint_name));
+            } else {
+                let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
+                sess.diag_note_once(
+                    &mut err,
+                    lint,
+                    &format!("`{} {}` implied by `{} {}`",
+                             flag, hyphen_case_lint_name, flag,
+                             hyphen_case_flag_val));
+            }
+        }
+        LintSource::Node(lint_attr_name, src) => {
+            sess.diag_span_note_once(&mut err, lint, src, "lint level defined here");
+            if lint_attr_name.as_str() != name {
+                let level_str = level.as_str();
+                sess.diag_note_once(&mut err, lint,
+                                    &format!("#[{}({})] implied by #[{}({})]",
+                                             level_str, name, level_str, lint_attr_name));
+            }
+        }
+    }
+
+    // Check for future incompatibility lints and issue a stronger warning.
+    let lints = sess.lint_store.borrow();
+    if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
+        let explanation = format!("this was previously accepted by the compiler \
+                                   but is being phased out; \
+                                   it will become a hard error in a future release!");
+        let citation = format!("for more information, see {}",
+                               future_incompatible.reference);
+        err.warn(&explanation);
+        err.note(&citation);
+    }
+
+    return err
+}
+
+fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
+    -> Rc<LintLevelMap>
+{
+    assert_eq!(cnum, LOCAL_CRATE);
+    let mut builder = LintLevelMapBuilder {
+        levels: LintLevelSets::builder(tcx.sess),
+        tcx: tcx,
+    };
+    let krate = tcx.hir.krate();
+
+    builder.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |builder| {
+        intravisit::walk_crate(builder, krate);
+    });
+
+    Rc::new(builder.levels.build_map())
+}
+
+struct LintLevelMapBuilder<'a, 'tcx: 'a> {
+    levels: levels::LintLevelsBuilder<'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> {
+    fn with_lint_attrs<F>(&mut self,
+                          id: ast::NodeId,
+                          attrs: &[ast::Attribute],
+                          f: F)
+        where F: FnOnce(&mut Self)
+    {
+        let push = self.levels.push(attrs);
+        self.levels.register_id(self.tcx.hir.definitions().node_to_hir_id(id));
+        f(self);
+        self.levels.pop(push);
+    }
+}
+
+impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+        intravisit::NestedVisitorMap::All(&self.tcx.hir)
+    }
+
+    fn visit_item(&mut self, it: &'tcx hir::Item) {
+        self.with_lint_attrs(it.id, &it.attrs, |builder| {
+            intravisit::walk_item(builder, it);
+        });
+    }
+
+    fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) {
+        self.with_lint_attrs(it.id, &it.attrs, |builder| {
+            intravisit::walk_foreign_item(builder, it);
+        })
+    }
+
+    fn visit_expr(&mut self, e: &'tcx hir::Expr) {
+        self.with_lint_attrs(e.id, &e.attrs, |builder| {
+            intravisit::walk_expr(builder, e);
+        })
+    }
+
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+        self.with_lint_attrs(s.id, &s.attrs, |builder| {
+            intravisit::walk_struct_field(builder, s);
+        })
+    }
+
+    fn visit_variant(&mut self,
+                     v: &'tcx hir::Variant,
+                     g: &'tcx hir::Generics,
+                     item_id: ast::NodeId) {
+        self.with_lint_attrs(v.node.data.id(), &v.node.attrs, |builder| {
+            intravisit::walk_variant(builder, v, g, item_id);
+        })
+    }
+
+    fn visit_local(&mut self, l: &'tcx hir::Local) {
+        self.with_lint_attrs(l.id, &l.attrs, |builder| {
+            intravisit::walk_local(builder, l);
+        })
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.with_lint_attrs(trait_item.id, &trait_item.attrs, |builder| {
+            intravisit::walk_trait_item(builder, trait_item);
+        });
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        self.with_lint_attrs(impl_item.id, &impl_item.attrs, |builder| {
+            intravisit::walk_impl_item(builder, impl_item);
+        });
+    }
+}
+
+pub fn provide(providers: &mut Providers) {
+    providers.lint_levels = lint_levels;
+}
diff --git a/src/librustc/lint/table.rs b/src/librustc/lint/table.rs
deleted file mode 100644
index f2dab25229a..00000000000
--- a/src/librustc/lint/table.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2012-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 syntax::ast;
-use syntax_pos::MultiSpan;
-use util::nodemap::NodeMap;
-
-use super::{Lint, LintId, EarlyLint, IntoEarlyLint};
-
-#[derive(RustcEncodable, RustcDecodable)]
-pub struct LintTable {
-    map: NodeMap<Vec<EarlyLint>>
-}
-
-impl LintTable {
-    pub fn new() -> Self {
-        LintTable { map: NodeMap() }
-    }
-
-    pub fn add_lint<S: Into<MultiSpan>>(&mut self,
-                                        lint: &'static Lint,
-                                        id: ast::NodeId,
-                                        sp: S,
-                                        msg: String)
-    {
-        self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
-    }
-
-    pub fn add_lint_diagnostic<M>(&mut self,
-                                  lint: &'static Lint,
-                                  id: ast::NodeId,
-                                  msg: M)
-        where M: IntoEarlyLint,
-    {
-        let lint_id = LintId::of(lint);
-        let early_lint = msg.into_early_lint(lint_id);
-        let arr = self.map.entry(id).or_insert(vec![]);
-        if !arr.contains(&early_lint) {
-            arr.push(early_lint);
-        }
-    }
-
-    pub fn get(&self, id: ast::NodeId) -> &[EarlyLint] {
-        self.map.get(&id).map(|v| &v[..]).unwrap_or(&[])
-    }
-
-    pub fn take(&mut self, id: ast::NodeId) -> Vec<EarlyLint> {
-        self.map.remove(&id).unwrap_or(vec![])
-    }
-
-    pub fn transfer(&mut self, into: &mut LintTable) {
-        into.map.extend(self.map.drain());
-    }
-
-    /// Returns the first (id, lint) pair that is non-empty. Used to
-    /// implement a sanity check in lints that all node-ids are
-    /// visited.
-    pub fn get_any(&self) -> Option<(&ast::NodeId, &Vec<EarlyLint>)> {
-        self.map.iter()
-                .filter(|&(_, v)| !v.is_empty())
-                .next()
-    }
-}
-
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index a525b4e13b7..4e08bc90c7c 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -17,11 +17,11 @@ use hir::{self, Item_, PatKind};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::itemlikevisit::ItemLikeVisitor;
 
-use middle::privacy;
-use ty::{self, TyCtxt};
 use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use lint;
+use middle::privacy;
+use ty::{self, TyCtxt};
 use util::nodemap::FxHashSet;
 
 use syntax::{ast, codemap};
@@ -299,7 +299,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
     }
 }
 
-fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
+fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt,
+                                    id: ast::NodeId,
+                                    attrs: &[ast::Attribute]) -> bool {
     if attr::contains_name(attrs, "lang") {
         return true;
     }
@@ -315,14 +317,7 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
         return true;
     }
 
-    let dead_code = lint::builtin::DEAD_CODE.name_lower();
-    for attr in lint::gather_attrs(attrs) {
-        match attr {
-            Ok((name, lint::Allow, _)) if name == &*dead_code => return true,
-            _ => (),
-        }
-    }
-    false
+    tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow
 }
 
 // This visitor seeds items that
@@ -338,14 +333,17 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
 //   or
 //   2) We are not sure to be live or not
 //     * Implementation of a trait method
-struct LifeSeeder<'k> {
+struct LifeSeeder<'k, 'tcx: 'k> {
     worklist: Vec<ast::NodeId>,
     krate: &'k hir::Crate,
+    tcx: TyCtxt<'k, 'tcx, 'tcx>,
 }
 
-impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> {
+impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
-        let allow_dead_code = has_allow_dead_code_or_lang_attr(&item.attrs);
+        let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx,
+                                                               item.id,
+                                                               &item.attrs);
         if allow_dead_code {
             self.worklist.push(item.id);
         }
@@ -360,7 +358,9 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> {
                     match trait_item.node {
                         hir::TraitItemKind::Const(_, Some(_)) |
                         hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
-                            if has_allow_dead_code_or_lang_attr(&trait_item.attrs) {
+                            if has_allow_dead_code_or_lang_attr(self.tcx,
+                                                                trait_item.id,
+                                                                &trait_item.attrs) {
                                 self.worklist.push(trait_item.id);
                             }
                         }
@@ -372,7 +372,9 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> {
                 for impl_item_ref in impl_item_refs {
                     let impl_item = self.krate.impl_item(impl_item_ref.id);
                     if opt_trait.is_some() ||
-                            has_allow_dead_code_or_lang_attr(&impl_item.attrs) {
+                            has_allow_dead_code_or_lang_attr(self.tcx,
+                                                             impl_item.id,
+                                                             &impl_item.attrs) {
                         self.worklist.push(impl_item_ref.id.node_id);
                     }
                 }
@@ -408,6 +410,7 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut life_seeder = LifeSeeder {
         worklist,
         krate,
+        tcx,
     };
     krate.visit_all_item_likes(&mut life_seeder);
 
@@ -472,17 +475,19 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
         !field.is_positional()
             && !self.symbol_is_live(field.id, None)
             && !is_marker_field
-            && !has_allow_dead_code_or_lang_attr(&field.attrs)
+            && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs)
     }
 
     fn should_warn_about_variant(&mut self, variant: &hir::Variant_) -> bool {
         !self.symbol_is_live(variant.data.id(), None)
-            && !has_allow_dead_code_or_lang_attr(&variant.attrs)
+            && !has_allow_dead_code_or_lang_attr(self.tcx,
+                                                 variant.data.id(),
+                                                 &variant.attrs)
     }
 
     fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool {
         !self.symbol_is_live(fi.id, None)
-            && !has_allow_dead_code_or_lang_attr(&fi.attrs)
+            && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs)
     }
 
     // id := node id of an item's definition.
@@ -528,11 +533,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
                       node_type: &str) {
         if !name.as_str().starts_with("_") {
             self.tcx
-                .sess
-                .add_lint(lint::builtin::DEAD_CODE,
-                          id,
-                          span,
-                          format!("{} is never used: `{}`", node_type, name));
+                .lint_node(lint::builtin::DEAD_CODE,
+                           id,
+                           span,
+                           &format!("{} is never used: `{}`", node_type, name));
         }
     }
 }
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index abd5cbcb89e..fcf366788b2 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -56,11 +56,11 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
         match self.unsafe_context.root {
             SafeContext => {
                 if is_lint {
-                    self.tcx.sess.add_lint(lint::builtin::SAFE_EXTERN_STATICS,
-                                           node_id,
-                                           span,
-                                           format!("{} requires unsafe function or \
-                                                    block (error E0133)", description));
+                    self.tcx.lint_node(lint::builtin::SAFE_EXTERN_STATICS,
+                                       node_id,
+                                       span,
+                                       &format!("{} requires unsafe function or \
+                                                 block (error E0133)", description));
                 } else {
                     // Report an error.
                     struct_span_err!(
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index abb75c96c10..a432e49dbaf 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1487,12 +1487,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 };
 
                 if is_assigned {
-                    self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp,
-                        format!("variable `{}` is assigned to, but never used",
-                                name));
+                    self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp,
+                        &format!("variable `{}` is assigned to, but never used",
+                                 name));
                 } else if name != "self" {
-                    self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_VARIABLES, id, sp,
-                        format!("unused variable: `{}`", name));
+                    self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp,
+                        &format!("unused variable: `{}`", name));
                 }
             }
             true
@@ -1514,11 +1514,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn report_dead_assign(&self, id: NodeId, sp: Span, var: Variable, is_argument: bool) {
         if let Some(name) = self.should_warn(var) {
             if is_argument {
-                self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
-                    format!("value passed to `{}` is never read", name));
+                self.ir.tcx.lint_node(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
+                    &format!("value passed to `{}` is never read", name));
             } else {
-                self.ir.tcx.sess.add_lint(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
-                    format!("value assigned to `{}` is never read", name));
+                self.ir.tcx.lint_node(lint::builtin::UNUSED_ASSIGNMENTS, id, sp,
+                    &format!("value assigned to `{}` is never read", name));
             }
         }
     }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 68c01db544a..5158c7e94af 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -493,7 +493,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 format!("use of deprecated item")
             };
 
-            self.sess.add_lint(lint::builtin::DEPRECATED, id, span, msg);
+            self.lint_node(lint::builtin::DEPRECATED, id, span, &msg);
         };
 
         // Deprecated attributes apply in-crate and cross-crate.
@@ -737,10 +737,10 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features {
         let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str())
             .expect("unexpectedly couldn't find version feature was stabilized");
-        sess.add_lint(lint::builtin::STABLE_FEATURES,
+        tcx.lint_node(lint::builtin::STABLE_FEATURES,
                       ast::CRATE_NODE_ID,
                       span,
-                      format_stable_since_msg(version));
+                      &format_stable_since_msg(version));
     }
 
     let index = tcx.stability.borrow();
@@ -748,10 +748,10 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         match remaining_lib_features.remove(used_lib_feature) {
             Some(span) => {
                 if let &attr::StabilityLevel::Stable { since: ref version } = level {
-                    sess.add_lint(lint::builtin::STABLE_FEATURES,
+                    tcx.lint_node(lint::builtin::STABLE_FEATURES,
                                   ast::CRATE_NODE_ID,
                                   span,
-                                  format_stable_since_msg(&version.as_str()));
+                                  &format_stable_since_msg(&version.as_str()));
                 }
             }
             None => ( /* used but undeclared, handled during the previous ast visit */ )
@@ -759,9 +759,9 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     }
 
     for &span in remaining_lib_features.values() {
-        sess.add_lint(lint::builtin::UNUSED_FEATURES,
+        tcx.lint_node(lint::builtin::UNUSED_FEATURES,
                       ast::CRATE_NODE_ID,
                       span,
-                      "unused or unknown feature".to_string());
+                      "unused or unknown feature");
     }
 }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index fe6b24f3e1f..be39f95b988 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -79,7 +79,7 @@ pub struct Session {
     // if the value stored here has been affected by path remapping.
     pub working_dir: (String, bool),
     pub lint_store: RefCell<lint::LintStore>,
-    pub lints: RefCell<lint::LintTable>,
+    pub buffered_lints: RefCell<Option<lint::LintBuffer>>,
     /// Set of (LintId, Option<Span>, message) tuples tracking lint
     /// (sub)diagnostics that have been set once, but should not be set again,
     /// in order to avoid redundantly verbose output (Issue #24690).
@@ -307,22 +307,15 @@ impl Session {
         self.diagnostic().unimpl(msg)
     }
 
-    pub fn add_lint<S: Into<MultiSpan>>(&self,
-                                        lint: &'static lint::Lint,
-                                        id: ast::NodeId,
-                                        sp: S,
-                                        msg: String)
-    {
-        self.lints.borrow_mut().add_lint(lint, id, sp, msg);
-    }
-
-    pub fn add_lint_diagnostic<M>(&self,
-                                  lint: &'static lint::Lint,
-                                  id: ast::NodeId,
-                                  msg: M)
-        where M: lint::IntoEarlyLint,
-    {
-        self.lints.borrow_mut().add_lint_diagnostic(lint, id, msg);
+    pub fn buffer_lint<S: Into<MultiSpan>>(&self,
+                                           lint: &'static lint::Lint,
+                                           id: ast::NodeId,
+                                           sp: S,
+                                           msg: &str) {
+        match *self.buffered_lints.borrow_mut() {
+            Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg),
+            None => bug!("can't buffer lints after HIR lowering"),
+        }
     }
 
     pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId {
@@ -708,7 +701,7 @@ pub fn build_session_(sopts: config::Options,
         local_crate_source_file,
         working_dir,
         lint_store: RefCell::new(lint::LintStore::new()),
-        lints: RefCell::new(lint::LintTable::new()),
+        buffered_lints: RefCell::new(Some(lint::LintBuffer::new())),
         one_time_diagnostics: RefCell::new(FxHashSet()),
         plugin_llvm_passes: RefCell::new(Vec::new()),
         plugin_attributes: RefCell::new(Vec::new()),
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 52484059138..e4042c48bf3 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -279,8 +279,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         let mut self_match_impls = vec![];
         let mut fuzzy_match_impls = vec![];
 
-        self.tcx.trait_def(trait_ref.def_id)
-            .for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
+        self.tcx.for_each_relevant_impl(
+            trait_ref.def_id, trait_self_ty, |def_id| {
                 let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
                 let impl_trait_ref = tcx
                     .impl_trait_ref(def_id)
@@ -397,10 +397,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                               trait_ref.skip_binder().self_ty(),
                                               true);
         let mut impl_candidates = Vec::new();
-        let trait_def = self.tcx.trait_def(trait_ref.def_id());
 
         match simp {
-            Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| {
+            Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
                 let imp = self.tcx.impl_trait_ref(def_id).unwrap();
                 let imp_simp = fast_reject::simplify_type(self.tcx,
                                                           imp.self_ty(),
@@ -412,7 +411,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 }
                 impl_candidates.push(imp);
             }),
-            None => trait_def.for_each_impl(self.tcx, |def_id| {
+            None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
                 impl_candidates.push(
                     self.tcx.impl_trait_ref(def_id).unwrap());
             })
@@ -501,11 +500,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // weird effect -- the diagnostic is reported as a lint, and
         // the builder which is returned is marked as canceled.
 
-        let mut err =
-            struct_span_err!(self.tcx.sess,
-                             error_span,
-                             E0276,
-                             "impl has stricter requirements than trait");
+        let msg = "impl has stricter requirements than trait";
+        let mut err = match lint_id {
+            Some(node_id) => {
+                self.tcx.struct_span_lint_node(EXTRA_REQUIREMENT_IN_IMPL,
+                                               node_id,
+                                               error_span,
+                                               msg)
+            }
+            None => {
+                struct_span_err!(self.tcx.sess,
+                                 error_span,
+                                 E0276,
+                                 "{}", msg)
+            }
+        };
 
         if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) {
             let span = self.tcx.sess.codemap().def_span(trait_item_span);
@@ -516,13 +525,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             error_span,
             format!("impl has extra requirement {}", requirement));
 
-        if let Some(node_id) = lint_id {
-            self.tcx.sess.add_lint_diagnostic(EXTRA_REQUIREMENT_IN_IMPL,
-                                              node_id,
-                                              (*err).clone());
-            err.cancel();
-        }
-
         err
     }
 
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index e13e25250a1..67c7ecda649 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -572,7 +572,7 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 {
     debug!("fully_normalize(value={:?})", value);
 
-    let mut selcx = &mut SelectionContext::new(infcx);
+    let selcx = &mut SelectionContext::new(infcx);
     // FIXME (@jroesch) ISSUE 26721
     // I'm not sure if this is a bug or not, needs further investigation.
     // It appears that by reusing the fulfillment_cx here we incur more
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 52c8b67278e..2e2daeb9845 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -504,7 +504,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| {
                 // Swap out () with ! so we can check if the trait is impld for !
                 {
-                    let mut trait_ref = &mut trait_pred.trait_ref;
+                    let trait_ref = &mut trait_pred.trait_ref;
                     let unit_substs = trait_ref.substs;
                     let mut never_substs = Vec::with_capacity(unit_substs.len());
                     never_substs.push(From::from(tcx.types.never));
@@ -522,11 +522,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             if raise_warning {
-                tcx.sess.add_lint(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
-                                  obligation.cause.body_id,
-                                  obligation.cause.span,
-                                  format!("code relies on type inference rules which are likely \
-                                           to change"));
+                tcx.lint_node(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
+                              obligation.cause.body_id,
+                              obligation.cause.span,
+                              &format!("code relies on type inference rules which are likely \
+                                        to change"));
             }
         }
         Ok(ret)
@@ -1619,10 +1619,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     {
         debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
 
-        let def = self.tcx().trait_def(obligation.predicate.def_id());
-
-        def.for_each_relevant_impl(
-            self.tcx(),
+        self.tcx().for_each_relevant_impl(
+            obligation.predicate.def_id(),
             obligation.predicate.0.trait_ref.self_ty(),
             |impl_def_id| {
                 self.probe(|this, snapshot| { /* [1] */
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 46e55102966..7c916e162a4 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -300,7 +300,8 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
                                                       -> Rc<specialization_graph::Graph> {
     let mut sg = specialization_graph::Graph::new();
 
-    let mut trait_impls: Vec<DefId> = tcx.trait_impls_of(trait_id).iter().collect();
+    let mut trait_impls = Vec::new();
+    tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did));
 
     // The coherence checking implementation seems to rely on impls being
     // iterated over (roughly) in definition order, so we are sorting by
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 0c79b2f23b9..c2c52e5fa21 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -11,14 +11,15 @@
 //! type context book-keeping
 
 use dep_graph::DepGraph;
+use errors::DiagnosticBuilder;
 use session::Session;
-use lint;
 use middle;
 use hir::TraitMap;
 use hir::def::{Def, ExportMap};
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::map as hir_map;
 use hir::map::DefPathHash;
+use lint::{self, Lint};
 use middle::free_region::FreeRegionMap;
 use middle::lang_items;
 use middle::resolve_lifetime;
@@ -58,6 +59,7 @@ use std::rc::Rc;
 use syntax::abi;
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
+use syntax::codemap::MultiSpan;
 use syntax::symbol::{Symbol, keywords};
 use syntax_pos::Span;
 
@@ -258,9 +260,6 @@ pub struct TypeckTables<'tcx> {
     /// *from* expression of the cast, not the cast itself.
     pub cast_kinds: NodeMap<ty::cast::CastKind>,
 
-    /// Lints for the body of this fn generated by typeck.
-    pub lints: lint::LintTable,
-
     /// Set of trait imports actually used in the method resolution.
     /// This is used for warning unused imports.
     pub used_trait_imports: DefIdSet,
@@ -291,7 +290,6 @@ impl<'tcx> TypeckTables<'tcx> {
             liberated_fn_sigs: NodeMap(),
             fru_field_types: NodeMap(),
             cast_kinds: NodeMap(),
-            lints: lint::LintTable::new(),
             used_trait_imports: DefIdSet(),
             tainted_by_errors: false,
             free_region_map: FreeRegionMap::new(),
@@ -1529,6 +1527,59 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
     }
+
+    pub fn lint_node<S: Into<MultiSpan>>(self,
+                                         lint: &'static Lint,
+                                         id: NodeId,
+                                         span: S,
+                                         msg: &str) {
+        self.struct_span_lint_node(lint, id, span.into(), msg).emit()
+    }
+
+    pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
+        -> (lint::Level, lint::LintSource)
+    {
+        // Right now we insert a `with_ignore` node in the dep graph here to
+        // ignore the fact that `lint_levels` below depends on the entire crate.
+        // For now this'll prevent false positives of recompiling too much when
+        // anything changes.
+        //
+        // Once red/green incremental compilation lands we should be able to
+        // remove this because while the crate changes often the lint level map
+        // will change rarely.
+        self.dep_graph.with_ignore(|| {
+            let sets = self.lint_levels(LOCAL_CRATE);
+            loop {
+                let hir_id = self.hir.definitions().node_to_hir_id(id);
+                if let Some(pair) = sets.level_and_source(lint, hir_id) {
+                    return pair
+                }
+                let next = self.hir.get_parent_node(id);
+                if next == id {
+                    bug!("lint traversal reached the root of the crate");
+                }
+                id = next;
+            }
+        })
+    }
+
+    pub fn struct_span_lint_node<S: Into<MultiSpan>>(self,
+                                                     lint: &'static Lint,
+                                                     id: NodeId,
+                                                     span: S,
+                                                     msg: &str)
+        -> DiagnosticBuilder<'tcx>
+    {
+        let (level, src) = self.lint_level_at_node(lint, id);
+        lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
+    }
+
+    pub fn struct_lint_node(self, lint: &'static Lint, id: NodeId, msg: &str)
+        -> DiagnosticBuilder<'tcx>
+    {
+        let (level, src) = self.lint_level_at_node(lint, id);
+        lint::struct_lint_level(self.sess, lint, level, src, None, msg)
+    }
 }
 
 pub trait InternAs<T: ?Sized, R> {
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 77c863a0123..900197f3dbd 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         match self.sty {
             TyAdt(def, substs) => {
                 {
-                    let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
+                    let substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
                     if !substs_set.insert(substs) {
                         // We are already calculating the inhabitedness of this type.
                         // The type must contain a reference to itself. Break the
@@ -193,7 +193,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                     }
                 }
                 let ret = def.uninhabited_from(visited, tcx, substs);
-                let mut substs_set = visited.get_mut(&def.did).unwrap();
+                let substs_set = visited.get_mut(&def.did).unwrap();
                 substs_set.remove(substs);
                 ret
             },
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 88a2ce0ab8a..b121c05f244 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -12,6 +12,7 @@ use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::def::Def;
 use hir;
+use lint;
 use middle::const_val;
 use middle::cstore::{ExternCrate, LinkagePreference};
 use middle::privacy::AccessLevels;
@@ -470,12 +471,6 @@ impl<'tcx> QueryDescription for queries::trait_impls_of<'tcx> {
     }
 }
 
-impl<'tcx> QueryDescription for queries::relevant_trait_impls_for<'tcx> {
-    fn describe(tcx: TyCtxt, (def_id, ty): (DefId, SimplifiedType)) -> String {
-        format!("relevant impls for: `({}, {:?})`", tcx.item_path_str(def_id), ty)
-    }
-}
-
 impl<'tcx> QueryDescription for queries::is_object_safe<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("determine object safety of trait `{}`", tcx.item_path_str(def_id))
@@ -512,6 +507,12 @@ impl<'tcx> QueryDescription for queries::extern_crate<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription for queries::lint_levels<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("computing the lint levels for items in this crate")
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -977,10 +978,7 @@ define_maps! { <'tcx>
     [] const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
     [] is_mir_available: IsMirAvailable(DefId) -> bool,
 
-    [] trait_impls_of: TraitImpls(DefId) -> ty::trait_def::TraitImpls,
-    // Note that TraitDef::for_each_relevant_impl() will do type simplication for you.
-    [] relevant_trait_impls_for: relevant_trait_impls_for((DefId, SimplifiedType))
-        -> ty::trait_def::TraitImpls,
+    [] trait_impls_of: TraitImpls(DefId) -> Rc<ty::trait_def::TraitImpls>,
     [] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
     [] is_object_safe: ObjectSafety(DefId) -> bool,
 
@@ -1008,6 +1006,8 @@ define_maps! { <'tcx>
     [] is_panic_runtime: IsPanicRuntime(DefId) -> bool,
 
     [] extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
+
+    [] lint_levels: lint_levels(CrateNum) -> Rc<lint::LintLevelMap>,
 }
 
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
@@ -1060,10 +1060,6 @@ fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::CrateVariances
 }
 
-fn relevant_trait_impls_for<'tcx>((def_id, t): (DefId, SimplifiedType)) -> DepConstructor<'tcx> {
-    DepConstructor::RelevantTraitImpls(def_id, t)
-}
-
 fn is_copy_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
     DepConstructor::IsCopy
 }
@@ -1083,3 +1079,7 @@ fn needs_drop_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstruct
 fn layout_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'tcx> {
     DepConstructor::Layout
 }
+
+fn lint_levels<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::LintLevels
+}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 3ac189ae047..b5aea7e33d6 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -494,6 +494,7 @@ impl<'tcx> TyS<'tcx> {
             TypeVariants::TyFnPtr(..) |
             TypeVariants::TyDynamic(..) |
             TypeVariants::TyClosure(..) |
+            TypeVariants::TyInfer(..) |
             TypeVariants::TyProjection(..) => false,
             _ => true,
         }
@@ -2515,7 +2516,6 @@ pub fn provide(providers: &mut ty::maps::Providers) {
         param_env,
         trait_of_item,
         trait_impls_of: trait_def::trait_impls_of_provider,
-        relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
         ..*providers
     };
 }
@@ -2525,7 +2525,6 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
         adt_sized_constraint,
         adt_dtorck_constraint,
         trait_impls_of: trait_def::trait_impls_of_provider,
-        relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
         param_env,
         ..*providers
     };
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index ef6bce8a3d9..9990472c6b4 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use hir;
 use hir::def_id::DefId;
 use hir::map::DefPathHash;
 use traits::specialization_graph;
 use ty::fast_reject;
 use ty::fold::TypeFoldable;
 use ty::{Ty, TyCtxt};
+
+use rustc_data_structures::fx::FxHashMap;
+
 use std::rc::Rc;
-use hir;
 
 /// A trait's definition with type information.
 pub struct TraitDef {
@@ -36,60 +39,12 @@ pub struct TraitDef {
     pub def_path_hash: DefPathHash,
 }
 
-// We don't store the list of impls in a flat list because each cached list of
-// `relevant_impls_for` we would then duplicate all blanket impls. By keeping
-// blanket and non-blanket impls separate, we can share the list of blanket
-// impls.
-#[derive(Clone)]
 pub struct TraitImpls {
-    blanket_impls: Rc<Vec<DefId>>,
-    non_blanket_impls: Rc<Vec<DefId>>,
+    blanket_impls: Vec<DefId>,
+    /// Impls indexed by their simplified self-type, for fast lookup.
+    non_blanket_impls: FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>,
 }
 
-impl TraitImpls {
-    pub fn iter(&self) -> TraitImplsIter {
-        TraitImplsIter {
-            blanket_impls: self.blanket_impls.clone(),
-            non_blanket_impls: self.non_blanket_impls.clone(),
-            index: 0
-        }
-    }
-}
-
-#[derive(Clone)]
-pub struct TraitImplsIter {
-    blanket_impls: Rc<Vec<DefId>>,
-    non_blanket_impls: Rc<Vec<DefId>>,
-    index: usize,
-}
-
-impl Iterator for TraitImplsIter {
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<DefId> {
-        if self.index < self.blanket_impls.len() {
-            let bi_index = self.index;
-            self.index += 1;
-            Some(self.blanket_impls[bi_index])
-        } else {
-            let nbi_index = self.index - self.blanket_impls.len();
-            if nbi_index < self.non_blanket_impls.len() {
-                self.index += 1;
-                Some(self.non_blanket_impls[nbi_index])
-            } else {
-                None
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let items_left = (self.blanket_impls.len() + self.non_blanket_impls.len()) - self.index;
-        (items_left, Some(items_left))
-    }
-}
-
-impl ExactSizeIterator for TraitImplsIter {}
-
 impl<'a, 'gcx, 'tcx> TraitDef {
     pub fn new(def_id: DefId,
                unsafety: hir::Unsafety,
@@ -111,20 +66,36 @@ impl<'a, 'gcx, 'tcx> TraitDef {
                      -> specialization_graph::Ancestors {
         specialization_graph::ancestors(tcx, self.def_id, of_impl)
     }
+}
 
-    pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) {
-        for impl_def_id in tcx.trait_impls_of(self.def_id).iter() {
+impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+    pub fn for_each_impl<F: FnMut(DefId)>(self, def_id: DefId, mut f: F) {
+        let impls = self.trait_impls_of(def_id);
+
+        for &impl_def_id in impls.blanket_impls.iter() {
             f(impl_def_id);
         }
+
+        for v in impls.non_blanket_impls.values() {
+            for &impl_def_id in v {
+                f(impl_def_id);
+            }
+        }
     }
 
     /// Iterate over every impl that could possibly match the
     /// self-type `self_ty`.
-    pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
-                                                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    pub fn for_each_relevant_impl<F: FnMut(DefId)>(self,
+                                                   def_id: DefId,
                                                    self_ty: Ty<'tcx>,
                                                    mut f: F)
     {
+        let impls = self.trait_impls_of(def_id);
+
+        for &impl_def_id in impls.blanket_impls.iter() {
+            f(impl_def_id);
+        }
+
         // simplify_type(.., false) basically replaces type parameters and
         // projections with infer-variables. This is, of course, done on
         // the impl trait-ref when it is instantiated, but not on the
@@ -137,15 +108,31 @@ impl<'a, 'gcx, 'tcx> TraitDef {
         // replace `S` with anything - this impl of course can't be
         // selected, and as there are hundreds of similar impls,
         // considering them would significantly harm performance.
-        let relevant_impls = if let Some(simplified_self_ty) =
-                fast_reject::simplify_type(tcx, self_ty, true) {
-            tcx.relevant_trait_impls_for((self.def_id, simplified_self_ty))
-        } else {
-            tcx.trait_impls_of(self.def_id)
-        };
 
-        for impl_def_id in relevant_impls.iter() {
-            f(impl_def_id);
+        // This depends on the set of all impls for the trait. That is
+        // unfortunate. When we get red-green recompilation, we would like
+        // to have a way of knowing whether the set of relevant impls
+        // changed. The most naive
+        // way would be to compute the Vec of relevant impls and see whether
+        // it differs between compilations. That shouldn't be too slow by
+        // itself - we do quite a bit of work for each relevant impl anyway.
+        //
+        // If we want to be faster, we could have separate queries for
+        // blanket and non-blanket impls, and compare them separately.
+        //
+        // I think we'll cross that bridge when we get to it.
+        if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
+            if let Some(impls) = impls.non_blanket_impls.get(&simp) {
+                for &impl_def_id in impls {
+                    f(impl_def_id);
+                }
+            }
+        } else {
+            for v in impls.non_blanket_impls.values() {
+                for &impl_def_id in v {
+                    f(impl_def_id);
+                }
+            }
         }
     }
 }
@@ -153,7 +140,7 @@ impl<'a, 'gcx, 'tcx> TraitDef {
 // Query provider for `trait_impls_of`.
 pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 trait_id: DefId)
-                                                -> TraitImpls {
+                                                -> Rc<TraitImpls> {
     let remote_impls = if trait_id.is_local() {
         // Traits defined in the current crate can't have impls in upstream
         // crates, so we don't bother querying the cstore.
@@ -163,7 +150,7 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     let mut blanket_impls = Vec::new();
-    let mut non_blanket_impls = Vec::new();
+    let mut non_blanket_impls = FxHashMap();
 
     let local_impls = tcx.hir
                          .trait_impls(trait_id)
@@ -176,47 +163,20 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             continue
         }
 
-        if fast_reject::simplify_type(tcx, impl_self_ty, false).is_some() {
-            non_blanket_impls.push(impl_def_id);
+        if let Some(simplified_self_ty) =
+            fast_reject::simplify_type(tcx, impl_self_ty, false)
+        {
+            non_blanket_impls
+                .entry(simplified_self_ty)
+                .or_insert(vec![])
+                .push(impl_def_id);
         } else {
             blanket_impls.push(impl_def_id);
         }
     }
 
-    TraitImpls {
-        blanket_impls: Rc::new(blanket_impls),
-        non_blanket_impls: Rc::new(non_blanket_impls),
-    }
-}
-
-// Query provider for `relevant_trait_impls_for`.
-pub(super) fn relevant_trait_impls_provider<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    (trait_id, self_ty): (DefId, fast_reject::SimplifiedType))
-    -> TraitImpls
-{
-    let all_trait_impls = tcx.trait_impls_of(trait_id);
-
-    let relevant: Vec<DefId> = all_trait_impls
-        .non_blanket_impls
-        .iter()
-        .cloned()
-        .filter(|&impl_def_id| {
-            let impl_self_ty = tcx.type_of(impl_def_id);
-            let impl_simple_self_ty = fast_reject::simplify_type(tcx,
-                                                                 impl_self_ty,
-                                                                 false).unwrap();
-            impl_simple_self_ty == self_ty
-        })
-        .collect();
-
-    if all_trait_impls.non_blanket_impls.len() == relevant.len() {
-        // If we didn't filter anything out, re-use the existing vec.
-        all_trait_impls
-    } else {
-        TraitImpls {
-            blanket_impls: all_trait_impls.blanket_impls.clone(),
-            non_blanket_impls: Rc::new(relevant),
-        }
-    }
+    Rc::new(TraitImpls {
+        blanket_impls: blanket_impls,
+        non_blanket_impls: non_blanket_impls,
+    })
 }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 67ec8d2ae63..2d29a288a26 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -423,7 +423,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         let mut dtor_did = None;
         let ty = self.type_of(adt_did);
-        self.trait_def(drop_trait).for_each_relevant_impl(self, ty, |impl_did| {
+        self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
             if let Some(item) = self.associated_items(impl_did).next() {
                 if let Ok(()) = validate(self, impl_did) {
                     dtor_did = Some(item.def_id);
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index e942b7264c5..676c3c51ea2 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -188,7 +188,7 @@ impl<'a> AllocFnFactory<'a> {
     fn arg_ty(&self,
               ty: &AllocatorTy,
               args: &mut Vec<Arg>,
-              mut ident: &mut FnMut() -> Ident) -> P<Expr> {
+              ident: &mut FnMut() -> Ident) -> P<Expr> {
         match *ty {
             AllocatorTy::Layout => {
                 let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
@@ -263,7 +263,7 @@ impl<'a> AllocFnFactory<'a> {
     fn ret_ty(&self,
               ty: &AllocatorTy,
               args: &mut Vec<Arg>,
-              mut ident: &mut FnMut() -> Ident,
+              ident: &mut FnMut() -> Ident,
               expr: P<Expr>) -> (P<Ty>, P<Expr>)
     {
         match *ty {
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index 212ddb9a15c..ec88bcf9c79 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -434,20 +434,40 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
         //! For mutable loans of content whose mutability derives
         //! from a local variable, mark the mutability decl as necessary.
 
-        match loan_path.kind {
-            LpVar(local_id) |
-            LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
-                self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
-            }
-            LpDowncast(ref base, _) |
-            LpExtend(ref base, mc::McInherited, _) |
-            LpExtend(ref base, mc::McDeclared, _) => {
-                self.mark_loan_path_as_mutated(&base);
-            }
-            LpExtend(_, mc::McImmutable, _) => {
-                // Nothing to do.
+        let mut wrapped_path = Some(loan_path);
+        let mut through_borrow = false;
+
+        while let Some(current_path) = wrapped_path {
+            wrapped_path = match current_path.kind {
+                LpVar(local_id) => {
+                    if !through_borrow {
+                        self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
+                    }
+                    None
+                }
+                LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
+                    self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
+                    None
+                }
+                LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) |
+                LpExtend(ref base, mc::McDeclared, LpDeref(pointer_kind)) => {
+                    if pointer_kind != mc::Unique {
+                        through_borrow = true;
+                    }
+                    Some(base)
+                }
+                LpDowncast(ref base, _) |
+                LpExtend(ref base, mc::McInherited, _) |
+                LpExtend(ref base, mc::McDeclared, _) => {
+                    Some(base)
+                }
+                LpExtend(_, mc::McImmutable, _) => {
+                    // Nothing to do.
+                    None
+                }
             }
         }
+
     }
 
     pub fn compute_gen_scope(&self,
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index cf3b7508c02..41771738ac6 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -99,7 +99,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     let tables = tcx.typeck_tables_of(owner_def_id);
     let region_maps = tcx.region_maps(owner_def_id);
     let body = tcx.hir.body(body_id);
-    let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id, body };
+    let bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id, body };
 
     // Eventually, borrowck will always read the MIR, but at the
     // moment we do not. So, for now, we always force MIR to be
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 060ff503d4e..a3f8aae472c 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -23,7 +23,7 @@ use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use rustc::lint;
-use rustc_errors::{Diagnostic, Level, DiagnosticBuilder};
+use rustc_errors::DiagnosticBuilder;
 
 use rustc::hir::def::*;
 use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
@@ -351,12 +351,10 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                             match arm_index {
                                 // The arm with the user-specified pattern.
                                 0 => {
-                                    let mut diagnostic = Diagnostic::new(Level::Warning,
-                                                                         "unreachable pattern");
-                                    diagnostic.set_span(pat.span);
-                                    cx.tcx.sess.add_lint_diagnostic(
+                                    cx.tcx.lint_node(
                                             lint::builtin::UNREACHABLE_PATTERNS,
-                                            hir_pat.id, diagnostic);
+                                        hir_pat.id, pat.span,
+                                        "unreachable pattern");
                                 },
                                 // The arm with the wildcard pattern.
                                 1 => {
@@ -371,16 +369,18 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 
                         hir::MatchSource::ForLoopDesugar |
                         hir::MatchSource::Normal => {
-                            let mut diagnostic = Diagnostic::new(Level::Warning,
-                                                                 "unreachable pattern");
-                            diagnostic.set_span(pat.span);
+                            let mut err = cx.tcx.struct_span_lint_node(
+                                lint::builtin::UNREACHABLE_PATTERNS,
+                                hir_pat.id,
+                                pat.span,
+                                "unreachable pattern",
+                            );
                             // if we had a catchall pattern, hint at that
                             if let Some(catchall) = catchall {
-                                diagnostic.span_label(pat.span, "this is an unreachable pattern");
-                                diagnostic.span_note(catchall, "this pattern matches any value");
+                                err.span_label(pat.span, "this is an unreachable pattern");
+                                err.span_note(catchall, "this pattern matches any value");
                             }
-                            cx.tcx.sess.add_lint_diagnostic(lint::builtin::UNREACHABLE_PATTERNS,
-                                                            hir_pat.id, diagnostic);
+                            err.emit();
                         },
 
                         // Unreachable patterns in try expressions occur when one of the arms
diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs
index ced73e9e426..df660d08603 100644
--- a/src/librustc_data_structures/array_vec.rs
+++ b/src/librustc_data_structures/array_vec.rs
@@ -260,7 +260,7 @@ impl<'a, A: Array> Drop for Drain<'a, A> {
                 let start = source_array_vec.len();
                 let tail = self.tail_start;
                 {
-                    let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
+                    let arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
                     let src = arr.as_ptr().offset(tail as isize);
                     let dst = arr.as_mut_ptr().offset(start as isize);
                     ptr::copy(src, dst, self.tail_len);
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index ffcd25a4cdd..7fc59be780f 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -166,7 +166,7 @@ impl BitMatrix {
     pub fn add(&mut self, source: usize, target: usize) -> bool {
         let (start, _) = self.range(source);
         let (word, mask) = word_mask(target);
-        let mut vector = &mut self.vector[..];
+        let vector = &mut self.vector[..];
         let v1 = vector[start + word];
         let v2 = v1 | mask;
         vector[start + word] = v2;
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 8e2a759b467..42f56aa0782 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -259,7 +259,7 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
     type IntoIter = slice::IterMut<'a, T>;
 
     #[inline]
-    fn into_iter(mut self) -> slice::IterMut<'a, T> {
+    fn into_iter(self) -> slice::IterMut<'a, T> {
         self.raw.iter_mut()
     }
 }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 6e8d3494ba5..e331d6c6ae0 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -89,7 +89,7 @@ pub fn compile_input(sess: &Session,
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
     let (outputs, trans) = {
-        let krate = match phase_1_parse_input(sess, input) {
+        let krate = match phase_1_parse_input(control, sess, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
                 parse_error.emit();
@@ -296,9 +296,13 @@ pub struct CompileController<'a> {
     pub after_llvm: PhaseController<'a>,
     pub compilation_done: PhaseController<'a>,
 
+    // FIXME we probably want to group the below options together and offer a
+    // better API, rather than this ad-hoc approach.
     pub make_glob_map: MakeGlobMap,
     // Whether the compiler should keep the ast beyond parsing.
     pub keep_ast: bool,
+    // -Zcontinue-parse-after-error
+    pub continue_parse_after_error: bool,
 }
 
 impl<'a> CompileController<'a> {
@@ -312,6 +316,7 @@ impl<'a> CompileController<'a> {
             compilation_done: PhaseController::basic(),
             make_glob_map: MakeGlobMap::No,
             keep_ast: false,
+            continue_parse_after_error: false,
         }
     }
 }
@@ -484,10 +489,10 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
     }
 
     fn state_when_compilation_done(input: &'a Input,
-                                    session: &'tcx Session,
-                                    out_dir: &'a Option<PathBuf>,
-                                    out_file: &'a Option<PathBuf>)
-                                    -> Self {
+                                   session: &'tcx Session,
+                                   out_dir: &'a Option<PathBuf>,
+                                   out_file: &'a Option<PathBuf>)
+                                   -> Self {
         CompileState {
             out_file: out_file.as_ref().map(|s| &**s),
             ..CompileState::empty(input, session, out_dir)
@@ -495,9 +500,11 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
     }
 }
 
-pub fn phase_1_parse_input<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
-    let continue_after_error = sess.opts.debugging_opts.continue_parse_after_error;
-    sess.diagnostic().set_continue_after_error(continue_after_error);
+pub fn phase_1_parse_input<'a>(control: &CompileController,
+                               sess: &'a Session,
+                               input: &Input)
+                               -> PResult<'a, ast::Crate> {
+    sess.diagnostic().set_continue_after_error(control.continue_parse_after_error);
 
     let krate = time(sess.time_passes(), "parsing", || {
         match *input {
@@ -638,7 +645,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         super::describe_lints(&sess.lint_store.borrow(), true);
         return Err(CompileIncomplete::Stopped);
     }
-    sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?;
 
     // Currently, we ignore the name resolution data structures for the purposes of dependency
     // tracking. Instead we will run name resolution and include its output in the hash of each
@@ -708,8 +714,8 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         missing_fragment_specifiers.sort();
         for span in missing_fragment_specifiers {
             let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
-            let msg = "missing fragment specifier".to_string();
-            sess.add_lint(lint, ast::CRATE_NODE_ID, span, msg);
+            let msg = "missing fragment specifier";
+            sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
         }
         if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
             ecx.parse_sess.span_diagnostic.abort_if_errors();
@@ -773,10 +779,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
          || no_asm::check_crate(sess, &krate));
 
     time(time_passes,
-         "early lint checks",
-         || lint::check_ast_crate(sess, &krate));
-
-    time(time_passes,
          "AST validation",
          || ast_validation::check_crate(sess, &krate));
 
@@ -800,6 +802,10 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         })
     })?;
 
+    time(time_passes,
+         "early lint checks",
+         || lint::check_ast_crate(sess, &krate));
+
     // Lower ast -> hir.
     let hir_forest = time(time_passes, "lowering ast -> hir", || {
         let hir_crate = lower_crate(sess, &krate, &mut resolver);
@@ -908,6 +914,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     rustc_const_eval::provide(&mut local_providers);
     middle::region::provide(&mut local_providers);
     cstore::provide_local(&mut local_providers);
+    lint::provide(&mut local_providers);
 
     let mut extern_providers = ty::maps::Providers::default();
     cstore::provide(&mut extern_providers);
@@ -1198,10 +1205,10 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
                          }
                          Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable),
                          Some(_) => {
-                             session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES,
-                                              ast::CRATE_NODE_ID,
-                                              a.span,
-                                              "invalid `crate_type` value".to_string());
+                             session.buffer_lint(lint::builtin::UNKNOWN_CRATE_TYPES,
+                                                 ast::CRATE_NODE_ID,
+                                                 a.span,
+                                                 "invalid `crate_type` value");
                              None
                          }
                          _ => {
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4c337993468..6f0a50180d7 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -422,7 +422,7 @@ fn show_content_with_pager(content: &String) {
 
     match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
         Ok(mut pager) => {
-            if let Some(mut pipe) = pager.stdin.as_mut() {
+            if let Some(pipe) = pager.stdin.as_mut() {
                 if pipe.write_all(content.as_bytes()).is_err() {
                     fallback_to_println = true;
                 }
@@ -518,7 +518,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                         -> CompileController<'a> {
         let mut control = CompileController::basic();
 
-        control.keep_ast = sess.opts.debugging_opts.keep_ast || save_analysis(sess);
+        control.keep_ast = sess.opts.debugging_opts.keep_ast;
+        control.continue_parse_after_error = sess.opts.debugging_opts.continue_parse_after_error;
 
         if let Some((ppm, opt_uii)) = parse_pretty(sess, matches) {
             if ppm.needs_ast_map(&opt_uii) {
@@ -574,19 +575,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
         }
 
         if save_analysis(sess) {
-            control.after_analysis.callback = box |state| {
-                time(state.session.time_passes(), "save analysis", || {
-                    save::process_crate(state.tcx.unwrap(),
-                                        state.expanded_crate.unwrap(),
-                                        state.analysis.unwrap(),
-                                        state.crate_name.unwrap(),
-                                        None,
-                                        DumpHandler::new(state.out_dir,
-                                                         state.crate_name.unwrap()))
-                });
-            };
-            control.after_analysis.run_callback_on_error = true;
-            control.make_glob_map = resolve::MakeGlobMap::Yes;
+            enable_save_analysis(&mut control);
         }
 
         if sess.print_fuel_crate.is_some() {
@@ -603,6 +592,23 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
     }
 }
 
+pub fn enable_save_analysis(control: &mut CompileController) {
+    control.keep_ast = true;
+    control.after_analysis.callback = box |state| {
+        time(state.session.time_passes(), "save analysis", || {
+            save::process_crate(state.tcx.unwrap(),
+                                state.expanded_crate.unwrap(),
+                                state.analysis.unwrap(),
+                                state.crate_name.unwrap(),
+                                None,
+                                DumpHandler::new(state.out_dir,
+                                                 state.crate_name.unwrap()))
+        });
+    };
+    control.after_analysis.run_callback_on_error = true;
+    control.make_glob_map = resolve::MakeGlobMap::Yes;
+}
+
 fn save_analysis(sess: &Session) -> bool {
     sess.opts.debugging_opts.save_analysis
 }
@@ -1215,7 +1221,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     Registry::new(&all_errors)
 }
 
-fn get_args() -> Vec<String> {
+pub fn get_args() -> Vec<String> {
     env::args_os().enumerate()
         .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
              early_error(ErrorOutputType::default(),
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 62e20a90f8a..8668ab30154 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -119,7 +119,9 @@ fn test_env<F>(source_string: &str,
         name: driver::anon_src(),
         input: source_string.to_string(),
     };
-    let krate = driver::phase_1_parse_input(&sess, &input).unwrap();
+    let krate = driver::phase_1_parse_input(&driver::CompileController::basic(),
+                                            &sess,
+                                            &input).unwrap();
     let driver::ExpansionResult { defs, resolutions, mut hir_forest, .. } = {
         driver::phase_2_configure_and_expand(&sess,
                                              &cstore,
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ca30ed4a536..88432e64290 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -36,7 +36,7 @@ use rustc::ty::{self, Ty};
 use rustc::traits::{self, Reveal};
 use rustc::hir::map as hir_map;
 use util::nodemap::NodeSet;
-use lint::{Level, LateContext, LintContext, LintArray};
+use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
 
 use std::collections::HashSet;
@@ -542,9 +542,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
         };
 
         if self.impling_types.is_none() {
-            let debug_def = cx.tcx.trait_def(debug);
             let mut impls = NodeSet();
-            debug_def.for_each_impl(cx.tcx, |d| {
+            cx.tcx.for_each_impl(debug, |d| {
                 if let Some(ty_def) = cx.tcx.type_of(d).ty_to_def_id() {
                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(ty_def) {
                         impls.insert(node_id);
@@ -877,16 +876,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
             let mut db = cx.struct_span_lint(UNCONDITIONAL_RECURSION,
                                              sp,
                                              "function cannot return without recurring");
-
             // FIXME #19668: these could be span_lint_note's instead of this manual guard.
-            if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
-                // offer some help to the programmer.
-                for call in &self_call_spans {
-                    db.span_note(*call, "recursive call site");
-                }
-                db.help("a `loop` may express intention \
-                         better if this is on purpose");
+            // offer some help to the programmer.
+            for call in &self_call_spans {
+                db.span_note(*call, "recursive call site");
             }
+            db.help("a `loop` may express intention \
+                     better if this is on purpose");
             db.emit();
         }
 
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index d7d0dc7cb35..ba17df4cdca 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -145,22 +145,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
         }
 
         let t = cx.tables.expr_ty(&expr);
-        let warned = match t.sty {
-            ty::TyTuple(ref tys, _) if tys.is_empty() => return,
-            ty::TyNever => return,
-            ty::TyBool => return,
-            ty::TyAdt(def, _) => check_must_use(cx, def.did, s.span),
+        let ty_warned = match t.sty {
+            ty::TyAdt(def, _) => check_must_use(cx, def.did, s.span, ""),
             _ => false,
         };
-        if !warned {
+
+        let mut fn_warned = false;
+        let maybe_def = match expr.node {
+            hir::ExprCall(ref callee, _) => {
+                match callee.node {
+                    hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.id)),
+                    _ => None
+                }
+            },
+            hir::ExprMethodCall(..) => {
+                cx.tables.type_dependent_defs.get(&expr.id).cloned()
+            },
+            _ => { None }
+        };
+        if let Some(def) = maybe_def {
+            let def_id = def.def_id();
+            fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+        }
+
+        if !(ty_warned || fn_warned) {
             cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
         }
 
-        fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span) -> bool {
+        fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span, describe_path: &str) -> bool {
             for attr in cx.tcx.get_attrs(def_id).iter() {
                 if attr.check_name("must_use") {
-                    let mut msg = format!("unused `{}` which must be used",
-                                          cx.tcx.item_path_str(def_id));
+                    let mut msg = format!("unused {}`{}` which must be used",
+                                          describe_path, cx.tcx.item_path_str(def_id));
                     // check for #[must_use="..."]
                     if let Some(s) = attr.value_str() {
                         msg.push_str(": ");
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 64cbe638e8d..225e271e467 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -480,7 +480,7 @@ impl CrateStore for cstore::CStore {
                 _ => {},
             }
 
-            let mut bfs_queue = &mut VecDeque::new();
+            let bfs_queue = &mut VecDeque::new();
             let mut add_child = |bfs_queue: &mut VecDeque<_>, child: def::Export, parent: DefId| {
                 let child = child.def.def_id();
 
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 702fc89fa12..e6360bd9570 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -206,7 +206,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         self.schedule_drop(span, extent, &Lvalue::Local(local_id), var_ty);
     }
 
-    pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, mut f: &mut F)
+    pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
         where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>)
     {
         match *pattern.kind {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 4f0d6a51bfd..53e3a7ff5a2 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -244,8 +244,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
                 let mut span = None;
 
                 self.tcx
-                    .trait_def(drop_trait_id)
-                    .for_each_relevant_impl(self.tcx, self.mir.return_ty, |impl_did| {
+                    .for_each_relevant_impl(drop_trait_id, self.mir.return_ty, |impl_did| {
                         self.tcx.hir
                             .as_local_node_id(impl_did)
                             .and_then(|impl_node_id| self.tcx.hir.find(impl_node_id))
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 888e5be10dd..787f1ae1e21 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -770,7 +770,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                value,
                obligations);
 
-        let mut fulfill_cx = &mut self.fulfillment_cx;
+        let fulfill_cx = &mut self.fulfillment_cx;
         for obligation in obligations {
             fulfill_cx.register_predicate_obligation(self.infcx, obligation);
         }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 38d8555334c..2643ed2a3c0 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -237,10 +237,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         self.check_trait_fn_not_const(sig.constness);
                         if block.is_none() {
                             self.check_decl_no_pat(&sig.decl, |span, _| {
-                                self.session.add_lint(lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
-                                                      trait_item.id, span,
-                                                      "patterns aren't allowed in methods \
-                                                       without bodies".to_string());
+                                self.session.buffer_lint(
+                                    lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                                    trait_item.id, span,
+                                    "patterns aren't allowed in methods \
+                                     without bodies");
                             });
                         }
                     }
@@ -252,7 +253,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 if item.attrs.iter().any(|attr| attr.check_name("warn_directory_ownership")) {
                     let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
                     let msg = "cannot declare a new module at this location";
-                    self.session.add_lint(lint, item.id, item.span, msg.to_string());
+                    self.session.buffer_lint(lint, item.id, item.span, msg);
                 }
             }
             ItemKind::Union(ref vdata, _) => {
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 9bc198c59a9..d0322e27d66 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -76,12 +76,12 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
                 ErroneousReferencedConstant(_) => {}
                 TypeckError => {}
                 _ => {
-                    self.tcx.sess.add_lint(CONST_ERR,
-                                           expr.id,
-                                           expr.span,
-                                           format!("constant evaluation error: {}. This will \
-                                                    become a HARD ERROR in the future",
-                                                   err.description().into_oneline()))
+                    self.tcx.lint_node(CONST_ERR,
+                                       expr.id,
+                                       expr.span,
+                                       &format!("constant evaluation error: {}. This will \
+                                                 become a HARD ERROR in the future",
+                                                err.description().into_oneline()));
                 }
             }
         }
@@ -260,10 +260,10 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
                     kind: LayoutError(ty::layout::LayoutError::Unknown(_)), ..
                 }) => {}
                 Err(msg) => {
-                    self.tcx.sess.add_lint(CONST_ERR,
-                                           ex.id,
-                                           msg.span,
-                                           msg.description().into_oneline().into_owned())
+                    self.tcx.lint_node(CONST_ERR,
+                                       ex.id,
+                                       msg.span,
+                                       &msg.description().into_oneline().into_owned());
                 }
             }
         }
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 907a258a12d..1bfa5943ee9 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -223,6 +223,40 @@ To fix this, add a label specifying which loop is being broken out of:
 ```
 'foo: while break 'foo {}
 ```
+"##,
+
+E0571: r##"
+A `break` statement with an argument appeared in a non-`loop` loop.
+
+Example of erroneous code:
+
+```compile_fail,E0571
+# let mut i = 1;
+# fn satisfied(n: usize) -> bool { n % 23 == 0 }
+let result = while true {
+    if satisfied(i) {
+        break 2*i; // error: `break` with value from a `while` loop
+    }
+    i += 1;
+};
+```
+
+The `break` statement can take an argument (which will be the value of the loop
+expression if the `break` statement is executed) in `loop` loops, but not
+`for`, `while`, or `while let` loops.
+
+Make sure `break value;` statements only occur in `loop` loops:
+
+```
+# let mut i = 1;
+# fn satisfied(n: usize) -> bool { n % 23 == 0 }
+let result = loop { // ok!
+    if satisfied(i) {
+        break 2*i;
+    }
+    i += 1;
+};
+```
 "##
 }
 
@@ -230,5 +264,4 @@ register_diagnostics! {
     E0226, // only a single explicit lifetime bound is permitted
     E0472, // asm! is unsupported on this target
     E0561, // patterns aren't allowed in function pointer types
-    E0571, // `break` with a value in a non-`loop`-loop
 }
diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs
index 60074cce2b9..b38369665f8 100644
--- a/src/librustc_platform_intrinsics/powerpc.rs
+++ b/src/librustc_platform_intrinsics/powerpc.rs
@@ -142,6 +142,146 @@ pub fn find(name: &str) -> Option<Intrinsic> {
             output: &::U32x4,
             definition: Named("llvm.ppc.altivec.vminuw")
         },
+        "_vec_subsbs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS },
+            output: &::I8x16,
+            definition: Named("llvm.ppc.altivec.vsubsbs")
+        },
+        "_vec_sububs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS },
+            output: &::U8x16,
+            definition: Named("llvm.ppc.altivec.vsububs")
+        },
+        "_vec_subshs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vsubshs")
+        },
+        "_vec_subuhs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vsubuhs")
+        },
+        "_vec_subsws" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vsubsws")
+        },
+        "_vec_subuws" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vsubuws")
+        },
+        "_vec_subc" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vsubcuw")
+        },
+        "_vec_addsbs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS },
+            output: &::I8x16,
+            definition: Named("llvm.ppc.altivec.vaddsbs")
+        },
+        "_vec_addubs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS },
+            output: &::U8x16,
+            definition: Named("llvm.ppc.altivec.vaddubs")
+        },
+        "_vec_addshs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vaddshs")
+        },
+        "_vec_adduhs" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vadduhs")
+        },
+        "_vec_addsws" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vaddsws")
+        },
+        "_vec_adduws" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vadduws")
+        },
+        "_vec_addc" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vaddcuw")
+        },
+        "_vec_mulesb" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vmulesb")
+        },
+        "_vec_muleub" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vmuleub")
+        },
+        "_vec_mulesh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vmulesh")
+        },
+        "_vec_muleuh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vmuleuh")
+        },
+        "_vec_mulosb" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vmulosb")
+        },
+        "_vec_muloub" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vmuloub")
+        },
+        "_vec_mulosh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vmulosh")
+        },
+        "_vec_mulouh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vmulouh")
+        },
+        "_vec_avgsb" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I8x16, &::I8x16]; &INPUTS },
+            output: &::I8x16,
+            definition: Named("llvm.ppc.altivec.vavgsb")
+        },
+        "_vec_avgub" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U8x16, &::U8x16]; &INPUTS },
+            output: &::U8x16,
+            definition: Named("llvm.ppc.altivec.vavgub")
+        },
+        "_vec_avgsh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vavgsh")
+        },
+        "_vec_avguh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vavguh")
+        },
+        "_vec_avgsw" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vavgsw")
+        },
+        "_vec_avguw" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U32x4,
+            definition: Named("llvm.ppc.altivec.vavguw")
+        },
         _ => return None,
     })
 }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 64af24d92ee..9fa5fea20d9 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -781,7 +781,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             hir::ItemTrait(.., ref trait_item_refs) => {
                 self.check_item(item.id).generics().predicates();
                 for trait_item_ref in trait_item_refs {
-                    let mut check = self.check_item(trait_item_ref.id.node_id);
+                    let check = self.check_item(trait_item_ref.id.node_id);
                     check.generics().predicates();
                     if trait_item_ref.kind != hir::AssociatedItemKind::Type ||
                        trait_item_ref.defaultness.has_value() {
@@ -814,7 +814,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             }
             hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
                 {
-                    let mut check = self.check_item(item.id);
+                    let check = self.check_item(item.id);
                     check.ty().generics().predicates();
                     if trait_ref.is_some() {
                         check.impl_trait_ref();
@@ -1345,11 +1345,11 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
                                     "private trait can't be public"))
                         .emit();
                 } else {
-                    self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
-                                           node_id,
-                                           self.span,
-                                           format!("private trait `{}` in public \
-                                                    interface (error E0445)", trait_ref));
+                    self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC,
+                                       node_id,
+                                       self.span,
+                                       &format!("private trait `{}` in public \
+                                                 interface (error E0445)", trait_ref));
                 }
             }
         }
@@ -1393,11 +1393,11 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
                         err.span_label(self.span, "can't leak private type");
                         err.emit();
                     } else {
-                        self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
-                                               node_id,
-                                               self.span,
-                                               format!("private type `{}` in public \
-                                                        interface (error E0446)", ty));
+                        self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC,
+                                           node_id,
+                                           self.span,
+                                           &format!("private type `{}` in public \
+                                                     interface (error E0446)", ty));
                     }
                 }
             }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index d150ff1ff81..a8bb6619bbd 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -122,13 +122,13 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
                  directive.span.source_equal(&DUMMY_SP) => {}
             ImportDirectiveSubclass::ExternCrate => {
                 let lint = lint::builtin::UNUSED_EXTERN_CRATES;
-                let msg = "unused extern crate".to_string();
-                resolver.session.add_lint(lint, directive.id, directive.span, msg);
+                let msg = "unused extern crate";
+             ;   resolver.session.buffer_lint(lint, directive.id, directive.span, msg)
             }
             ImportDirectiveSubclass::MacroUse => {
                 let lint = lint::builtin::UNUSED_IMPORTS;
-                let msg = "unused `#[macro_use]` import".to_string();
-                resolver.session.add_lint(lint, directive.id, directive.span, msg);
+                let msg = "unused `#[macro_use]` import";
+                resolver.session.buffer_lint(lint, directive.id, directive.span, msg);
             }
             _ => {}
         }
@@ -160,9 +160,6 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
                           } else {
                               String::new()
                           });
-        visitor.session.add_lint(lint::builtin::UNUSED_IMPORTS,
-                                 *id,
-                                 ms,
-                                 msg);
+        visitor.session.buffer_lint(lint::builtin::UNUSED_IMPORTS, *id, ms, &msg);
     }
 }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 2317e36a0ab..b4f9ba4e8f7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2552,9 +2552,10 @@ impl<'a> Resolver<'a> {
                                 = self.struct_constructors.get(&def_id).cloned() {
                             if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
                                 let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
-                                self.session.add_lint(lint, id, span,
+                                self.session.buffer_lint(lint, id, span,
                                     "private struct constructors are not usable through \
-                                     reexports in outer modules".to_string());
+                                     reexports in outer modules",
+                                );
                                 res = Some(PathResolution::new(ctor_def));
                             }
                         }
@@ -2748,7 +2749,7 @@ impl<'a> Resolver<'a> {
             };
             if result.base_def() == unqualified_result {
                 let lint = lint::builtin::UNUSED_QUALIFICATIONS;
-                self.session.add_lint(lint, id, span, "unnecessary qualification".to_string());
+                self.session.buffer_lint(lint, id, span, "unnecessary qualification")
             }
         }
 
@@ -3486,7 +3487,7 @@ impl<'a> Resolver<'a> {
                 span.push_span_label(b1.span, msg1);
                 span.push_span_label(b2.span, msg2);
                 let msg = format!("`{}` is ambiguous", name);
-                self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg);
+                self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, &msg);
             } else {
                 let mut err =
                     self.session.struct_span_err(span, &format!("`{}` is ambiguous", name));
@@ -3607,8 +3608,8 @@ impl<'a> Resolver<'a> {
 
     fn warn_legacy_self_import(&self, directive: &'a ImportDirective<'a>) {
         let (id, span) = (directive.id, directive.span);
-        let msg = "`self` no longer imports values".to_string();
-        self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg);
+        let msg = "`self` no longer imports values";
+        self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg);
     }
 
     fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 4d4f6aadce4..98eaa056177 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -319,8 +319,8 @@ impl<'a> base::Resolver for Resolver<'a> {
             };
             if let Some((id, span)) = id_span {
                 let lint = lint::builtin::UNUSED_MACROS;
-                let msg = "unused macro definition".to_string();
-                self.session.add_lint(lint, id, span, msg);
+                let msg = "unused macro definition";
+                self.session.buffer_lint(lint, id, span, msg);
             } else {
                 bug!("attempted to create unused macro error, but span not available");
             }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 5e799b14f20..26c398379dc 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -379,7 +379,7 @@ impl<'a> Resolver<'a> {
         // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
         // during which the resolution might end up getting re-defined via a glob cycle.
         let (binding, t) = {
-            let mut resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
+            let resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
             let old_binding = resolution.binding();
 
             let t = f(self, resolution);
@@ -745,8 +745,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 let msg = format!("extern crate `{}` is private, and cannot be reexported \
                                    (error E0365), consider declaring with `pub`",
                                    ident);
-                self.session.add_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-                                      directive.id, directive.span, msg);
+                self.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+                                         directive.id,
+                                         directive.span,
+                                         &msg);
             } else if ns == TypeNS {
                 struct_span_err!(self.session, directive.span, E0365,
                                  "`{}` is private, and cannot be reexported", ident)
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index e8032529b1f..8cbc5155dde 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1464,7 +1464,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
                 let mut output = i.to_string(scx.tcx());
                 output.push_str(" @@");
                 let mut empty = Vec::new();
-                let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
+                let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
                 cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
                 cgus.dedup();
                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index cff0eca02c6..63c7b18e8d2 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -335,7 +335,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
                 CodegenUnit::empty(codegen_unit_name.clone())
             };
 
-            let mut codegen_unit = codegen_units.entry(codegen_unit_name.clone())
+            let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
                                                 .or_insert_with(make_codegen_unit);
 
             let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
diff --git a/src/librustc_trans/time_graph.rs b/src/librustc_trans/time_graph.rs
index e0ebe8a0933..ead6e432561 100644
--- a/src/librustc_trans/time_graph.rs
+++ b/src/librustc_trans/time_graph.rs
@@ -70,7 +70,7 @@ impl TimeGraph {
         {
             let mut table = self.data.lock().unwrap();
 
-            let mut data = table.entry(timeline).or_insert(PerThread {
+            let data = table.entry(timeline).or_insert(PerThread {
                 timings: Vec::new(),
                 open_work_package: None,
             });
@@ -90,7 +90,7 @@ impl TimeGraph {
         let end = Instant::now();
 
         let mut table = self.data.lock().unwrap();
-        let mut data = table.get_mut(&timeline).unwrap();
+        let data = table.get_mut(&timeline).unwrap();
 
         if let Some((start, work_package_kind)) = data.open_work_package {
             data.timings.push(Timing {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 1ec850ad7f3..2910d25486e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -985,9 +985,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     .span_label(data.span, "only traits may use parentheses")
                     .emit();
             } else {
-                let msg = "parenthesized parameters may only be used with a trait".to_string();
-                self.tcx().sess.add_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-                                         ast::CRATE_NODE_ID, data.span, msg);
+                let msg = "parenthesized parameters may only be used with a trait";
+                self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+                                     ast::CRATE_NODE_ID, data.span, msg);
             }
         }
     }
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index b3f62de5b57..5f256eab9a9 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -291,25 +291,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
         let t_cast = self.cast_ty;
         let t_expr = self.expr_ty;
         if t_cast.is_numeric() && t_expr.is_numeric() {
-            fcx.tables.borrow_mut().lints.add_lint(
+            fcx.tcx.lint_node(
                 lint::builtin::TRIVIAL_NUMERIC_CASTS,
                 self.expr.id,
                 self.span,
-                format!("trivial numeric cast: `{}` as `{}`. Cast can be \
-                         replaced by coercion, this might require type \
-                         ascription or a temporary variable",
-                        fcx.ty_to_string(t_expr),
-                        fcx.ty_to_string(t_cast)));
+                &format!("trivial numeric cast: `{}` as `{}`. Cast can be \
+                          replaced by coercion, this might require type \
+                          ascription or a temporary variable",
+                         fcx.ty_to_string(t_expr),
+                         fcx.ty_to_string(t_cast)));
         } else {
-            fcx.tables.borrow_mut().lints.add_lint(
+            fcx.tcx.lint_node(
                 lint::builtin::TRIVIAL_CASTS,
                 self.expr.id,
                 self.span,
-                format!("trivial cast: `{}` as `{}`. Cast can be \
-                         replaced by coercion, this might require type \
-                         ascription or a temporary variable",
-                        fcx.ty_to_string(t_expr),
-                        fcx.ty_to_string(t_cast)));
+                &format!("trivial cast: `{}` as `{}`. Cast can be \
+                          replaced by coercion, this might require type \
+                          ascription or a temporary variable",
+                         fcx.ty_to_string(t_expr),
+                         fcx.ty_to_string(t_cast)));
         }
 
     }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index e494bc15222..934a4f9b296 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1204,7 +1204,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                     }
                 }
 
-                if let Some(mut augment_error) = augment_error {
+                if let Some(augment_error) = augment_error {
                     augment_error(&mut db);
                 }
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index dd5b0cdda42..1ccb1e64a98 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -58,8 +58,9 @@ pub enum MethodError<'tcx> {
     ClosureAmbiguity(// DefId of fn trait
                      DefId),
 
-    // Found an applicable method, but it is not visible.
-    PrivateMatch(Def),
+    // Found an applicable method, but it is not visible. The second argument contains a list of
+    // not-in-scope traits which may work.
+    PrivateMatch(Def, Vec<DefId>),
 
     // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
     // forgotten to import a trait.
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 587e583cabd..6669e75d5a0 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -556,7 +556,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             // 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.body_id);
-            let mut selcx = &mut traits::SelectionContext::new(self.fcx);
+            let selcx = &mut traits::SelectionContext::new(self.fcx);
             let traits::Normalized { value: xform_self_ty, obligations } =
                 traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
             debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
@@ -738,10 +738,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                                                      import_id: Option<ast::NodeId>,
                                                      trait_def_id: DefId,
                                                      item: ty::AssociatedItem) {
-        let trait_def = self.tcx.trait_def(trait_def_id);
-
         // FIXME(arielb1): can we use for_each_relevant_impl here?
-        trait_def.for_each_impl(self.tcx, |impl_def_id| {
+        self.tcx.for_each_impl(trait_def_id, |impl_def_id| {
             debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={:?} \
                                                                   impl_def_id={:?}",
                    trait_def_id,
@@ -769,7 +767,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             // as it will pollute the fcx's fulfillment context after this probe
             // is over.
             let cause = traits::ObligationCause::misc(self.span, self.body_id);
-            let mut selcx = &mut traits::SelectionContext::new(self.fcx);
+            let selcx = &mut traits::SelectionContext::new(self.fcx);
             let traits::Normalized { value: xform_self_ty, obligations } =
                 traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
 
@@ -1059,7 +1057,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         };
 
         if let Some(def) = private_candidate {
-            return Err(MethodError::PrivateMatch(def));
+            return Err(MethodError::PrivateMatch(def, out_of_scope_traits));
         }
 
         Err(MethodError::NoMatch(NoMatchData::new(static_candidates,
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 53da9e19ee0..56eacc3194d 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -311,9 +311,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.sess().span_err(span, &msg);
             }
 
-            MethodError::PrivateMatch(def) => {
-                struct_span_err!(self.tcx.sess, span, E0624,
-                                 "{} `{}` is private", def.kind_name(), item_name).emit();
+            MethodError::PrivateMatch(def, out_of_scope_traits) => {
+                let mut err = struct_span_err!(self.tcx.sess, span, E0624,
+                                               "{} `{}` is private", def.kind_name(), item_name);
+                self.suggest_valid_traits(&mut err, out_of_scope_traits);
+                err.emit();
             }
 
             MethodError::IllegalSizedBound(candidates) => {
@@ -353,13 +355,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         err.note(&msg[..]);
     }
 
-    fn suggest_traits_to_import(&self,
-                                err: &mut DiagnosticBuilder,
-                                span: Span,
-                                rcvr_ty: Ty<'tcx>,
-                                item_name: ast::Name,
-                                rcvr_expr: Option<&hir::Expr>,
-                                valid_out_of_scope_traits: Vec<DefId>) {
+    fn suggest_valid_traits(&self,
+                            err: &mut DiagnosticBuilder,
+                            valid_out_of_scope_traits: Vec<DefId>) -> bool {
         if !valid_out_of_scope_traits.is_empty() {
             let mut candidates = valid_out_of_scope_traits;
             candidates.sort();
@@ -379,6 +377,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             });
 
             self.suggest_use_candidates(err, msg, candidates);
+            true
+        } else {
+            false
+        }
+    }
+
+    fn suggest_traits_to_import(&self,
+                                err: &mut DiagnosticBuilder,
+                                span: Span,
+                                rcvr_ty: Ty<'tcx>,
+                                item_name: ast::Name,
+                                rcvr_expr: Option<&hir::Expr>,
+                                valid_out_of_scope_traits: Vec<DefId>) {
+        if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
             return;
         }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index fee10f50378..d2176b245be 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1754,10 +1754,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
             debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
 
-            self.tables.borrow_mut().lints.add_lint(
+            self.tcx().lint_node(
                 lint::builtin::UNREACHABLE_CODE,
                 id, span,
-                format!("unreachable {}", kind));
+                &format!("unreachable {}", kind));
         }
     }
 
@@ -4073,7 +4073,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Ok(def) => def,
             Err(error) => {
                 let def = match error {
-                    method::MethodError::PrivateMatch(def) => def,
+                    method::MethodError::PrivateMatch(def, _) => def,
                     _ => Def::Err,
                 };
                 if item_name != keywords::Invalid.name() {
@@ -4240,8 +4240,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
 
             let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
-            let mut ctxt = enclosing_breakables.find_breakable(blk.id);
-            let mut coerce = ctxt.coerce.as_mut().unwrap();
+            let ctxt = enclosing_breakables.find_breakable(blk.id);
+            let coerce = ctxt.coerce.as_mut().unwrap();
             if let Some(tail_expr_ty) = tail_expr_ty {
                 let tail_expr = tail_expr.unwrap();
                 let cause = self.cause(tail_expr.span,
@@ -4286,8 +4286,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         ty
     }
 
-    /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is
-    /// `fn main` if it is a method, `None` otherwise.
+    /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether a
+    /// suggetion can be made, `None` otherwise.
     pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
         // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
         // `while` before reaching it, as block tail returns are not available in them.
@@ -4298,9 +4298,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 name, node: hir::ItemFn(ref decl, ..), ..
             }) = parent {
                 decl.clone().and_then(|decl| {
-                    // This is less than ideal, it will not present the return type span on any
-                    // method called `main`, regardless of whether it is actually the entry point.
-                    Some((decl, name == Symbol::intern("main")))
+                    // This is less than ideal, it will not suggest a return type span on any
+                    // method called `main`, regardless of whether it is actually the entry point,
+                    // but it will still present it as the reason for the expected type.
+                    Some((decl, name != Symbol::intern("main")))
                 })
             } else if let Node::NodeTraitItem(&hir::TraitItem {
                 node: hir::TraitItemKind::Method(hir::MethodSig {
@@ -4308,6 +4309,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }, ..), ..
             }) = parent {
                 decl.clone().and_then(|decl| {
+                    Some((decl, true))
+                })
+            } else if let Node::NodeImplItem(&hir::ImplItem {
+                node: hir::ImplItemKind::Method(hir::MethodSig {
+                    ref decl, ..
+                }, ..), ..
+            }) = parent {
+                decl.clone().and_then(|decl| {
                     Some((decl, false))
                 })
             } else {
@@ -4332,11 +4341,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                             blk_id: ast::NodeId) {
         self.suggest_missing_semicolon(err, expression, expected, cause_span);
 
-        if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) {
-            // `fn main()` must return `()`, do not suggest changing return type
-            if !is_main {
-                self.suggest_missing_return_type(err, &fn_decl, found);
-            }
+        if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
+            self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
         }
     }
 
@@ -4392,20 +4398,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn suggest_missing_return_type(&self,
                                    err: &mut DiagnosticBuilder<'tcx>,
                                    fn_decl: &hir::FnDecl,
-                                   ty: Ty<'tcx>) {
-
-        // Only recommend changing the return type for methods that
+                                   expected: Ty<'tcx>,
+                                   found: Ty<'tcx>,
+                                   can_suggest: bool) {
+        // Only suggest changing the return type for methods that
         // haven't set a return type at all (and aren't `fn main()` or an impl).
-        if let &hir::FnDecl {
-            output: hir::FunctionRetTy::DefaultReturn(span), ..
-        } = fn_decl {
-            if ty.is_suggestable() {
+        match (&fn_decl.output, found.is_suggestable(), can_suggest) {
+            (&hir::FunctionRetTy::DefaultReturn(span), true, true) => {
                 err.span_suggestion(span,
                                     "try adding a return type",
-                                    format!("-> {} ", ty));
-            } else {
+                                    format!("-> {} ", found));
+            }
+            (&hir::FunctionRetTy::DefaultReturn(span), false, true) => {
                 err.span_label(span, "possibly return type missing here?");
             }
+            (&hir::FunctionRetTy::DefaultReturn(span), _, _) => {
+                // `fn main()` must return `()`, do not suggest changing return type
+                err.span_label(span, "expected `()` because of default return type");
+            }
+            (&hir::FunctionRetTy::Return(ref ty), _, _) => {
+                // Only point to return type if the expected type is the return type, as if they
+                // are not, the expectation must have been caused by something else.
+                debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.node);
+                let sp = ty.span;
+                let ty = AstConv::ast_ty_to_ty(self, ty);
+                debug!("suggest_missing_return_type: return type sty {:?}", ty.sty);
+                debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty);
+                if ty.sty == expected.sty {
+                    err.span_label(sp, format!("expected `{}` because of return type",
+                                               expected));
+                }
+            }
         }
     }
 
@@ -4803,8 +4826,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             } else {
                 let mut multispan = MultiSpan::from_span(lifetimes[0].span);
                 multispan.push_span_label(span_late, note_msg.to_string());
-                self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
-                                       lifetimes[0].id, multispan, primary_msg.to_string());
+                self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
+                                   lifetimes[0].id, multispan, primary_msg);
             }
             return;
         }
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 032e37a34a8..c1711491ee4 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                           lhs_expr: &'gcx hir::Expr,
                           lhs_ty: Ty<'tcx>,
                           rhs_ty: Ty<'tcx>,
-                          mut err: &mut errors::DiagnosticBuilder) -> bool {
+                          err: &mut errors::DiagnosticBuilder) -> bool {
         // If this function returns true it means a note was printed, so we don't need
         // to print the normal "implementation of `std::ops::Add` might be missing" note
         let mut is_string_addition = false;
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 8101e87880c..c18a070300a 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -43,7 +43,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         wbcx.visit_fru_field_types();
         wbcx.visit_anon_types();
         wbcx.visit_cast_types();
-        wbcx.visit_lints();
         wbcx.visit_free_region_map();
         wbcx.visit_generator_sigs();
         wbcx.visit_generator_interiors();
@@ -237,10 +236,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
             self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value)));
     }
 
-    fn visit_lints(&mut self) {
-        self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints);
-    }
-
     fn visit_free_region_map(&mut self) {
         let free_region_map = self.tcx().lift_to_global(&self.fcx.tables.borrow().free_region_map);
         let free_region_map = free_region_map.expect("all regions in free-region-map are global");
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 1af55d4d840..e95d49f00bf 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -39,7 +39,7 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
         } else {
             "unused import".to_string()
         };
-        self.tcx.sess.add_lint(lint::builtin::UNUSED_IMPORTS, id, span, msg);
+        self.tcx.lint_node(lint::builtin::UNUSED_IMPORTS, id, span, &msg);
     }
 }
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 7c2adce66fb..0ce5c96da76 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -999,12 +999,12 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         if !allow_defaults && p.default.is_some() {
             if !tcx.sess.features.borrow().default_type_parameter_fallback {
-                tcx.sess.add_lint(
+                tcx.lint_node(
                     lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
                     p.id,
                     p.span,
-                    format!("defaults for type parameters are only allowed in `struct`, \
-                             `enum`, `type`, or `trait` definitions."));
+                    &format!("defaults for type parameters are only allowed in `struct`, \
+                              `enum`, `type`, or `trait` definitions."));
             }
         }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 62b91feb09d..e101e29fc6f 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -155,7 +155,9 @@ pub fn run_core(search_paths: SearchPaths,
     target_features::add_configuration(&mut cfg, &sess);
     sess.parse_sess.config = cfg;
 
-    let krate = panictry!(driver::phase_1_parse_input(&sess, &input));
+    let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(),
+                                                      &sess,
+                                                      &input));
 
     let name = link::find_crate_name(Some(&sess), &krate.attrs, &input);
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 03da451fd9a..735c9d8af7a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -32,7 +32,6 @@ use std::ascii::AsciiExt;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
-use std::ffi::CString;
 use std::fmt::{self, Write};
 use std::str;
 use syntax::feature_gate::UnstableFeatures;
@@ -529,8 +528,8 @@ extern {
     fn hoedown_document_free(md: *mut hoedown_document);
 
     fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer;
-    fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char);
     fn hoedown_buffer_free(b: *mut hoedown_buffer);
+    fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const u8, len: libc::size_t);
 }
 
 impl hoedown_buffer {
@@ -620,8 +619,7 @@ pub fn render(w: &mut fmt::Formatter,
                                Some("rust-example-rendered"),
                                None,
                                playground_button.as_ref().map(String::as_str)));
-                let output = CString::new(s).unwrap();
-                hoedown_buffer_puts(ob, output.as_ptr());
+                hoedown_buffer_put(ob, s.as_ptr(), s.len());
             })
         }
     }
@@ -630,7 +628,7 @@ pub fn render(w: &mut fmt::Formatter,
                      level: libc::c_int, data: *const hoedown_renderer_data,
                      _: libc::size_t) {
         // hoedown does this, we may as well too
-        unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
+        unsafe { hoedown_buffer_put(ob, "\n".as_ptr(), 1); }
 
         // Extract the text provided
         let s = if text.is_null() {
@@ -681,8 +679,7 @@ pub fn render(w: &mut fmt::Formatter,
                            <a href='#{id}'>{sec}{}</a></h{lvl}>",
                            s, lvl = level, id = id, sec = sec);
 
-        let text = CString::new(text).unwrap();
-        unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
+        unsafe { hoedown_buffer_put(ob, text.as_ptr(), text.len()); }
     }
 
     extern fn codespan(
@@ -700,8 +697,9 @@ pub fn render(w: &mut fmt::Formatter,
         };
 
         let content = format!("<code>{}</code>", Escape(&content));
-        let element = CString::new(content).unwrap();
-        unsafe { hoedown_buffer_puts(ob, element.as_ptr()); }
+        unsafe {
+            hoedown_buffer_put(ob, content.as_ptr(), content.len());
+        }
         // Return anything except 0, which would mean "also print the code span verbatim".
         1
     }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index f012fd974b5..b1e92b5190f 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -91,7 +91,9 @@ pub fn run(input: &str,
     sess.parse_sess.config =
         config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
 
-    let krate = panictry!(driver::phase_1_parse_input(&sess, &input));
+    let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(),
+                                                      &sess,
+                                                      &input));
     let driver::ExpansionResult { defs, mut hir_forest, .. } = {
         phase_2_configure_and_expand(
             &sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(())
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 12241b3f881..7e2229a8f84 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1618,7 +1618,7 @@ impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
     type Item = (&'a K, &'a mut V);
     type IntoIter = IterMut<'a, K, V>;
 
-    fn into_iter(mut self) -> IterMut<'a, K, V> {
+    fn into_iter(self) -> IterMut<'a, K, V> {
         self.iter_mut()
     }
 }
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 3844690860b..6f7c5a5de42 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -563,7 +563,7 @@ impl<'t, K, V> FullBucket<K, V, &'t mut RawTable<K, V>> {
     ///
     /// This works similarly to `put`, building an `EmptyBucket` out of the
     /// taken bucket.
-    pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
+    pub fn take(self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
         self.table.size -= 1;
 
         unsafe {
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index d1c2bfb96b3..401552a6ec4 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -514,7 +514,7 @@ mod tests {
     #[test]
     fn downcasting() {
         let mut a = A;
-        let mut a = &mut a as &mut (Error + 'static);
+        let a = &mut a as &mut (Error + 'static);
         assert_eq!(a.downcast_ref::<A>(), Some(&A));
         assert_eq!(a.downcast_ref::<B>(), None);
         assert_eq!(a.downcast_mut::<A>(), Some(&mut A));
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 616b4f47ed3..d986021a18b 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -456,7 +456,7 @@ mod tests {
     #[test]
     fn test_slice_reader() {
         let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let mut reader = &mut &in_buf[..];
+        let reader = &mut &in_buf[..];
         let mut buf = [];
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
         let mut buf = [0];
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 03db1e4f01c..5e88a46ecc3 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -14,6 +14,16 @@
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
+#[macro_export]
+// This stability attribute is totally useless.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
+macro_rules! __rust_unstable_column {
+    () => {
+        column!()
+    }
+}
+
 /// The entry point for panic of Rust threads.
 ///
 /// This macro is used to inject panic into a Rust thread, causing the thread to
@@ -48,7 +58,8 @@ macro_rules! panic {
     ($msg:expr) => ({
         $crate::rt::begin_panic($msg, {
             // static requires less code at runtime, more constant data
-            static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!());
+            static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(),
+                __rust_unstable_column!());
             &_FILE_LINE_COL
         })
     });
@@ -58,7 +69,8 @@ macro_rules! panic {
             // used inside a dead function. Just `#[allow(dead_code)]` is
             // insufficient, since the user may have
             // `#[forbid(dead_code)]` and which cannot be overridden.
-            static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!());
+            static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(),
+                __rust_unstable_column!());
             &_FILE_LINE_COL
         })
     });
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index a7b01e49d2b..273c7c1c54a 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -152,7 +152,7 @@ impl Barrier {
             BarrierWaitResult(false)
         } else {
             lock.count = 0;
-            lock.generation_id += 1;
+            lock.generation_id = lock.generation_id.wrapping_add(1);
             self.cvar.notify_all();
             BarrierWaitResult(true)
         }
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index d9edf5d1254..bb18fe95a9d 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -267,7 +267,7 @@ impl Once {
     #[cold]
     fn call_inner(&'static self,
                   ignore_poisoning: bool,
-                  mut init: &mut FnMut(bool)) {
+                  init: &mut FnMut(bool)) {
         let mut state = self.state.load(Ordering::SeqCst);
 
         'outer: loop {
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 77ebad4e344..1f56a299407 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -12,13 +12,13 @@ pub use self::imp::OsRng;
 
 use mem;
 
-fn next_u32(mut fill_buf: &mut FnMut(&mut [u8])) -> u32 {
+fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 {
     let mut buf: [u8; 4] = [0; 4];
     fill_buf(&mut buf);
     unsafe { mem::transmute::<[u8; 4], u32>(buf) }
 }
 
-fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
+fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 {
     let mut buf: [u8; 8] = [0; 8];
     fill_buf(&mut buf);
     unsafe { mem::transmute::<[u8; 8], u64>(buf) }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 7f3291cf304..f2487c1b0bd 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -768,8 +768,8 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
 
     unsafe {
         let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
-        let mut db = data.as_mut_ptr()
-                        as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
+        let db = data.as_mut_ptr()
+                    as *mut c::REPARSE_MOUNTPOINT_DATA_BUFFER;
         let buf = &mut (*db).ReparseTarget as *mut _;
         let mut i = 0;
         // FIXME: this conversion is very hacky
diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs
index 0938738b52c..1e8a0be8096 100644
--- a/src/libstd_unicode/tables.rs
+++ b/src/libstd_unicode/tables.rs
@@ -12,9 +12,32 @@
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
-/// The version of [Unicode](http://www.unicode.org/)
-/// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (10, 0, 0);
+/// Represents a Unicode Version.
+///
+/// See also: <http://www.unicode.org/versions/>
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub struct UnicodeVersion {
+    /// Major version.
+    pub major: u32,
+
+    /// Minor version.
+    pub minor: u32,
+
+    /// Micro (or Update) version.
+    pub micro: u32,
+
+    // Private field to keep struct expandable.
+    _priv: (),
+}
+
+/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
+/// `CharExt` and `UnicodeStrPrelude` traits are based on.
+pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
+    major: 10,
+    minor: 0,
+    micro: 0,
+    _priv: (),
+};
 
 
 // BoolTrie is a trie for representing a set of Unicode codepoints. It is
diff --git a/src/libstd_unicode/unicode.py b/src/libstd_unicode/unicode.py
index 5f9def02c7d..1fac859242e 100755
--- a/src/libstd_unicode/unicode.py
+++ b/src/libstd_unicode/unicode.py
@@ -560,9 +560,32 @@ if __name__ == "__main__":
             pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
             unicode_version = re.search(pattern, readme.read()).groups()
         rf.write("""
-/// The version of [Unicode](http://www.unicode.org/)
-/// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
+/// Represents a Unicode Version.
+///
+/// See also: <http://www.unicode.org/versions/>
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub struct UnicodeVersion {
+    /// Major version.
+    pub major: u32,
+
+    /// Minor version.
+    pub minor: u32,
+
+    /// Micro (or Update) version.
+    pub micro: u32,
+
+    // Private field to keep struct expandable.
+    _priv: (),
+}
+
+/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
+/// `CharExt` and `UnicodeStrPrelude` traits are based on.
+pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
+    major: %s,
+    minor: %s,
+    micro: %s,
+    _priv: (),
+};
 """ % unicode_version)
         (canon_decomp, compat_decomp, gencats, combines,
                 to_upper, to_lower, to_title) = load_unicode_data("UnicodeData.txt")
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 6598ecb9444..2ea3fe51d30 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -162,6 +162,63 @@ For more information about the cfg attribute, read:
 https://doc.rust-lang.org/reference.html#conditional-compilation
 "##,
 
+E0552: r##"
+A unrecognized representation attribute was used.
+
+Erroneous code example:
+
+```compile_fail,E0552
+#[repr(D)] // error: unrecognized representation hint
+struct MyStruct {
+    my_field: usize
+}
+```
+
+You can use a `repr` attribute to tell the compiler how you want a struct or
+enum to be laid out in memory.
+
+Make sure you're using one of the supported options:
+
+```
+#[repr(C)] // ok!
+struct MyStruct {
+    my_field: usize
+}
+```
+
+For more information about specifying representations, see the ["Alternative
+Representations" section] of the Rustonomicon.
+
+["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html
+"##,
+
+E0554: r##"
+Feature attributes are only allowed on the nightly release channel. Stable or
+beta compilers will not comply.
+
+Example of erroneous code (on a stable compiler):
+
+```ignore (depends on release channel)
+#![feature(non_ascii_idents)] // error: #![feature] may not be used on the
+                              //        stable release channel
+```
+
+If you need the feature, make sure to use a nightly release of the compiler
+(but be warned that the feature may be removed or altered in the future).
+"##,
+
+E0557: r##"
+A feature attribute named a feature that has been removed.
+
+Erroneous code example:
+
+```compile_fail,E0557
+#![feature(managed_boxes)] // error: feature has been removed
+```
+
+Delete the offending feature attribute.
+"##,
+
 E0558: r##"
 The `export_name` attribute was malformed.
 
@@ -300,11 +357,8 @@ register_diagnostics! {
     E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
     E0550, // multiple deprecated attributes
     E0551, // incorrect meta item
-    E0552, // unrecognized representation hint
-    E0554, // #[feature] may not be used on the [] release channel
     E0555, // malformed feature attribute, expected #![feature(...)]
     E0556, // malformed feature, expected just one word
-    E0557, // feature has been removed
     E0584, // file for module `..` found at both .. and ..
     E0589, // invalid `repr(align)` attribute
 }
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 3cdd3a4b2c3..b293aa8de38 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -52,6 +52,16 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
     base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32))
 }
 
+/* __rust_unstable_column!(): expands to the current column number */
+pub fn expand_column_gated(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
+                  -> Box<base::MacResult+'static> {
+    if sp.allows_unstable() {
+        expand_column(cx, sp, tts)
+    } else {
+        cx.span_fatal(sp, "the __rust_unstable_column macro is unstable");
+    }
+}
+
 /// file!(): expands to the current filename */
 /// The filemap (`loc.file`) contains a bunch more information we could spit
 /// out if we wanted.
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 60833c75a15..146bd5d9856 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -211,7 +211,7 @@ pub enum NamedMatch {
 
 fn nameize<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, ms: &[TokenTree], mut res: I)
                                              -> NamedParseResult {
-    fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, mut res: &mut I,
+    fn n_rec<I: Iterator<Item=NamedMatch>>(sess: &ParseSess, m: &TokenTree, res: &mut I,
              ret_val: &mut HashMap<Ident, Rc<NamedMatch>>)
              -> Result<(), (syntax_pos::Span, String)> {
         match *m {
@@ -445,7 +445,7 @@ pub fn parse(sess: &ParseSess,
         /* error messages here could be improved with links to orig. rules */
         if token_name_eq(&parser.token, &token::Eof) {
             if eof_items.len() == 1 {
-                let matches = eof_items[0].matches.iter_mut().map(|mut dv| {
+                let matches = eof_items[0].matches.iter_mut().map(|dv| {
                     Rc::make_mut(dv).pop().unwrap()
                 });
                 return nameize(sess, ms, matches);
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 8e746676ecd..80b6794d1e3 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -86,7 +86,7 @@ impl TTMacroExpander for MacroRulesMacroExpander {
 
 fn trace_macros_note(cx: &mut ExtCtxt, sp: Span, message: String) {
     let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
-    let mut values: &mut Vec<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
+    let values: &mut Vec<String> = cx.expansions.entry(sp).or_insert_with(Vec::new);
     values.push(message);
 }
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index bf19a7e0383..cb0cc2aafb0 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1611,7 +1611,7 @@ fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate,
             if attr.check_name("feature") {
                 let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
                 span_err!(span_handler, attr.span, E0554,
-                          "#[feature] may not be used on the {} release channel",
+                          "#![feature] may not be used on the {} release channel",
                           release_channel);
             }
         }
diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs
index 83a164bdb96..85df4eee913 100644
--- a/src/libsyntax/parse/lexer/unicode_chars.rs
+++ b/src/libsyntax/parse/lexer/unicode_chars.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -9,15 +9,16 @@
 // except according to those terms.
 
 // Characters and their corresponding confusables were collected from
-// http://www.unicode.org/Public/security/revision-06/confusables.txt
+// http://www.unicode.org/Public/security/10.0.0/confusables.txt
 
 use syntax_pos::{Span, NO_EXPANSION};
 use errors::DiagnosticBuilder;
 use super::StringReader;
 
 const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
-    (' ', "No-Break Space", ' '),
-    (' ', "Ogham Space Mark", ' '),
+    ('
', "Line Separator", ' '),
+    ('
', "Paragraph Separator", ' '),
+    (' ', "Ogham Space mark", ' '),
     (' ', "En Quad", ' '),
     (' ', "Em Quad", ' '),
     (' ', "En Space", ' '),
@@ -25,39 +26,63 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     (' ', "Three-Per-Em Space", ' '),
     (' ', "Four-Per-Em Space", ' '),
     (' ', "Six-Per-Em Space", ' '),
-    (' ', "Figure Space", ' '),
     (' ', "Punctuation Space", ' '),
     (' ', "Thin Space", ' '),
     (' ', "Hair Space", ' '),
-    (' ', "Narrow No-Break Space", ' '),
     (' ', "Medium Mathematical Space", ' '),
+    (' ', "No-Break Space", ' '),
+    (' ', "Figure Space", ' '),
+    (' ', "Narrow No-Break Space", ' '),
     (' ', "Ideographic Space", ' '),
+
     ('ߺ', "Nko Lajanyalan", '_'),
     ('﹍', "Dashed Low Line", '_'),
     ('﹎', "Centreline Low Line", '_'),
     ('﹏', "Wavy Low Line", '_'),
+    ('_', "Fullwidth Low Line", '_'),
+
     ('‐', "Hyphen", '-'),
     ('‑', "Non-Breaking Hyphen", '-'),
     ('‒', "Figure Dash", '-'),
     ('–', "En Dash", '-'),
     ('—', "Em Dash", '-'),
     ('﹘', "Small Em Dash", '-'),
+    ('۔', "Arabic Full Stop", '-'),
     ('⁃', "Hyphen Bullet", '-'),
     ('˗', "Modifier Letter Minus Sign", '-'),
     ('−', "Minus Sign", '-'),
+    ('➖', "Heavy Minus Sign", '-'),
+    ('Ⲻ', "Coptic Letter Dialect-P Ni", '-'),
     ('ー', "Katakana-Hiragana Prolonged Sound Mark", '-'),
+    ('-', "Fullwidth Hyphen-Minus", '-'),
+    ('―', "Horizontal Bar", '-'),
+    ('─', "Box Drawings Light Horizontal", '-'),
+    ('━', "Box Drawings Heavy Horizontal", '-'),
+    ('㇐', "CJK Stroke H", '-'),
+    ('ꟷ', "Latin Epigraphic Letter Dideways", '-'),
+    ('ᅳ', "Hangul Jungseong Eu", '-'),
+    ('ㅡ', "Hangul Letter Eu", '-'),
+    ('一', "CJK Unified Ideograph-4E00", '-'),
+    ('⼀', "Kangxi Radical One", '-'),
+
+    ('؍', "Arabic Date Separator", ','),
     ('٫', "Arabic Decimal Separator", ','),
     ('‚', "Single Low-9 Quotation Mark", ','),
+    ('¸', "Cedilla", ','),
     ('ꓹ', "Lisu Letter Tone Na Po", ','),
     (',', "Fullwidth Comma", ','),
+
     (';', "Greek Question Mark", ';'),
     (';', "Fullwidth Semicolon", ';'),
+    ('︔', "Presentation Form For Vertical Semicolon", ';'),
+
     ('ः', "Devanagari Sign Visarga", ':'),
     ('ઃ', "Gujarati Sign Visarga", ':'),
     (':', "Fullwidth Colon", ':'),
     ('։', "Armenian Full Stop", ':'),
     ('܃', "Syriac Supralinear Colon", ':'),
     ('܄', "Syriac Sublinear Colon", ':'),
+    ('᛬', "Runic Multiple Ponctuation", ':'),
     ('︰', "Presentation Form For Vertical Two Dot Leader", ':'),
     ('᠃', "Mongolian Full Stop", ':'),
     ('᠉', "Mongolian Manchu Full Stop", ':'),
@@ -68,25 +93,48 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('∶', "Ratio", ':'),
     ('ː', "Modifier Letter Triangular Colon", ':'),
     ('ꓽ', "Lisu Letter Tone Mya Jeu", ':'),
+    ('︓', "Presentation Form For Vertical Colon", ':'),
+
     ('!', "Fullwidth Exclamation Mark", '!'),
     ('ǃ', "Latin Letter Retroflex Click", '!'),
+    ('ⵑ', "Tifinagh Letter Tuareg Yang", '!'),
+    ('︕', "Presentation Form For Vertical Exclamation Mark", '!'),
+
     ('ʔ', "Latin Letter Glottal Stop", '?'),
+    ('Ɂ', "Latin Capital Letter Glottal Stop", '?'),
     ('ॽ', "Devanagari Letter Glottal Stop", '?'),
     ('Ꭾ', "Cherokee Letter He", '?'),
+    ('ꛫ', "Bamum Letter Ntuu", '?'),
     ('?', "Fullwidth Question Mark", '?'),
+    ('︖', "Presentation Form For Vertical Question Mark", '?'),
+
     ('𝅭', "Musical Symbol Combining Augmentation Dot", '.'),
     ('․', "One Dot Leader", '.'),
-    ('۔', "Arabic Full Stop", '.'),
     ('܁', "Syriac Supralinear Full Stop", '.'),
     ('܂', "Syriac Sublinear Full Stop", '.'),
     ('꘎', "Vai Full Stop", '.'),
     ('𐩐', "Kharoshthi Punctuation Dot", '.'),
-    ('·', "Middle Dot", '.'),
     ('٠', "Arabic-Indic Digit Zero", '.'),
     ('۰', "Extended Arabic-Indic Digit Zero", '.'),
     ('ꓸ', "Lisu Letter Tone Mya Ti", '.'),
-    ('。', "Ideographic Full Stop", '.'),
+    ('·', "Middle Dot", '.'),
     ('・', "Katakana Middle Dot", '.'),
+    ('・', "Halfwidth Katakana Middle Dot", '.'),
+    ('᛫', "Runic Single Punctuation", '.'),
+    ('·', "Greek Ano Teleia", '.'),
+    ('⸱', "Word Separator Middle Dot", '.'),
+    ('𐄁', "Aegean Word Separator Dot", '.'),
+    ('•', "Bullet", '.'),
+    ('‧', "Hyphenation Point", '.'),
+    ('∙', "Bullet Operator", '.'),
+    ('⋅', "Dot Operator", '.'),
+    ('ꞏ', "Latin Letter Sinological Dot", '.'),
+    ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'),
+    ('ᐧ', "Canadian Syllabics Final Middle Dot", '.'),
+    ('.', "Fullwidth Full Stop", '.'),
+    ('。', "Ideographic Full Stop", '.'),
+    ('︒', "Presentation Form For Vertical Ideographic Full Stop", '.'),
+
     ('՝', "Armenian Comma", '\''),
     (''', "Fullwidth Apostrophe", '\''),
     ('‘', "Left Single Quotation Mark", '\''),
@@ -96,8 +144,10 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('‵', "Reversed Prime", '\''),
     ('՚', "Armenian Apostrophe", '\''),
     ('׳', "Hebrew Punctuation Geresh", '\''),
+    ('`', "Greek Accent", '\''),
     ('`', "Greek Varia", '\''),
     ('`', "Fullwidth Grave Accent", '\''),
+    ('´', "Acute Accent", '\''),
     ('΄', "Greek Tonos", '\''),
     ('´', "Greek Oxia", '\''),
     ('᾽', "Greek Koronis", '\''),
@@ -105,6 +155,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('῾', "Greek Dasia", '\''),
     ('ʹ', "Modifier Letter Prime", '\''),
     ('ʹ', "Greek Numeral Sign", '\''),
+    ('ˈ', "Modifier Letter Vertical Line", '\''),
     ('ˊ', "Modifier Letter Acute Accent", '\''),
     ('ˋ', "Modifier Letter Grave Accent", '\''),
     ('˴', "Modifier Letter Middle Grave Accent", '\''),
@@ -116,6 +167,12 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('י', "Hebrew Letter Yod", '\''),
     ('ߴ', "Nko High Tone Apostrophe", '\''),
     ('ߵ', "Nko Low Tone Apostrophe", '\''),
+    ('ᑊ', "Canadian Syllabics West-Cree P", '\''),
+    ('ᛌ', "Runic Letter Short-Twig-Sol S", '\''),
+    ('𖽑', "Miao Sign Aspiration", '\''),
+    ('𖽒', "Miao Sign Reformed Voicing", '\''),
+
+    ('᳓', "Vedic Sign Nihshvasa", '"'),
     ('"', "Fullwidth Quotation Mark", '"'),
     ('“', "Left Double Quotation Mark", '"'),
     ('”', "Right Double Quotation Mark", '"'),
@@ -132,12 +189,15 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'),
     ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'),
     ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'),
+
+    ('(', "Fullwidth Left Parenthesis", '('),
     ('❨', "Medium Left Parenthesis Ornament", '('),
     ('﴾', "Ornate Left Parenthesis", '('),
-    ('(', "Fullwidth Left Parenthesis", '('),
+
+    (')', "Fullwidth Right Parenthesis", ')'),
     ('❩', "Medium Right Parenthesis Ornament", ')'),
     ('﴿', "Ornate Right Parenthesis", ')'),
-    (')', "Fullwidth Right Parenthesis", ')'),
+
     ('[', "Fullwidth Left Square Bracket", '['),
     ('❲', "Light Left Tortoise Shell Bracket Ornament", '['),
     ('「', "Left Corner Bracket", '['),
@@ -147,6 +207,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('〖', "Left White Lenticular Bracket", '['),
     ('〘', "Left White Tortoise Shell Bracket", '['),
     ('〚', "Left White Square Bracket", '['),
+
     (']', "Fullwidth Right Square Bracket", ']'),
     ('❳', "Light Right Tortoise Shell Bracket Ornament", ']'),
     ('」', "Right Corner Bracket", ']'),
@@ -156,11 +217,20 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('〗', "Right White Lenticular Bracket", ']'),
     ('〙', "Right White Tortoise Shell Bracket", ']'),
     ('〛', "Right White Square Bracket", ']'),
+
     ('❴', "Medium Left Curly Bracket Ornament", '{'),
+    ('𝄔', "Musical Symbol Brace", '{'),
+    ('{', "Fullwidth Left Curly Bracket", '{'),
+
     ('❵', "Medium Right Curly Bracket Ornament", '}'),
+    ('}', "Fullwidth Right Curly Bracket", '}'),
+
     ('⁎', "Low Asterisk", '*'),
     ('٭', "Arabic Five Pointed Star", '*'),
     ('∗', "Asterisk Operator", '*'),
+    ('𐌟', "Old Italic Letter Ess", '*'),
+    ('*', "Fullwidth Asterisk", '*'),
+
     ('᜵', "Philippine Single Punctuation", '/'),
     ('⁁', "Caret Insertion Point", '/'),
     ('∕', "Division Slash", '/'),
@@ -168,37 +238,73 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
     ('╱', "Box Drawings Light Diagonal Upper Right To Lower Left", '/'),
     ('⟋', "Mathematical Rising Diagonal", '/'),
     ('⧸', "Big Solidus", '/'),
-    ('㇓', "Cjk Stroke Sp", '/'),
+    ('𝈺', "Greek Instrumental Notation Symbol-47", '/'),
+    ('㇓', "CJK Stroke Sp", '/'),
     ('〳', "Vertical Kana Repeat Mark Upper Half", '/'),
-    ('丿', "Cjk Unified Ideograph-4E3F", '/'),
+    ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'),
+    ('ノ', "Katakana Letter No", '/'),
+    ('丿', "CJK Unified Ideograph-4E3F", '/'),
     ('⼃', "Kangxi Radical Slash", '/'),
+    ('/', "Fullwidth Solidus", '/'),
+
     ('\', "Fullwidth Reverse Solidus", '\\'),
     ('﹨', "Small Reverse Solidus", '\\'),
     ('∖', "Set Minus", '\\'),
     ('⟍', "Mathematical Falling Diagonal", '\\'),
     ('⧵', "Reverse Solidus Operator", '\\'),
     ('⧹', "Big Reverse Solidus", '\\'),
+    ('⧹', "Greek Vocal Notation Symbol-16", '\\'),
+    ('⧹', "Greek Instrumental Symbol-48", '\\'),
+    ('㇔', "CJK Stroke D", '\\'),
+    ('丶', "CJK Unified Ideograph-4E36", '\\'),
+    ('⼂', "Kangxi Radical Dot", '\\'),
     ('、', "Ideographic Comma", '\\'),
     ('ヽ', "Katakana Iteration Mark", '\\'),
-    ('㇔', "Cjk Stroke D", '\\'),
-    ('丶', "Cjk Unified Ideograph-4E36", '\\'),
-    ('⼂', "Kangxi Radical Dot", '\\'),
+
     ('ꝸ', "Latin Small Letter Um", '&'),
+    ('&', "Fullwidth Ampersand", '&'),
+
+    ('᛭', "Runic Cros Punctuation", '+'),
+    ('➕', "Heavy Plus Sign", '+'),
+    ('𐊛', "Lycian Letter H", '+'),
     ('﬩', "Hebrew Letter Alternative Plus Sign", '+'),
+    ('+', "Fullwidth Plus Sign", '+'),
+
     ('‹', "Single Left-Pointing Angle Quotation Mark", '<'),
     ('❮', "Heavy Left-Pointing Angle Quotation Mark Ornament", '<'),
     ('˂', "Modifier Letter Left Arrowhead", '<'),
+    ('𝈶', "Greek Instrumental Symbol-40", '<'),
+    ('ᐸ', "Canadian Syllabics Pa", '<'),
+    ('ᚲ', "Runic Letter Kauna", '<'),
+    ('❬', "Medium Left-Pointing Angle Bracket Ornament", '<'),
+    ('⟨', "Mathematical Left Angle Bracket", '<'),
+    ('〈', "Left-Pointing Angle Bracket", '<'),
     ('〈', "Left Angle Bracket", '<'),
+    ('㇛', "CJK Stroke Pd", '<'),
+    ('く', "Hiragana Letter Ku", '<'),
+    ('𡿨', "CJK Unified Ideograph-21FE8", '<'),
     ('《', "Left Double Angle Bracket", '<'),
+    ('<', "Fullwidth Less-Than Sign", '<'),
+
+    ('᐀', "Canadian Syllabics Hyphen", '='),
+    ('⹀', "Double Hyphen", '='),
+    ('゠', "Katakana-Hiragana Double Hyphen", '='),
     ('꓿', "Lisu Punctuation Full Stop", '='),
+    ('=', "Fullwidth Equals Sign", '='),
+
     ('›', "Single Right-Pointing Angle Quotation Mark", '>'),
     ('❯', "Heavy Right-Pointing Angle Quotation Mark Ornament", '>'),
     ('˃', "Modifier Letter Right Arrowhead", '>'),
+    ('𝈷', "Greek Instrumental Symbol-42", '>'),
+    ('ᐳ', "Canadian Syllabics Po", '>'),
+    ('𖼿', "Miao Letter Archaic Zza", '>'),
+    ('❭', "Medium Right-Pointing Angle Bracket Ornament", '>'),
+    ('⟩', "Mathematical Right Angle Bracket", '>'),
+    ('〉', "Right-Pointing Angle Bracket", '>'),
     ('〉', "Right Angle Bracket", '>'),
     ('》', "Right Double Angle Bracket", '>'),
-    ('Ⲻ', "Coptic Capital Letter Dialect-P Ni", '-'),
-    ('Ɂ', "Latin Capital Letter Glottal Stop", '?'),
-    ('Ⳇ', "Coptic Capital Letter Old Coptic Esh", '/'), ];
+    ('>', "Fullwidth Greater-Than Sign", '>'), ];
+
 
 const ASCII_ARRAY: &'static [(char, &'static str)] = &[
     (' ', "Space"),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5fe3cf0ddac..df1bae523a5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5526,12 +5526,11 @@ impl<'a> Parser<'a> {
         })
     }
 
-    /// Parse a static item from a foreign module
+    /// Parse a static item from a foreign module.
+    /// Assumes that the `static` keyword is already parsed.
     fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
                                  -> PResult<'a, ForeignItem> {
-        self.expect_keyword(keywords::Static)?;
         let mutbl = self.eat_keyword(keywords::Mut);
-
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
@@ -6005,19 +6004,23 @@ impl<'a> Parser<'a> {
         let lo = self.span;
         let visibility = self.parse_visibility(false)?;
 
-        if self.check_keyword(keywords::Static) {
-            // FOREIGN STATIC ITEM
+        // FOREIGN STATIC ITEM
+        // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
+        if self.check_keyword(keywords::Static) || self.token.is_keyword(keywords::Const) {
+            if self.token.is_keyword(keywords::Const) {
+                self.diagnostic()
+                    .struct_span_err(self.span, "extern items cannot be `const`")
+                    .span_suggestion(self.span, "instead try using", "static".to_owned())
+                    .emit();
+            }
+            self.bump(); // `static` or `const`
             return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?));
         }
+        // FOREIGN FUNCTION ITEM
         if self.check_keyword(keywords::Fn) {
-            // FOREIGN FUNCTION ITEM
             return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
         }
 
-        if self.check_keyword(keywords::Const) {
-            return Err(self.span_fatal(self.span, "extern items cannot be `const`"));
-        }
-
         // FIXME #5668: this will occur for a macro invocation:
         match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? {
             Some(item) => {
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 9734bb867f1..16b06424c92 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -529,7 +529,7 @@ impl<'a, 'b> Context<'a, 'b> {
 
     /// Actually builds the expression which the format_args! block will be
     /// expanded to
-    fn into_expr(mut self) -> P<ast::Expr> {
+    fn into_expr(self) -> P<ast::Expr> {
         let mut locals = Vec::new();
         let mut counts = Vec::new();
         let mut pats = Vec::new();
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 8ba07c35b05..5eab81dd28f 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -89,6 +89,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
     use syntax::ext::source_util::*;
     register! {
         line: expand_line,
+        __rust_unstable_column: expand_column_gated,
         column: expand_column,
         file: expand_file,
         stringify: expand_stringify,
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index bca0881c08c..ba0c4fbe173 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -278,10 +278,12 @@ static Optional<Reloc::Model> fromRust(LLVMRustRelocMode RustReloc) {
     return Reloc::RWPI;
   case LLVMRustRelocMode::ROPIRWPI:
     return Reloc::ROPI_RWPI;
-#endif
+#else
   default:
-    llvm_unreachable("Bad RelocModel.");
+    break;
+#endif
   }
+  llvm_unreachable("Bad RelocModel.");
 }
 
 #if LLVM_RUSTLLVM
diff --git a/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs b/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs
index 508f8dac571..f42d1006bf5 100644
--- a/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs
+++ b/src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs
@@ -11,6 +11,7 @@
 // aux-build:attributes-included.rs
 
 #![feature(proc_macro, rustc_attrs)]
+#![warn(unused)]
 
 extern crate attributes_included;
 
diff --git a/src/test/compile-fail/E0010.rs b/src/test/compile-fail/E0010.rs
index 8a666168c86..ccaf01932d4 100644
--- a/src/test/compile-fail/E0010.rs
+++ b/src/test/compile-fail/E0010.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(box_syntax)]
+#![allow(warnings)]
 
 const CON : Box<i32> = box 0; //~ ERROR E0010
                               //~| NOTE allocation not allowed in
diff --git a/src/test/compile-fail/E0394.rs b/src/test/compile-fail/E0394.rs
index e35d038248c..c7d5665cd2c 100644
--- a/src/test/compile-fail/E0394.rs
+++ b/src/test/compile-fail/E0394.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(warnings)]
+
 static A: u32 = 0;
 static B: u32 = A;
 //~^ ERROR E0394
diff --git a/src/test/compile-fail/bad-lint-cap2.rs b/src/test/compile-fail/bad-lint-cap2.rs
index 5a97d7b1a79..cb9fb973a01 100644
--- a/src/test/compile-fail/bad-lint-cap2.rs
+++ b/src/test/compile-fail/bad-lint-cap2.rs
@@ -10,6 +10,7 @@
 
 // compile-flags: --cap-lints deny
 
+#![warn(unused)]
 #![deny(warnings)]
 
 use std::option; //~ ERROR
diff --git a/src/test/compile-fail/bad-lint-cap3.rs b/src/test/compile-fail/bad-lint-cap3.rs
index e03ba6ecb64..c9394954c5f 100644
--- a/src/test/compile-fail/bad-lint-cap3.rs
+++ b/src/test/compile-fail/bad-lint-cap3.rs
@@ -10,6 +10,7 @@
 
 // compile-flags: --cap-lints warn
 
+#![warn(unused)]
 #![deny(warnings)]
 #![feature(rustc_attrs)]
 
diff --git a/src/test/compile-fail/check-static-values-constraints.rs b/src/test/compile-fail/check-static-values-constraints.rs
index f65968e0e11..3642add3259 100644
--- a/src/test/compile-fail/check-static-values-constraints.rs
+++ b/src/test/compile-fail/check-static-values-constraints.rs
@@ -12,6 +12,7 @@
 
 // gate-test-drop_types_in_const
 
+#![allow(warnings)]
 #![feature(box_syntax)]
 
 use std::marker;
diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs
index 9b045ed1d02..0fd41a17b2c 100644
--- a/src/test/compile-fail/const-eval-overflow-2.rs
+++ b/src/test/compile-fail/const-eval-overflow-2.rs
@@ -11,7 +11,7 @@
 // Evaluation of constants in refutable patterns goes through
 // different compiler control-flow paths.
 
-#![allow(unused_imports)]
+#![allow(unused_imports, warnings)]
 
 use std::fmt;
 use std::{i8, i16, i32, i64, isize};
diff --git a/src/test/compile-fail/const-match-pattern-arm.rs b/src/test/compile-fail/const-match-pattern-arm.rs
index 452aa87d6ba..bc944948f3d 100644
--- a/src/test/compile-fail/const-match-pattern-arm.rs
+++ b/src/test/compile-fail/const-match-pattern-arm.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(warnings)]
+
 const x: bool = match Some(true) {
     Some(value) => true,
     //~^ ERROR: constant contains unimplemented expression type [E0019]
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs
index d9664fda2b3..360895d30b0 100644
--- a/src/test/compile-fail/feature-gate-dropck-ugeh.rs
+++ b/src/test/compile-fail/feature-gate-dropck-ugeh.rs
@@ -28,7 +28,6 @@ struct Foo<T> { data: Vec<T> }
 impl<T> Drop for Foo<T> {
     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
     //~^ ERROR unsafe_destructor_blind_to_params has been replaced
-    //~^^ WARN: use of deprecated attribute
     fn drop(&mut self) { }
 }
 
diff --git a/src/test/compile-fail/issue-14227.rs b/src/test/compile-fail/issue-14227.rs
index c4846a64f29..d8f9f5543e4 100644
--- a/src/test/compile-fail/issue-14227.rs
+++ b/src/test/compile-fail/issue-14227.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(safe_extern_statics, warnings)]
+
 extern {
     pub static symbol: ();
 }
diff --git a/src/test/compile-fail/issue-16538.rs b/src/test/compile-fail/issue-16538.rs
index 6c41450796c..08c3f7a7c15 100644
--- a/src/test/compile-fail/issue-16538.rs
+++ b/src/test/compile-fail/issue-16538.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(safe_extern_statics)]
+
 mod Y {
     pub type X = usize;
     extern {
diff --git a/src/test/compile-fail/issue-17450.rs b/src/test/compile-fail/issue-17450.rs
index 5471d8522df..cde1bbbe492 100644
--- a/src/test/compile-fail/issue-17450.rs
+++ b/src/test/compile-fail/issue-17450.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(dead_code)]
+#![allow(dead_code, warnings)]
 
 static mut x: isize = 3;
 static mut y: isize = unsafe {
diff --git a/src/test/compile-fail/issue-17718-const-naming.rs b/src/test/compile-fail/issue-17718-const-naming.rs
index 06719e2756b..4857c2fb446 100644
--- a/src/test/compile-fail/issue-17718-const-naming.rs
+++ b/src/test/compile-fail/issue-17718-const-naming.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![warn(unused)]
 #[deny(warnings)]
 
 const foo: isize = 3;
diff --git a/src/test/compile-fail/issue-17718-references.rs b/src/test/compile-fail/issue-17718-references.rs
index c159168030b..8e0df283cdb 100644
--- a/src/test/compile-fail/issue-17718-references.rs
+++ b/src/test/compile-fail/issue-17718-references.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(warnings)]
+
 struct Struct { a: usize }
 
 const C: usize = 1;
diff --git a/src/test/compile-fail/issue-18937.rs b/src/test/compile-fail/issue-18937.rs
index f57f3477a8a..5996c8e5438 100644
--- a/src/test/compile-fail/issue-18937.rs
+++ b/src/test/compile-fail/issue-18937.rs
@@ -26,7 +26,7 @@ trait A<'a> {
 }
 
 impl<'a> A<'a> for B {
-    fn foo<F>(&mut self, f: F) //~ ERROR E0276
+    fn foo<F>(&mut self, f: F) //~ ERROR impl has stricter
         //~^ WARNING future release
         where F: fmt::Debug + 'static,
     {
diff --git a/src/test/compile-fail/issue-28075.rs b/src/test/compile-fail/issue-28075.rs
index cd73a456411..057c99f9305 100644
--- a/src/test/compile-fail/issue-28075.rs
+++ b/src/test/compile-fail/issue-28075.rs
@@ -12,7 +12,7 @@
 
 // aux-build:lint_stability.rs
 
-#![allow(unused_imports)]
+#![allow(warnings)]
 
 extern crate lint_stability;
 
diff --git a/src/test/compile-fail/issue-28113.rs b/src/test/compile-fail/issue-28113.rs
index 5c697b69c80..7d2541966a4 100644
--- a/src/test/compile-fail/issue-28113.rs
+++ b/src/test/compile-fail/issue-28113.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(warnings)]
+
 const X: u8 =
     || -> u8 { 5 }()
     //~^ ERROR calls in constants are limited to constant functions
diff --git a/src/test/compile-fail/issue-28324.rs b/src/test/compile-fail/issue-28324.rs
index 13ce41f4dcc..3c4d6b42b50 100644
--- a/src/test/compile-fail/issue-28324.rs
+++ b/src/test/compile-fail/issue-28324.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(safe_extern_statics)]
+
 extern {
     static error_message_count: u32;
 }
diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs
index 086938334c7..d1af39a6c18 100644
--- a/src/test/compile-fail/issue-30730.rs
+++ b/src/test/compile-fail/issue-30730.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![warn(unused)]
 #![deny(warnings)] //~ NOTE: lint level defined here
 use std::thread;
 //~^ ERROR: unused import
diff --git a/src/test/compile-fail/issue-37515.rs b/src/test/compile-fail/issue-37515.rs
index fa452d6e74a..d5733f98193 100644
--- a/src/test/compile-fail/issue-37515.rs
+++ b/src/test/compile-fail/issue-37515.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(rustc_attrs)]
+#![warn(unused)]
 
 type Z = for<'x> Send;
 //~^ WARN type alias is never used
diff --git a/src/test/compile-fail/issue-7364.rs b/src/test/compile-fail/issue-7364.rs
index 16b407baad1..bd32317ae78 100644
--- a/src/test/compile-fail/issue-7364.rs
+++ b/src/test/compile-fail/issue-7364.rs
@@ -10,6 +10,7 @@
 
 #![feature(box_syntax)]
 #![feature(const_fn)]
+#![allow(warnings)]
 
 use std::cell::RefCell;
 
diff --git a/src/test/compile-fail/lint-removed-allow.rs b/src/test/compile-fail/lint-removed-allow.rs
index 1498ed4d17e..9f84190ea18 100644
--- a/src/test/compile-fail/lint-removed-allow.rs
+++ b/src/test/compile-fail/lint-removed-allow.rs
@@ -11,7 +11,8 @@
 // No warnings about removed lint when
 // allow(renamed_and_removed_lints)
 
+#![allow(renamed_and_removed_lints)]
+
 #[deny(raw_pointer_derive)]
-#[allow(renamed_and_removed_lints)]
 #[deny(unused_variables)]
 fn main() { let unused = (); } //~ ERROR unused
diff --git a/src/test/compile-fail/lint-removed-cmdline.rs b/src/test/compile-fail/lint-removed-cmdline.rs
index d6bfd1eec39..e1da5086612 100644
--- a/src/test/compile-fail/lint-removed-cmdline.rs
+++ b/src/test/compile-fail/lint-removed-cmdline.rs
@@ -16,5 +16,7 @@
 // error-pattern:lint raw_pointer_derive has been removed
 // error-pattern:requested on the command line with `-D raw_pointer_derive`
 
+#![warn(unused)]
+
 #[deny(warnings)]
 fn main() { let unused = (); }
diff --git a/src/test/compile-fail/lint-renamed-allow.rs b/src/test/compile-fail/lint-renamed-allow.rs
index ea26c3656e6..ae010b64bfd 100644
--- a/src/test/compile-fail/lint-renamed-allow.rs
+++ b/src/test/compile-fail/lint-renamed-allow.rs
@@ -11,7 +11,8 @@
 // No warnings about renamed lint when
 // allow(renamed_and_removed_lints)
 
+#![allow(renamed_and_removed_lints)]
+
 #[deny(unknown_features)]
-#[allow(renamed_and_removed_lints)]
 #[deny(unused)]
 fn main() { let unused = (); } //~ ERROR unused
diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs
index d8813b6a610..8443518b3f5 100644
--- a/src/test/compile-fail/lint-stability-deprecated.rs
+++ b/src/test/compile-fail/lint-stability-deprecated.rs
@@ -13,9 +13,9 @@
 // aux-build:stability_cfg1.rs
 // aux-build:stability_cfg2.rs
 
-#![deny(deprecated)]
+#![warn(deprecated)]
 #![allow(dead_code)]
-#![feature(staged_api, test_feature)]
+#![feature(staged_api, test_feature, rustc_attrs)]
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -32,41 +32,41 @@ mod cross_crate {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ ERROR use of deprecated item
-        foo.method_deprecated(); //~ ERROR use of deprecated item
-        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-
-        deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
-        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-
-        deprecated_unstable(); //~ ERROR use of deprecated item
-        foo.method_deprecated_unstable(); //~ ERROR use of deprecated item
-        Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo>::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-
-        deprecated_unstable_text(); //~ ERROR use of deprecated item: text
-        foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
-        Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        deprecated(); //~ WARN use of deprecated item
+        foo.method_deprecated(); //~ WARN use of deprecated item
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item
+        foo.trait_deprecated(); //~ WARN use of deprecated item
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
+
+        deprecated_text(); //~ WARN use of deprecated item: text
+        foo.method_deprecated_text(); //~ WARN use of deprecated item: text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+
+        deprecated_unstable(); //~ WARN use of deprecated item
+        foo.method_deprecated_unstable(); //~ WARN use of deprecated item
+        Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+
+        deprecated_unstable_text(); //~ WARN use of deprecated item: text
+        foo.method_deprecated_unstable_text(); //~ WARN use of deprecated item: text
+        Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
 
         unstable();
         foo.method_unstable();
@@ -106,30 +106,30 @@ mod cross_crate {
 
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
-        //~^ ERROR use of deprecated item
+        //~^ WARN use of deprecated item
 
-        let _ = DeprecatedStruct { //~ ERROR use of deprecated item
-            i: 0 //~ ERROR use of deprecated item
+        let _ = DeprecatedStruct { //~ WARN use of deprecated item
+            i: 0 //~ WARN use of deprecated item
         };
         let _ = DeprecatedUnstableStruct {
-            //~^ ERROR use of deprecated item
-            i: 0 //~ ERROR use of deprecated item
+            //~^ WARN use of deprecated item
+            i: 0 //~ WARN use of deprecated item
         };
         let _ = UnstableStruct { i: 0 };
         let _ = StableStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
-        let _ = DeprecatedUnstableUnitStruct; //~ ERROR use of deprecated item
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item
+        let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated item
         let _ = UnstableUnitStruct;
         let _ = StableUnitStruct;
 
-        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
-        let _ = Enum::DeprecatedUnstableVariant; //~ ERROR use of deprecated item
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item
+        let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated item
         let _ = Enum::UnstableVariant;
         let _ = Enum::StableVariant;
 
-        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
-        let _ = DeprecatedUnstableTupleStruct (1); //~ ERROR use of deprecated item
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item
+        let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated item
         let _ = UnstableTupleStruct (1);
         let _ = StableTupleStruct (1);
 
@@ -138,28 +138,28 @@ mod cross_crate {
         // Eventually, we will want to lint the contents of the
         // macro in the module *defining* it. Also, stability levels
         // on macros themselves are not yet linted.
-        macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text
-        macro_test_arg!(deprecated_unstable_text()); //~ ERROR use of deprecated item: text
-        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
+        macro_test_arg!(deprecated_text()); //~ WARN use of deprecated item: text
+        macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated item: text
+        macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated item: text
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item
+        Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated item
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text
+        Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated item: text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -175,10 +175,10 @@ mod cross_crate {
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
-        foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
+        foo.trait_deprecated_unstable(); //~ WARN use of deprecated item
+        foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated item: text
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_stable();
@@ -187,9 +187,9 @@ mod cross_crate {
     struct S;
 
     impl UnstableTrait for S { }
-    impl DeprecatedTrait for S {} //~ ERROR use of deprecated item: text
+    impl DeprecatedTrait for S {} //~ WARN use of deprecated item: text
     trait LocalTrait : UnstableTrait { }
-    trait LocalTrait2 : DeprecatedTrait { } //~ ERROR use of deprecated item: text
+    trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated item: text
 
     impl Trait for S {
         fn trait_stable(&self) {}
@@ -208,7 +208,7 @@ mod inheritance {
         stable_mod::unstable();
         stable_mod::stable();
 
-        unstable_mod::deprecated(); //~ ERROR use of deprecated item
+        unstable_mod::deprecated(); //~ WARN use of deprecated item
         unstable_mod::unstable();
 
         let _ = Unstable::UnstableVariant;
@@ -330,23 +330,23 @@ mod this_crate {
         type Foo = MethodTester;
         let foo = MethodTester;
 
-        deprecated(); //~ ERROR use of deprecated item
-        foo.method_deprecated(); //~ ERROR use of deprecated item
-        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-
-        deprecated_text(); //~ ERROR use of deprecated item: text
-        foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
-        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        deprecated(); //~ WARN use of deprecated item
+        foo.method_deprecated(); //~ WARN use of deprecated item
+        Foo::method_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::method_deprecated(&foo); //~ WARN use of deprecated item
+        foo.trait_deprecated(); //~ WARN use of deprecated item
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
+
+        deprecated_text(); //~ WARN use of deprecated item: text
+        foo.method_deprecated_text(); //~ WARN use of deprecated item: text
+        Foo::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
 
         unstable();
         foo.method_unstable();
@@ -385,34 +385,34 @@ mod this_crate {
         <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct {
-            //~^ ERROR use of deprecated item
-            i: 0 //~ ERROR use of deprecated item
+            //~^ WARN use of deprecated item
+            i: 0 //~ WARN use of deprecated item
         };
         let _ = UnstableStruct { i: 0 };
         let _ = StableStruct { i: 0 };
 
-        let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
+        let _ = DeprecatedUnitStruct; //~ WARN use of deprecated item
         let _ = UnstableUnitStruct;
         let _ = StableUnitStruct;
 
-        let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
+        let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated item
         let _ = Enum::UnstableVariant;
         let _ = Enum::StableVariant;
 
-        let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
+        let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated item
         let _ = UnstableTupleStruct (1);
         let _ = StableTupleStruct (1);
     }
 
     fn test_method_param<Foo: Trait>(foo: Foo) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
-        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
-        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item
+        Trait::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated item
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated item: text
         foo.trait_unstable();
         Trait::trait_unstable(&foo);
         <Foo>::trait_unstable(&foo);
@@ -428,8 +428,8 @@ mod this_crate {
     }
 
     fn test_method_object(foo: &Trait) {
-        foo.trait_deprecated(); //~ ERROR use of deprecated item
-        foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        foo.trait_deprecated(); //~ WARN use of deprecated item
+        foo.trait_deprecated_text(); //~ WARN use of deprecated item: text
         foo.trait_unstable();
         foo.trait_unstable_text();
         foo.trait_stable();
@@ -439,7 +439,7 @@ mod this_crate {
     #[rustc_deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
-        fn_in_body(); //~ ERROR use of deprecated item: text
+        fn_in_body(); //~ WARN use of deprecated item: text
     }
 
     impl MethodTester {
@@ -447,7 +447,7 @@ mod this_crate {
         #[rustc_deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
-            fn_in_body(); //~ ERROR use of deprecated item: text
+            fn_in_body(); //~ WARN use of deprecated item: text
         }
     }
 
@@ -459,9 +459,9 @@ mod this_crate {
 
     struct S;
 
-    impl DeprecatedTrait for S { } //~ ERROR use of deprecated item
+    impl DeprecatedTrait for S { } //~ WARN use of deprecated item
 
-    trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item
+    trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated item
 }
 
-fn main() {}
+#[rustc_error] fn main() {} //~ ERROR: compilation successful
diff --git a/src/test/compile-fail/lint-type-overflow2.rs b/src/test/compile-fail/lint-type-overflow2.rs
index d399fda3286..55934997583 100644
--- a/src/test/compile-fail/lint-type-overflow2.rs
+++ b/src/test/compile-fail/lint-type-overflow2.rs
@@ -9,16 +9,18 @@
 // except according to those terms.
 //
 
-#![deny(overflowing_literals)]
-#![deny(const_err)]
+#![warn(overflowing_literals)]
+#![warn(const_err)]
+#![feature(rustc_attrs)]
 
 #[allow(unused_variables)]
-fn main() {
-    let x2: i8 = --128; //~ error: literal out of range for i8
-    //~^ error: attempt to negate with overflow
+#[rustc_error]
+fn main() { //~ ERROR: compilation successful
+    let x2: i8 = --128; //~ warn: literal out of range for i8
+    //~^ warn: attempt to negate with overflow
 
-    let x = -3.40282357e+38_f32; //~ error: literal out of range for f32
-    let x =  3.40282357e+38_f32; //~ error: literal out of range for f32
-    let x = -1.7976931348623159e+308_f64; //~ error: literal out of range for f64
-    let x =  1.7976931348623159e+308_f64; //~ error: literal out of range for f64
+    let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32
+    let x =  3.40282357e+38_f32; //~ warn: literal out of range for f32
+    let x = -1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
+    let x =  1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
 }
diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs
index 21cfadb9c79..26d00755da3 100644
--- a/src/test/compile-fail/lint-unused-mut-variables.rs
+++ b/src/test/compile-fail/lint-unused-mut-variables.rs
@@ -47,6 +47,26 @@ fn main() {
     let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable
     fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable
 
+    let mut a = &mut 5; //~ ERROR: variable does not need to be mutable
+    *a = 4;
+
+    let mut a = 5;
+    let mut b = (&mut a,);
+    *b.0 = 4; //~^ ERROR: variable does not need to be mutable
+
+    let mut x = &mut 1; //~ ERROR: variable does not need to be mutable
+    let mut f = || {
+      *x += 1;
+    };
+    f();
+
+    fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
+        &mut arg[..] //~^ ERROR: variable does not need to be mutable
+    }
+
+    let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable
+    v.push(());
+
     // positive cases
     let mut a = 2;
     a = 3;
diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs
index 1615af40071..1d947684792 100644
--- a/src/test/compile-fail/lint-uppercase-variables.rs
+++ b/src/test/compile-fail/lint-uppercase-variables.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![warn(unused)]
 #![allow(dead_code)]
 #![deny(non_snake_case)]
 
diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs
index 3aab953eb79..d056d6be806 100644
--- a/src/test/compile-fail/liveness-unused.rs
+++ b/src/test/compile-fail/liveness-unused.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![warn(unused)]
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
 #![allow(dead_code, non_camel_case_types, trivial_numeric_casts)]
diff --git a/src/test/compile-fail/never-assign-dead-code.rs b/src/test/compile-fail/never-assign-dead-code.rs
index d8752e1c050..1e0cc0f5357 100644
--- a/src/test/compile-fail/never-assign-dead-code.rs
+++ b/src/test/compile-fail/never-assign-dead-code.rs
@@ -10,12 +10,12 @@
 
 // Test that an assignment of type ! makes the rest of the block dead code.
 
-#![feature(never_type)]
-#![deny(unused, unreachable_code)]
+#![feature(never_type, rustc_attrs)]
+#![warn(unused)]
 
-fn main() {
-    let x: ! = panic!("aah"); //~ ERROR unused
-    drop(x); //~ ERROR unreachable
-    //~^ ERROR unreachable
+#[rustc_error]
+fn main() { //~ ERROR: compilation successful
+    let x: ! = panic!("aah"); //~ WARN unused
+    drop(x); //~ WARN unreachable
+    //~^ WARN unreachable
 }
-
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
index 140891027d5..4d41f8ba47d 100644
--- a/src/test/compile-fail/private-inferred-type.rs
+++ b/src/test/compile-fail/private-inferred-type.rs
@@ -11,6 +11,7 @@
 #![feature(associated_consts)]
 #![feature(conservative_impl_trait)]
 #![feature(decl_macro)]
+#![allow(warnings)]
 
 mod m {
     fn priv_fn() {}
diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs
index 925d692f8ae..a5581664f74 100644
--- a/src/test/compile-fail/private-type-in-interface.rs
+++ b/src/test/compile-fail/private-type-in-interface.rs
@@ -11,6 +11,7 @@
 // aux-build:private-inferred-type.rs
 
 #![feature(conservative_impl_trait)]
+#![allow(warnings)]
 
 extern crate private_inferred_type as ext;
 
diff --git a/src/test/compile-fail/rust-unstable-column-gated.rs b/src/test/compile-fail/rust-unstable-column-gated.rs
new file mode 100644
index 00000000000..abc92c86eec
--- /dev/null
+++ b/src/test/compile-fail/rust-unstable-column-gated.rs
@@ -0,0 +1,14 @@
+// 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.
+
+fn main() {
+    println!("{}", __rust_unstable_column!());
+    //~^ERROR the __rust_unstable_column macro is unstable
+}
diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs
index 7c37abf7657..a855b08f066 100644
--- a/src/test/compile-fail/static-mut-not-constant.rs
+++ b/src/test/compile-fail/static-mut-not-constant.rs
@@ -14,6 +14,7 @@
 
 static mut a: Box<isize> = box 3;
 //~^ ERROR allocations are not allowed in statics
-//~^^ ERROR destructors in statics are an unstable feature
+//~| ERROR destructors in statics are an unstable feature
+//~| WARN: constant evaluation error
 
 fn main() {}
diff --git a/src/test/compile-fail/struct-path-self-type-mismatch.rs b/src/test/compile-fail/struct-path-self-type-mismatch.rs
index f694e7d277c..ad568b41fcb 100644
--- a/src/test/compile-fail/struct-path-self-type-mismatch.rs
+++ b/src/test/compile-fail/struct-path-self-type-mismatch.rs
@@ -20,17 +20,15 @@ impl Bar for Foo<i32> {
 }
 
 impl<T> Foo<T> {
-    fn new<U>(u: U) -> Foo<U> {
+    fn new<U>(u: U) -> Foo<U> { //~ NOTE expected `Foo<U>` because of return type
         Self {
         //~^ ERROR mismatched types
-        //~| expected type parameter, found a different type parameter
-        //~| expected type `Foo<U>`
-        //~| found type `Foo<T>`
+        //~| NOTE expected type parameter, found a different type parameter
+        //~| NOTE expected type `Foo<U>`
             inner: u
             //~^ ERROR mismatched types
-            //~| expected type parameter, found a different type parameter
-            //~| expected type `T`
-            //~| found type `U`
+            //~| NOTE expected type parameter, found a different type parameter
+            //~| NOTE expected type `T`
         }
     }
 }
diff --git a/src/test/compile-fail/unreachable-try-pattern.rs b/src/test/compile-fail/unreachable-try-pattern.rs
index f4817ba33b5..46ea4a06a3b 100644
--- a/src/test/compile-fail/unreachable-try-pattern.rs
+++ b/src/test/compile-fail/unreachable-try-pattern.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(never_type)]
-#![deny(unreachable_code)]
-#![deny(unreachable_patterns)]
+#![feature(never_type, rustc_attrs)]
+#![warn(unreachable_code)]
+#![warn(unreachable_patterns)]
 
 enum Void {}
 
@@ -26,8 +26,8 @@ fn bar(x: Result<!, i32>) -> Result<u32, i32> {
 
 fn foo(x: Result<!, i32>) -> Result<u32, i32> {
     let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?;
-    //~^ ERROR unreachable pattern
-    //~| ERROR unreachable expression
+    //~^ WARN unreachable pattern
+    //~| WARN unreachable expression
     Ok(y)
 }
 
@@ -37,11 +37,12 @@ fn qux(x: Result<u32, Void>) -> Result<u32, i32> {
 
 fn vom(x: Result<u32, Void>) -> Result<u32, i32> {
     let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?;
-    //~^ ERROR unreachable pattern
+    //~^ WARN unreachable pattern
     Ok(y)
 }
 
-fn main() {
+#[rustc_error]
+fn main() { //~ ERROR: compilation successful
     let _ = bar(Err(123));
     let _ = foo(Err(123));
     let _ = qux(Ok(123));
diff --git a/src/test/run-pass/issue-43057.rs b/src/test/run-pass/issue-43057.rs
new file mode 100644
index 00000000000..152ddfb193f
--- /dev/null
+++ b/src/test/run-pass/issue-43057.rs
@@ -0,0 +1,23 @@
+// 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.
+
+#![allow(unused)]
+
+macro_rules! column {
+    ($i:ident) => {
+        $i
+    };
+}
+
+fn foo() -> ! {
+    panic!();
+}
+
+fn main() {}
diff --git a/src/test/rustdoc/nul-error.rs b/src/test/rustdoc/nul-error.rs
new file mode 100644
index 00000000000..2c9d07f190d
--- /dev/null
+++ b/src/test/rustdoc/nul-error.rs
@@ -0,0 +1,18 @@
+// 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.
+
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html '//code' ''
+#[doc = "Attempted to pass a string containing `\0`"]
+pub fn foo() {}
diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs
index 1e428629cc2..19ce2362134 100644
--- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs
+++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.rs
@@ -14,6 +14,7 @@
 // compile-flags: -A test-lint
 
 #![feature(plugin)]
+#![warn(unused)]
 #![plugin(lint_plugin_test)]
 
 fn lintme() { }
diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
index b8513b95d36..7c9c4e99039 100644
--- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
@@ -1,8 +1,13 @@
 warning: function is never used: `lintme`
-  --> $DIR/lint-plugin-cmdline-allow.rs:19:1
+  --> $DIR/lint-plugin-cmdline-allow.rs:20:1
    |
-19 | fn lintme() { }
+20 | fn lintme() { }
    | ^^^^^^^^^^^^^^^
    |
-   = note: #[warn(dead_code)] on by default
+note: lint level defined here
+  --> $DIR/lint-plugin-cmdline-allow.rs:17:9
+   |
+17 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
 
diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr
index f60a0c2e5f6..20c7dc416f3 100644
--- a/src/test/ui/block-result/block-must-not-have-result-res.stderr
+++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/block-must-not-have-result-res.rs:15:9
    |
+14 |     fn drop(&mut self) {
+   |                        - expected `()` because of default return type
 15 |         true //~  ERROR mismatched types
    |         ^^^^ expected (), found bool
    |
diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr
index 41113eb7a57..cd8c28cd2cf 100644
--- a/src/test/ui/block-result/issue-13624.stderr
+++ b/src/test/ui/block-result/issue-13624.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-13624.rs:17:5
    |
+16 |   pub fn get_enum_struct_variant() -> () {
+   |                                       -- expected `()` because of return type
 17 |     Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
    |
diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr
index a9bcc8bea94..c6113ae0c9f 100644
--- a/src/test/ui/block-result/issue-22645.stderr
+++ b/src/test/ui/block-result/issue-22645.stderr
@@ -11,6 +11,9 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
 error[E0308]: mismatched types
   --> $DIR/issue-22645.rs:25:3
    |
+23 | fn main() {
+   |           - expected `()` because of default return type
+24 |   let b = Bob + 3.5;
 25 |   b + 3 //~ ERROR E0277
    |   ^^^^^ expected (), found struct `Bob`
    |
diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr
index bd670a14f24..29dbd5a8cf5 100644
--- a/src/test/ui/block-result/issue-5500.stderr
+++ b/src/test/ui/block-result/issue-5500.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-5500.rs:12:5
    |
+11 | fn main() {
+   |           - expected `()` because of default return type
 12 |     &panic!()
    |     ^^^^^^^^^ expected (), found reference
    |
diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs
index c77fa74f6e0..108d7e1ea22 100644
--- a/src/test/ui/check_match/issue-43253.rs
+++ b/src/test/ui/check_match/issue-43253.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(exclusive_range_pattern)]
+#![warn(unreachable_patterns)]
 
 fn main() {
     // These cases should generate no warning.
@@ -48,4 +49,4 @@ fn main() {
         9...9 => {},
         _ => {},
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr
index 0d4a2ecf512..a1cb3963914 100644
--- a/src/test/ui/check_match/issue-43253.stderr
+++ b/src/test/ui/check_match/issue-43253.stderr
@@ -1,20 +1,24 @@
 warning: unreachable pattern
-  --> $DIR/issue-43253.rs:36:9
+  --> $DIR/issue-43253.rs:37:9
    |
-36 |         9 => {},
+37 |         9 => {},
    |         ^
    |
-   = note: #[warn(unreachable_patterns)] on by default
+note: lint level defined here
+  --> $DIR/issue-43253.rs:12:9
+   |
+12 | #![warn(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
 
 warning: unreachable pattern
-  --> $DIR/issue-43253.rs:42:9
+  --> $DIR/issue-43253.rs:43:9
    |
-42 |         8...9 => {},
+43 |         8...9 => {},
    |         ^^^^^
 
 warning: unreachable pattern
-  --> $DIR/issue-43253.rs:48:9
+  --> $DIR/issue-43253.rs:49:9
    |
-48 |         9...9 => {},
+49 |         9...9 => {},
    |         ^^^^^
 
diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr
index b1b5aedea70..e58251c846f 100644
--- a/src/test/ui/compare-method/proj-outlives-region.stderr
+++ b/src/test/ui/compare-method/proj-outlives-region.stderr
@@ -1,4 +1,4 @@
-error[E0276]: impl has stricter requirements than trait
+error: impl has stricter requirements than trait
   --> $DIR/proj-outlives-region.rs:19:5
    |
 14 |     fn foo() where T: 'a;
diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr
index b02aa5eeb2f..95db68fea5c 100644
--- a/src/test/ui/compare-method/region-unrelated.stderr
+++ b/src/test/ui/compare-method/region-unrelated.stderr
@@ -1,4 +1,4 @@
-error[E0276]: impl has stricter requirements than trait
+error: impl has stricter requirements than trait
   --> $DIR/region-unrelated.rs:19:5
    |
 14 |     fn foo() where T: 'a;
diff --git a/src/test/ui/extern-const.rs b/src/test/ui/extern-const.rs
new file mode 100644
index 00000000000..a77d7b11895
--- /dev/null
+++ b/src/test/ui/extern-const.rs
@@ -0,0 +1,19 @@
+// 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.
+
+// compile-flags: -Z continue-parse-after-error
+
+extern "C" {
+    const C: u8; //~ ERROR extern items cannot be `const`
+}
+
+fn main() {
+    let x = C;
+}
diff --git a/src/test/ui/extern-const.stderr b/src/test/ui/extern-const.stderr
new file mode 100644
index 00000000000..c5a3149e85a
--- /dev/null
+++ b/src/test/ui/extern-const.stderr
@@ -0,0 +1,8 @@
+error: extern items cannot be `const`
+  --> $DIR/extern-const.rs:14:5
+   |
+14 |     const C: u8; //~ ERROR extern items cannot be `const`
+   |     ^^^^^ help: instead try using: `static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs
new file mode 100644
index 00000000000..5aea5f2ca06
--- /dev/null
+++ b/src/test/ui/lint/fn_must_use.rs
@@ -0,0 +1,34 @@
+// 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.
+
+#![warn(unused_must_use)]
+
+struct MyStruct {
+    n: usize
+}
+
+impl MyStruct {
+    #[must_use]
+    fn need_to_use_this_method_value(&self) -> usize {
+        self.n
+    }
+}
+
+#[must_use="it's important"]
+fn need_to_use_this_value() -> bool {
+    false
+}
+
+fn main() {
+    need_to_use_this_value();
+
+    let m = MyStruct { n: 2 };
+    m.need_to_use_this_method_value();
+}
diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr
new file mode 100644
index 00000000000..20eb7452aea
--- /dev/null
+++ b/src/test/ui/lint/fn_must_use.stderr
@@ -0,0 +1,18 @@
+warning: unused return value of `need_to_use_this_value` which must be used: it's important
+  --> $DIR/fn_must_use.rs:30:5
+   |
+30 |     need_to_use_this_value();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/fn_must_use.rs:11:9
+   |
+11 | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
+  --> $DIR/fn_must_use.rs:33:5
+   |
+33 |     m.need_to_use_this_method_value();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs
index d71da58829a..a79dacbc1c9 100644
--- a/src/test/ui/lint/outer-forbid.rs
+++ b/src/test/ui/lint/outer-forbid.rs
@@ -16,7 +16,13 @@
 
 #![forbid(unused, non_snake_case)]
 
-#[allow(unused, unused_variables, bad_style)]
+#[allow(unused_variables)]
+fn foo() {}
+
+#[allow(unused)]
+fn bar() {}
+
+#[allow(bad_style)]
 fn main() {
     println!("hello forbidden world")
 }
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
index df62f5acc00..67a1f4f88ad 100644
--- a/src/test/ui/lint/outer-forbid.stderr
+++ b/src/test/ui/lint/outer-forbid.stderr
@@ -1,29 +1,29 @@
-error[E0453]: allow(unused) overruled by outer forbid(unused)
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
   --> $DIR/outer-forbid.rs:19:9
    |
 17 | #![forbid(unused, non_snake_case)]
    |           ------ `forbid` level set here
 18 | 
-19 | #[allow(unused, unused_variables, bad_style)]
-   |         ^^^^^^ overruled by previous forbid
+19 | #[allow(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
 
-error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
-  --> $DIR/outer-forbid.rs:19:17
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:22:9
    |
 17 | #![forbid(unused, non_snake_case)]
    |           ------ `forbid` level set here
-18 | 
-19 | #[allow(unused, unused_variables, bad_style)]
-   |                 ^^^^^^^^^^^^^^^^ overruled by previous forbid
+...
+22 | #[allow(unused)]
+   |         ^^^^^^ overruled by previous forbid
 
 error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
-  --> $DIR/outer-forbid.rs:19:35
+  --> $DIR/outer-forbid.rs:25:9
    |
 17 | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
-18 | 
-19 | #[allow(unused, unused_variables, bad_style)]
-   |                                   ^^^^^^^^^ overruled by previous forbid
+...
+25 | #[allow(bad_style)]
+   |         ^^^^^^^^^ overruled by previous forbid
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index d40bc3b3339..8c63d7d6f91 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:26:5
    |
+25 | fn a() -> Foo {
+   |           --- expected `Foo` because of return type
 26 |     Some(Foo { bar: 1 })
    |     ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option`
    |
@@ -10,6 +12,8 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:30:5
    |
+29 | fn a2() -> Foo {
+   |            --- expected `Foo` because of return type
 30 |     Ok(Foo { bar: 1})
    |     ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result`
    |
@@ -19,6 +23,8 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:34:5
    |
+33 | fn b() -> Option<Foo> {
+   |           ----------- expected `std::option::Option<Foo>` because of return type
 34 |     Foo { bar: 1 }
    |     ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo`
    |
@@ -28,6 +34,8 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:38:5
    |
+37 | fn c() -> Result<Foo, Bar> {
+   |           ---------------- expected `std::result::Result<Foo, Bar>` because of return type
 38 |     Foo { bar: 1 }
    |     ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo`
    |
@@ -37,6 +45,9 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:49:5
    |
+41 | fn d() -> X<X<String, String>, String> {
+   |           ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
+...
 49 |     x
    |     ^ expected struct `std::string::String`, found integral variable
    |
@@ -46,6 +57,9 @@ error[E0308]: mismatched types
 error[E0308]: mismatched types
   --> $DIR/abridged.rs:60:5
    |
+52 | fn e() -> X<X<String, String>, String> {
+   |           ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type
+...
 60 |     x
    |     ^ expected struct `std::string::String`, found integral variable
    |
diff --git a/src/test/ui/path-lookahead.rs b/src/test/ui/path-lookahead.rs
index c43f2229cdc..367a2560155 100644
--- a/src/test/ui/path-lookahead.rs
+++ b/src/test/ui/path-lookahead.rs
@@ -10,6 +10,8 @@
 
 // run-pass
 
+#![warn(unused)]
+
 // Parser test for #37765
 
 fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr
index 8fd1b8de687..9936a1eb81e 100644
--- a/src/test/ui/path-lookahead.stderr
+++ b/src/test/ui/path-lookahead.stderr
@@ -1,26 +1,31 @@
 warning: unnecessary parentheses around `return` value
-  --> $DIR/path-lookahead.rs:16:10
+  --> $DIR/path-lookahead.rs:18:10
    |
-16 |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
+18 |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[warn(unused_parens)] on by default
 
 warning: function is never used: `with_parens`
-  --> $DIR/path-lookahead.rs:15:1
+  --> $DIR/path-lookahead.rs:17:1
    |
-15 | / fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
-16 | |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
-17 | | }
+17 | / fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
+18 | |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
+19 | | }
    | |_^
    |
-   = note: #[warn(dead_code)] on by default
+note: lint level defined here
+  --> $DIR/path-lookahead.rs:13:9
+   |
+13 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
 
 warning: function is never used: `no_parens`
-  --> $DIR/path-lookahead.rs:19:1
+  --> $DIR/path-lookahead.rs:21:1
    |
-19 | / fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
-20 | |   return <T as ToString>::to_string(&arg);
-21 | | }
+21 | / fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
+22 | |   return <T as ToString>::to_string(&arg);
+23 | | }
    | |_^
 
diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr
index 328b75fd236..9f4562fe297 100644
--- a/src/test/ui/reachable/expr_unary.stderr
+++ b/src/test/ui/reachable/expr_unary.stderr
@@ -1,8 +1,20 @@
+error: unreachable expression
+  --> $DIR/expr_unary.rs:18:28
+   |
+18 |     let x: ! = ! { return; 22 };
+   |                            ^^
+   |
+note: lint level defined here
+  --> $DIR/expr_unary.rs:14:9
+   |
+14 | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
 error[E0600]: cannot apply unary operator `!` to type `!`
   --> $DIR/expr_unary.rs:18:16
    |
 18 |     let x: ! = ! { return; 22 };
    |                ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-24690.rs b/src/test/ui/span/issue-24690.rs
index def0d9aced3..f59d2845108 100644
--- a/src/test/ui/span/issue-24690.rs
+++ b/src/test/ui/span/issue-24690.rs
@@ -11,10 +11,13 @@
 //! A test to ensure that helpful `note` messages aren't emitted more often
 //! than necessary.
 
-// Although there are three errors, we should only get two "lint level defined
+#![feature(rustc_attrs)]
+
+// Although there are three warnings, we should only get two "lint level defined
 // here" notes pointing at the `warnings` span, one for each error type.
-#![deny(warnings)]
+#![warn(unused)]
 
+#[rustc_error]
 fn main() {
     let theTwo = 2;
     let theOtherTwo = 2;
diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr
index 8332ba50a73..4f1c870d874 100644
--- a/src/test/ui/span/issue-24690.stderr
+++ b/src/test/ui/span/issue-24690.stderr
@@ -1,34 +1,37 @@
-error: variable `theTwo` should have a snake case name such as `the_two`
-  --> $DIR/issue-24690.rs:19:9
+warning: unused variable: `theOtherTwo`
+  --> $DIR/issue-24690.rs:23:9
    |
-19 |     let theTwo = 2;
-   |         ^^^^^^
+23 |     let theOtherTwo = 2;
+   |         ^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-24690.rs:16:9
+  --> $DIR/issue-24690.rs:18:9
    |
-16 | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
+18 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_variables)] implied by #[warn(unused)]
 
-error: variable `theOtherTwo` should have a snake case name such as `the_other_two`
-  --> $DIR/issue-24690.rs:20:9
+warning: variable `theTwo` should have a snake case name such as `the_two`
+  --> $DIR/issue-24690.rs:22:9
    |
-20 |     let theOtherTwo = 2;
-   |         ^^^^^^^^^^^
+22 |     let theTwo = 2;
+   |         ^^^^^^
+   |
+   = note: #[warn(non_snake_case)] on by default
 
-error: unused variable: `theOtherTwo`
-  --> $DIR/issue-24690.rs:20:9
+warning: variable `theOtherTwo` should have a snake case name such as `the_other_two`
+  --> $DIR/issue-24690.rs:23:9
    |
-20 |     let theOtherTwo = 2;
+23 |     let theOtherTwo = 2;
    |         ^^^^^^^^^^^
-   |
-note: lint level defined here
-  --> $DIR/issue-24690.rs:16:9
-   |
-16 | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: #[deny(unused_variables)] implied by #[deny(warnings)]
 
-error: aborting due to 3 previous errors
+error: compilation successful
+  --> $DIR/issue-24690.rs:21:1
+   |
+21 | / fn main() {
+22 | |     let theTwo = 2;
+23 | |     let theOtherTwo = 2;
+24 | |     println!("{}", theTwo);
+25 | | }
+   | |_^
 
diff --git a/src/test/ui/span/macro-span-replacement.rs b/src/test/ui/span/macro-span-replacement.rs
index d779bec4ace..b7aae39c469 100644
--- a/src/test/ui/span/macro-span-replacement.rs
+++ b/src/test/ui/span/macro-span-replacement.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![warn(unused)]
+
 macro_rules! m {
     ($a:tt $b:tt) => {
         $b $a;
diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr
index e7336697f48..af03aa6a369 100644
--- a/src/test/ui/span/macro-span-replacement.stderr
+++ b/src/test/ui/span/macro-span-replacement.stderr
@@ -1,11 +1,16 @@
 warning: struct is never used: `S`
-  --> $DIR/macro-span-replacement.rs:13:9
+  --> $DIR/macro-span-replacement.rs:15:9
    |
-13 |         $b $a;
+15 |         $b $a;
    |         ^^^^^^
 ...
-18 |     m!(S struct);
+20 |     m!(S struct);
    |     ------------- in this macro invocation
    |
-   = note: #[warn(dead_code)] on by default
+note: lint level defined here
+  --> $DIR/macro-span-replacement.rs:11:9
+   |
+11 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
 
diff --git a/src/test/ui/span/multispan-import-lint.rs b/src/test/ui/span/multispan-import-lint.rs
index 43b6cd8f85f..66536b29c02 100644
--- a/src/test/ui/span/multispan-import-lint.rs
+++ b/src/test/ui/span/multispan-import-lint.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![warn(unused)]
+
 use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
 
 fn main() {
diff --git a/src/test/ui/span/multispan-import-lint.stderr b/src/test/ui/span/multispan-import-lint.stderr
index 4b1ca7f98bb..1fecdea7d0d 100644
--- a/src/test/ui/span/multispan-import-lint.stderr
+++ b/src/test/ui/span/multispan-import-lint.stderr
@@ -1,8 +1,13 @@
 warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`
-  --> $DIR/multispan-import-lint.rs:11:16
+  --> $DIR/multispan-import-lint.rs:13:16
    |
-11 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
+13 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd};
    |                ^^  ^^^       ^^^^^^^^^  ^^^^^^^^^^
    |
-   = note: #[warn(unused_imports)] on by default
+note: lint level defined here
+  --> $DIR/multispan-import-lint.rs:11:9
+   |
+11 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(unused_imports)] implied by #[warn(unused)]
 
diff --git a/src/test/ui/trait-method-private.rs b/src/test/ui/trait-method-private.rs
new file mode 100644
index 00000000000..5c1bd668ac6
--- /dev/null
+++ b/src/test/ui/trait-method-private.rs
@@ -0,0 +1,30 @@
+// 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.
+
+mod inner {
+    pub trait Bar {
+        fn method(&self);
+    }
+
+    pub struct Foo;
+
+    impl Foo {
+        fn method(&self) {}
+    }
+
+    impl Bar for Foo {
+        fn method(&self) {}
+    }
+}
+
+fn main() {
+    let foo = inner::Foo;
+    foo.method();
+}
diff --git a/src/test/ui/trait-method-private.stderr b/src/test/ui/trait-method-private.stderr
new file mode 100644
index 00000000000..c7a7b689edc
--- /dev/null
+++ b/src/test/ui/trait-method-private.stderr
@@ -0,0 +1,12 @@
+error[E0624]: method `method` is private
+  --> $DIR/trait-method-private.rs:29:9
+   |
+29 |     foo.method();
+   |         ^^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           candidate #1: `use inner::Bar;`
+
+error: aborting due to previous error
+
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 305bc25d5e105e84ffe261655b46cf74570f6e5
+Subproject 7704f7b1fd52607104cc7fdc435d636c9de1fe9
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 93696561708..769748c63c0 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1156,9 +1156,21 @@ actual:\n\
     fn compile_test(&self) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
         // FIXME (#9639): This needs to handle non-utf8 paths
-        let link_args = vec!["-L".to_owned(),
-                             aux_dir.to_str().unwrap().to_owned()];
-        let args = self.make_compile_args(link_args,
+        let mut extra_args = vec!["-L".to_owned(),
+                                  aux_dir.to_str().unwrap().to_owned()];
+        match self.config.mode {
+            CompileFail | Ui => {
+                // compile-fail and ui tests tend to have tons of unused code as
+                // it's just testing various pieces of the compile, but we don't
+                // want to actually assert warnings about all this code. Instead
+                // let's just ignore unused code warnings by defaults and tests
+                // can turn it back on if needed.
+                extra_args.push("-A".to_owned());
+                extra_args.push("unused".to_owned());
+            }
+            _ => {}
+        }
+        let args = self.make_compile_args(extra_args,
                                           &self.testpaths.file,
                                           TargetLocation::ThisFile(self.make_exe_name()));
         self.compose_and_run_compiler(args, None)