about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrad Gibson <b2b@humanenginuity.com>2018-05-06 07:56:53 -0700
committerBrad Gibson <b2b@humanenginuity.com>2018-05-06 07:56:53 -0700
commit6a78c0a10f2e719117fe4bb929bfb38549acfeec (patch)
tree0089dcdd34bfa5ba430ed33163264b147677be59 /src
parente1d5509bf381d978a1894b6ba869c3b56dd3eeca (diff)
parent6f721f54c6fb1de9cf00eb9d2d050f818c882871 (diff)
downloadrust-6a78c0a10f2e719117fe4bb929bfb38549acfeec.tar.gz
rust-6a78c0a10f2e719117fe4bb929bfb38549acfeec.zip
resolved conflict with upstream commit
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock124
-rw-r--r--src/Cargo.toml8
-rw-r--r--src/bootstrap/README.md4
-rw-r--r--src/bootstrap/bin/rustc.rs7
-rw-r--r--src/bootstrap/builder.rs51
-rw-r--r--src/bootstrap/config.rs15
-rwxr-xr-xsrc/bootstrap/configure.py2
-rw-r--r--src/bootstrap/doc.rs1
-rw-r--r--src/bootstrap/flags.rs19
-rw-r--r--src/bootstrap/job.rs10
-rw-r--r--src/bootstrap/lib.rs14
-rw-r--r--src/bootstrap/test.rs27
-rw-r--r--src/ci/docker/dist-various-1/Dockerfile10
-rw-r--r--src/ci/docker/mingw-check/Dockerfile1
-rw-r--r--src/ci/docker/x86_64-gnu-debug/Dockerfile2
-rwxr-xr-xsrc/ci/run.sh4
m---------src/doc/book0
-rw-r--r--src/doc/index.md4
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc/.gitignore1
-rw-r--r--src/doc/rustc/book.toml5
-rw-r--r--src/doc/rustc/src/SUMMARY.md16
-rw-r--r--src/doc/rustc/src/codegen-options/index.md209
-rw-r--r--src/doc/rustc/src/command-line-arguments.md116
-rw-r--r--src/doc/rustc/src/contributing.md6
-rw-r--r--src/doc/rustc/src/lints/groups.md29
-rw-r--r--src/doc/rustc/src/lints/index.md28
-rw-r--r--src/doc/rustc/src/lints/levels.md252
-rw-r--r--src/doc/rustc/src/lints/listing/allowed-by-default.md453
-rw-r--r--src/doc/rustc/src/lints/listing/deny-by-default.md241
-rw-r--r--src/doc/rustc/src/lints/listing/index.md5
-rw-r--r--src/doc/rustc/src/lints/listing/warn-by-default.md1039
-rw-r--r--src/doc/rustc/src/targets/built-in.md10
-rw-r--r--src/doc/rustc/src/targets/custom.md17
-rw-r--r--src/doc/rustc/src/targets/index.md13
-rw-r--r--src/doc/rustc/src/what-is-rustc.md68
-rw-r--r--src/doc/unstable-book/src/language-features/fn-must-use.md30
-rw-r--r--src/doc/unstable-book/src/language-features/tool-attributes.md26
-rw-r--r--src/liballoc/alloc.rs14
-rw-r--r--src/liballoc/arc.rs5
-rw-r--r--src/liballoc/boxed.rs1
-rw-r--r--src/liballoc/lib.rs5
-rw-r--r--src/liballoc/raw_vec.rs10
-rw-r--r--src/liballoc/rc.rs5
-rw-r--r--src/liballoc/tests/lib.rs2
-rw-r--r--src/liballoc/tests/slice.rs1
-rw-r--r--src/liballoc/vec.rs3
-rw-r--r--src/libcore/cmp.rs12
-rw-r--r--src/libcore/fmt/mod.rs13
-rw-r--r--src/libcore/iter/iterator.rs2
-rw-r--r--src/libcore/lib.rs12
-rw-r--r--src/libcore/macros.rs4
-rw-r--r--src/libcore/marker.rs2
-rw-r--r--src/libcore/ops/arith.rs6
-rw-r--r--src/libcore/ops/bit.rs16
-rw-r--r--src/libcore/ops/deref.rs4
-rw-r--r--src/libcore/ops/range.rs84
-rw-r--r--src/libcore/ptr.rs6
-rw-r--r--src/libcore/slice/memchr.rs97
-rw-r--r--src/libcore/slice/mod.rs1
-rw-r--r--src/libcore/tests/lib.rs4
-rw-r--r--src/libcore/tests/num/uint_macros.rs1
-rw-r--r--src/libcore/tests/ops.rs8
-rw-r--r--src/libcore/tests/slice.rs86
-rw-r--r--src/libcore/tests/time.rs124
-rw-r--r--src/libcore/time.rs116
-rw-r--r--src/libcore/unicode/bool_trie.rs16
-rw-r--r--src/libproc_macro/lib.rs49
-rw-r--r--src/librustc/Cargo.toml1
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/hir/check_attr.rs32
-rw-r--r--src/librustc/hir/intravisit.rs3
-rw-r--r--src/librustc/hir/lowering.rs36
-rw-r--r--src/librustc/hir/map/def_collector.rs33
-rw-r--r--src/librustc/hir/map/definitions.rs6
-rw-r--r--src/librustc/ich/impls_const_math.rs44
-rw-r--r--src/librustc/ich/impls_mir.rs26
-rw-r--r--src/librustc/ich/impls_syntax.rs49
-rw-r--r--src/librustc/ich/impls_ty.rs37
-rw-r--r--src/librustc/ich/mod.rs1
-rw-r--r--src/librustc/infer/combine.rs4
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs26
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs16
-rw-r--r--src/librustc/infer/mod.rs58
-rw-r--r--src/librustc/infer/region_constraints/mod.rs164
-rw-r--r--src/librustc/infer/type_variable.rs18
-rw-r--r--src/librustc/lib.rs6
-rw-r--r--src/librustc/lint/levels.rs6
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc/middle/const_val.rs12
-rw-r--r--src/librustc/middle/expr_use_visitor.rs60
-rw-r--r--src/librustc/middle/liveness.rs44
-rw-r--r--src/librustc/middle/mem_categorization.rs105
-rw-r--r--src/librustc/middle/region.rs11
-rw-r--r--src/librustc/middle/stability.rs2
-rw-r--r--src/librustc/mir/cache.rs2
-rw-r--r--src/librustc/mir/interpret/error.rs66
-rw-r--r--src/librustc/mir/interpret/mod.rs12
-rw-r--r--src/librustc/mir/mod.rs208
-rw-r--r--src/librustc/mir/traversal.rs16
-rw-r--r--src/librustc/mir/visit.rs14
-rw-r--r--src/librustc/session/config.rs12
-rw-r--r--src/librustc/session/mod.rs13
-rw-r--r--src/librustc/traits/coherence.rs5
-rw-r--r--src/librustc/traits/error_reporting.rs19
-rw-r--r--src/librustc/traits/fulfill.rs4
-rw-r--r--src/librustc/traits/mod.rs19
-rw-r--r--src/librustc/traits/on_unimplemented.rs8
-rw-r--r--src/librustc/traits/project.rs14
-rw-r--r--src/librustc/traits/query/evaluate_obligation.rs70
-rw-r--r--src/librustc/traits/query/mod.rs4
-rw-r--r--src/librustc/traits/query/normalize.rs2
-rw-r--r--src/librustc/traits/select.rs252
-rw-r--r--src/librustc/traits/structural_impls.rs1
-rw-r--r--src/librustc/ty/context.rs40
-rw-r--r--src/librustc/ty/fold.rs20
-rw-r--r--src/librustc/ty/item_path.rs11
-rw-r--r--src/librustc/ty/layout.rs135
-rw-r--r--src/librustc/ty/maps/config.rs39
-rw-r--r--src/librustc/ty/maps/job.rs5
-rw-r--r--src/librustc/ty/maps/keys.rs12
-rw-r--r--src/librustc/ty/maps/mod.rs17
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs21
-rw-r--r--src/librustc/ty/maps/plumbing.rs939
-rw-r--r--src/librustc/ty/maps/values.rs2
-rw-r--r--src/librustc/ty/mod.rs46
-rw-r--r--src/librustc/ty/structural_impls.rs30
-rw-r--r--src/librustc/ty/sty.rs37
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc/util/common.rs19
-rw-r--r--src/librustc/util/ppaux.rs6
-rw-r--r--src/librustc_apfloat/ppc.rs2
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs30
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs29
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/lifetime.rs15
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs34
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs16
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs31
-rw-r--r--src/librustc_const_math/Cargo.toml14
-rw-r--r--src/librustc_const_math/err.rs87
-rw-r--r--src/librustc_const_math/float.rs213
-rw-r--r--src/librustc_const_math/lib.rs31
-rw-r--r--src/librustc_data_structures/lazy_btree_map.rs108
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_driver/lib.rs5
-rw-r--r--src/librustc_driver/profile/trace.rs2
-rw-r--r--src/librustc_driver/test.rs4
-rw-r--r--src/librustc_errors/diagnostic.rs21
-rw-r--r--src/librustc_errors/diagnostic_builder.rs11
-rw-r--r--src/librustc_errors/lib.rs10
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs2
-rw-r--r--src/librustc_incremental/assert_module_sources.rs2
-rw-r--r--src/librustc_lint/builtin.rs3
-rw-r--r--src/librustc_lint/lib.rs1
-rw-r--r--src/librustc_lint/unused.rs81
-rw-r--r--src/librustc_metadata/cstore_impl.rs4
-rw-r--r--src/librustc_metadata/decoder.rs24
-rw-r--r--src/librustc_mir/Cargo.toml1
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs3
-rw-r--r--src/librustc_mir/borrow_check/location.rs123
-rw-r--r--src/librustc_mir/borrow_check/mod.rs439
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs187
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/facts.rs194
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs64
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/dfs.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs71
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/input_output.rs31
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs186
-rw-r--r--src/librustc_mir/build/block.rs9
-rw-r--r--src/librustc_mir/build/expr/as_place.rs18
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs31
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs297
-rw-r--r--src/librustc_mir/build/mod.rs82
-rw-r--r--src/librustc_mir/dataflow/graphviz.rs6
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs6
-rw-r--r--src/librustc_mir/hair/cx/mod.rs25
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs12
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs77
-rw-r--r--src/librustc_mir/interpret/cast.rs9
-rw-r--r--src/librustc_mir/interpret/const_eval.rs2
-rw-r--r--src/librustc_mir/interpret/eval_context.rs19
-rw-r--r--src/librustc_mir/interpret/memory.rs6
-rw-r--r--src/librustc_mir/interpret/operator.rs62
-rw-r--r--src/librustc_mir/interpret/place.rs4
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs13
-rw-r--r--src/librustc_mir/lib.rs7
-rw-r--r--src/librustc_mir/monomorphize/item.rs2
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs14
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs12
-rw-r--r--src/librustc_mir/transform/const_prop.rs14
-rw-r--r--src/librustc_mir/transform/copy_prop.rs21
-rw-r--r--src/librustc_mir/transform/deaggregator.rs21
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs14
-rw-r--r--src/librustc_mir/transform/generator.rs9
-rw-r--r--src/librustc_mir/transform/inline.rs69
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/transform/remove_noop_landing_pads.rs2
-rw-r--r--src/librustc_mir/transform/simplify.rs10
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs36
-rw-r--r--src/librustc_mir/util/graphviz.rs2
-rw-r--r--src/librustc_mir/util/liveness.rs2
-rw-r--r--src/librustc_passes/Cargo.toml1
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_passes/mir_stats.rs13
-rw-r--r--src/librustc_passes/rvalue_promotion.rs12
-rw-r--r--src/librustc_plugin/lib.rs1
-rw-r--r--src/librustc_plugin/registry.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs44
-rw-r--r--src/librustc_resolve/diagnostics.rs73
-rw-r--r--src/librustc_resolve/lib.rs57
-rw-r--r--src/librustc_resolve/macros.rs11
-rw-r--r--src/librustc_resolve/resolve_imports.rs80
-rw-r--r--src/librustc_target/abi/mod.rs27
-rw-r--r--src/librustc_target/lib.rs1
-rw-r--r--src/librustc_target/spec/apple_ios_base.rs1
-rw-r--r--src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs38
-rw-r--r--src/librustc_target/spec/i686_apple_darwin.rs1
-rw-r--r--src/librustc_target/spec/mod.rs1
-rw-r--r--src/librustc_traits/dropck_outlives.rs40
-rw-r--r--src/librustc_traits/evaluate_obligation.rs35
-rw-r--r--src/librustc_traits/lib.rs2
-rw-r--r--src/librustc_traits/normalize_erasing_regions.rs2
-rw-r--r--src/librustc_trans/Cargo.toml1
-rw-r--r--src/librustc_trans/abi.rs26
-rw-r--r--src/librustc_trans/allocator.rs4
-rw-r--r--src/librustc_trans/attributes.rs32
-rw-r--r--src/librustc_trans/back/linker.rs6
-rw-r--r--src/librustc_trans/back/symbol_export.rs2
-rw-r--r--src/librustc_trans/back/write.rs31
-rw-r--r--src/librustc_trans/base.rs2
-rw-r--r--src/librustc_trans/callee.rs2
-rw-r--r--src/librustc_trans/common.rs6
-rw-r--r--src/librustc_trans/consts.rs2
-rw-r--r--src/librustc_trans/context.rs6
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs4
-rw-r--r--src/librustc_trans/debuginfo/mod.rs4
-rw-r--r--src/librustc_trans/debuginfo/namespace.rs2
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs4
-rw-r--r--src/librustc_trans/declare.rs4
-rw-r--r--src/librustc_trans/intrinsic.rs2
-rw-r--r--src/librustc_trans/lib.rs4
-rw-r--r--src/librustc_trans/mir/analyze.rs2
-rw-r--r--src/librustc_trans/mir/block.rs36
-rw-r--r--src/librustc_trans/mir/place.rs33
-rw-r--r--src/librustc_trans/mir/rvalue.rs19
-rw-r--r--src/librustc_trans/trans_item.rs2
-rw-r--r--src/librustc_trans_utils/symbol_names.rs6
-rw-r--r--src/librustc_typeck/Cargo.toml1
-rw-r--r--src/librustc_typeck/astconv.rs4
-rw-r--r--src/librustc_typeck/check/autoderef.rs4
-rw-r--r--src/librustc_typeck/check/compare_method.rs3
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/mod.rs3
-rw-r--r--src/librustc_typeck/check/method/probe.rs9
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/check/regionck.rs47
-rw-r--r--src/librustc_typeck/check/upvar.rs31
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/check/writeback.rs4
-rw-r--r--src/librustc_typeck/collect.rs18
-rw-r--r--src/librustc_typeck/lib.rs4
-rw-r--r--src/librustdoc/clean/auto_trait.rs4
-rw-r--r--src/librustdoc/clean/cfg.rs242
-rw-r--r--src/librustdoc/clean/mod.rs78
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/render.rs8
-rw-r--r--src/librustdoc/html/static/main.js90
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/visit_ast.rs15
-rw-r--r--src/libstd/collections/hash/map.rs1
-rw-r--r--src/libstd/collections/hash/table.rs2
-rw-r--r--src/libstd/error.rs65
-rw-r--r--src/libstd/ffi/c_str.rs3
-rw-r--r--src/libstd/lib.rs21
-rw-r--r--src/libstd/macros.rs4
-rw-r--r--src/libstd/net/addr.rs4
-rw-r--r--src/libstd/net/mod.rs65
-rw-r--r--src/libstd/panic.rs51
-rw-r--r--src/libstd/panicking.rs8
-rw-r--r--src/libstd/path.rs27
-rw-r--r--src/libstd/sync/mpsc/select.rs2
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/attr.rs183
-rw-r--r--src/libsyntax/diagnostic_list.rs15
-rw-r--r--src/libsyntax/ext/base.rs21
-rw-r--r--src/libsyntax/ext/expand.rs76
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs8
-rw-r--r--src/libsyntax/feature_gate.rs156
-rw-r--r--src/libsyntax/json.rs26
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/parse/attr.rs7
-rw-r--r--src/libsyntax/parse/mod.rs8
-rw-r--r--src/libsyntax/parse/parser.rs8
-rw-r--r--src/libsyntax/parse/token.rs3
-rw-r--r--src/libsyntax/print/pp.rs30
-rw-r--r--src/libsyntax/print/pprust.rs39
-rw-r--r--src/libsyntax_ext/concat_idents.rs5
-rw-r--r--src/libsyntax_ext/deriving/custom.rs8
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs2
-rw-r--r--src/libsyntax_pos/hygiene.rs43
-rw-r--r--src/libsyntax_pos/lib.rs16
-rw-r--r--src/libsyntax_pos/symbol.rs192
-rw-r--r--src/stage0.txt2
-rw-r--r--src/test/codegen/align-struct.rs3
-rw-r--r--src/test/codegen/call-metadata.rs29
-rw-r--r--src/test/codegen/force-frame-pointers.rs (renamed from src/test/compile-fail/macro-reexport-malformed-2.rs)12
-rw-r--r--src/test/codegen/function-arguments.rs12
-rw-r--r--src/test/codegen/lifetime_start_end.rs8
-rw-r--r--src/test/codegen/noreturnflag.rs22
-rw-r--r--src/test/codegen/target-feature-on-functions.rs19
-rw-r--r--src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs2
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs55
-rw-r--r--src/test/compile-fail/attr-usage-inline.rs2
-rw-r--r--src/test/compile-fail/auxiliary/macro_non_reexport_2.rs19
-rw-r--r--src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs2
-rw-r--r--src/test/compile-fail/extern-macro.rs2
-rw-r--r--src/test/compile-fail/feature-gate-tool_attributes.rs15
-rw-r--r--src/test/compile-fail/impl-trait/impl-generic-mismatch.rs11
-rw-r--r--src/test/compile-fail/impl-trait/where-allowed.rs1
-rw-r--r--src/test/compile-fail/issue-23080-2.rs3
-rw-r--r--src/test/compile-fail/issue-31769.rs2
-rw-r--r--src/test/compile-fail/issue-43988.rs6
-rw-r--r--src/test/compile-fail/lint-unused-mut-variables.rs61
-rw-r--r--src/test/compile-fail/macro-non-lifetime.rs (renamed from src/test/compile-fail/macro-reexport-not-locally-visible.rs)14
-rw-r--r--src/test/compile-fail/macros-nonfatal-errors.rs1
-rw-r--r--src/test/compile-fail/mir_check_cast_unsize.rs1
-rw-r--r--src/test/compile-fail/nll/match-guards-always-borrow.rs61
-rw-r--r--src/test/compile-fail/nll/unused-mut-issue-50343.rs17
-rw-r--r--src/test/compile-fail/privacy/associated-item-privacy-inherent.rs1
-rw-r--r--src/test/compile-fail/privacy/associated-item-privacy-trait.rs1
-rw-r--r--src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs1
-rw-r--r--src/test/compile-fail/private-inferred-type-3.rs1
-rw-r--r--src/test/compile-fail/private-inferred-type.rs1
-rw-r--r--src/test/compile-fail/repr-align.rs5
-rw-r--r--src/test/compile-fail/trait-bounds-not-on-struct.rs1
-rw-r--r--src/test/compile-fail/unknown-tool-name.rs16
-rw-r--r--src/test/compile-fail/unknown_tool_attributes-1.rs18
-rw-r--r--src/test/compile-fail/used.rs28
-rw-r--r--src/test/mir-opt/match_false_edges.rs114
-rw-r--r--src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs2
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/Makefile12
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/basic.rs (renamed from src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs)12
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/ep-lib.rs (renamed from src/test/compile-fail/auxiliary/macro_reexport_1.rs)12
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/ep-vec.rs13
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/feature-gate.rs (renamed from src/test/run-pass/auxiliary/macro_reexport_1.rs)8
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/relative-only.rs (renamed from src/test/compile-fail/macro-reexport-malformed-1.rs)15
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs24
-rw-r--r--src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs17
-rw-r--r--src/test/run-make-fulldeps/libtest-json/Makefile2
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs2
-rw-r--r--src/test/run-pass-fulldeps/macro-quote-test.rs2
-rw-r--r--src/test/run-pass/auxiliary/issue-48984-aux.rs16
-rw-r--r--src/test/run-pass/auxiliary/macro_reexport_2.rs16
-rw-r--r--src/test/run-pass/backtrace-debuginfo.rs1
-rw-r--r--src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs56
-rw-r--r--src/test/run-pass/dyn-trait.rs2
-rw-r--r--src/test/run-pass/extern-prelude-no-speculative.rs21
-rw-r--r--src/test/run-pass/hygiene/issue-47311.rs2
-rw-r--r--src/test/run-pass/hygiene/issue-47312.rs2
-rw-r--r--src/test/run-pass/hygiene/legacy_interaction.rs2
-rw-r--r--src/test/run-pass/hygiene/lexical.rs2
-rw-r--r--src/test/run-pass/hygiene/wrap_unhygienic_example.rs2
-rw-r--r--src/test/run-pass/hygiene/xcrate.rs2
-rw-r--r--src/test/run-pass/issue-47703-tuple.rs21
-rw-r--r--src/test/run-pass/issue-48984.rs (renamed from src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs)13
-rw-r--r--src/test/run-pass/issue-49632.rs (renamed from src/test/compile-fail/macro-reexport-malformed-3.rs)13
-rw-r--r--src/test/run-pass/issue-49685.rs (renamed from src/test/compile-fail-fulldeps/gated-macro-reexports.rs)19
-rw-r--r--src/test/run-pass/issue-50415.rs27
-rw-r--r--src/test/run-pass/nll/issue-48623-closure.rs24
-rw-r--r--src/test/run-pass/nll/issue-48623-generator.rs25
-rw-r--r--src/test/run-pass/nll/issue-50343.rs17
-rw-r--r--src/test/run-pass/paths-in-macro-invocations.rs2
-rw-r--r--src/test/run-pass/repr_c_int_align.rs55
-rw-r--r--src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs2
-rw-r--r--src/test/run-pass/sync-send-in-std.rs6
-rw-r--r--src/test/run-pass/tool_attributes.rs23
-rw-r--r--src/test/run-pass/vec-const-new.rs17
-rw-r--r--src/test/rustdoc-js/alias-2.js6
-rw-r--r--src/test/rustdoc-js/alias.js6
-rw-r--r--src/test/rustdoc-js/basic.js2
-rw-r--r--src/test/rustdoc/auxiliary/all-item-types.rs32
-rw-r--r--src/test/rustdoc/cross-crate-links.rs71
-rw-r--r--src/test/rustdoc/pub-use-extern-macros.rs11
-rw-r--r--src/test/rustdoc/universal-impl-trait.rs7
-rw-r--r--src/test/rustfix/closure-immutable-outer-variable.fixed (renamed from src/test/run-pass/macro-reexport.rs)13
-rw-r--r--src/test/rustfix/closure-immutable-outer-variable.rs (renamed from src/test/run-pass/macro-reexport-no-intermediate-use.rs)13
-rw-r--r--src/test/rustfix/empty-no-fixes.fixed11
-rw-r--r--src/test/rustfix/empty-no-fixes.rs11
-rw-r--r--src/test/rustfix/empty-no-fixes.rs.fixed12
-rw-r--r--src/test/rustfix/issue-45562.fixed13
-rw-r--r--src/test/rustfix/issue-45562.rs13
-rw-r--r--src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed12
-rw-r--r--src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs12
-rw-r--r--src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed (renamed from src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs)20
-rw-r--r--src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs22
-rw-r--r--src/test/rustfix/main-no-fixes.fixed11
-rw-r--r--src/test/rustfix/main-no-fixes.rs11
-rw-r--r--src/test/rustfix/main-no-fixes.rs.fixed11
-rw-r--r--src/test/rustfix/missing-comma-in-match.fixed17
-rw-r--r--src/test/rustfix/missing-comma-in-match.rs17
-rw-r--r--src/test/rustfix/str-as-char.fixed13
-rw-r--r--src/test/rustfix/str-as-char.rs13
-rw-r--r--src/test/rustfix/tuple-float-index.fixed15
-rw-r--r--src/test/rustfix/tuple-float-index.rs15
-rwxr-xr-xsrc/test/rustfix/update-all-references.sh31
-rwxr-xr-xsrc/test/rustfix/update-references.sh45
-rw-r--r--src/test/ui/const-eval/ice-packed.rs28
-rw-r--r--src/test/ui/const-eval/index_out_of_bound.stderr2
-rw-r--r--src/test/ui/const-eval/promoted_errors.stderr12
-rw-r--r--src/test/ui/error-codes/E0080.rs1
-rw-r--r--src/test/ui/error-codes/E0080.stderr2
-rw-r--r--src/test/ui/error-codes/E0518.stderr8
-rw-r--r--src/test/ui/feature-gate-dyn-trait.stderr11
-rw-r--r--src/test/ui/feature-gate-extern_prelude.rs11
-rw-r--r--src/test/ui/feature-gate-extern_prelude.stderr8
-rw-r--r--src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr8
-rw-r--r--src/test/ui/feature-gate-fn_must_use.rs31
-rw-r--r--src/test/ui/feature-gate-fn_must_use.stderr24
-rw-r--r--src/test/ui/feature-gate-tool_attributes.rs15
-rw-r--r--src/test/ui/feature-gate-tool_attributes.stderr11
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs21
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr460
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.rs10
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr26
-rw-r--r--src/test/ui/fn_must_use.rs (renamed from src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs)1
-rw-r--r--src/test/ui/fn_must_use.stderr (renamed from src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr)16
-rw-r--r--src/test/ui/generator/borrowing.nll.stderr38
-rw-r--r--src/test/ui/generator/borrowing.rs4
-rw-r--r--src/test/ui/generator/dropck.nll.stderr26
-rw-r--r--src/test/ui/generator/dropck.rs5
-rw-r--r--src/test/ui/generator/dropck.stderr15
-rw-r--r--src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr18
-rw-r--r--src/test/ui/generator/yield-while-iterating.nll.stderr32
-rw-r--r--src/test/ui/hygiene/fields.rs2
-rw-r--r--src/test/ui/hygiene/globs.rs2
-rw-r--r--src/test/ui/hygiene/impl_items.rs2
-rw-r--r--src/test/ui/hygiene/intercrate.rs2
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.rs2
-rw-r--r--src/test/ui/hygiene/privacy.rs2
-rw-r--r--src/test/ui/hygiene/trait_items.rs2
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr2
-rw-r--r--src/test/ui/impl_trait_projections.rs2
-rw-r--r--src/test/ui/impl_trait_projections.stderr10
-rw-r--r--src/test/ui/imports/macro-paths.rs2
-rw-r--r--src/test/ui/imports/shadow_builtin_macros.rs2
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr4
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.rs1
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr6
-rw-r--r--src/test/ui/inference_unstable.rs2
-rw-r--r--src/test/ui/inference_unstable.stderr2
-rw-r--r--src/test/ui/issue-49934.rs52
-rw-r--r--src/test/ui/issue-49934.stderr50
-rw-r--r--src/test/ui/issue-50187.rs49
-rw-r--r--src/test/ui/issue-50403.rs (renamed from src/test/ui/feature-gate-dyn-trait.rs)7
-rw-r--r--src/test/ui/issue-50403.stderr8
-rw-r--r--src/test/ui/lifetime_starts_expressions.rs23
-rw-r--r--src/test/ui/lifetime_starts_expressions.stderr14
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs43
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr48
-rw-r--r--src/test/ui/lint/must-use-ops.rs51
-rw-r--r--src/test/ui/lint/must-use-ops.stderr132
-rw-r--r--src/test/ui/macro-reexport-removed.rs (renamed from src/test/compile-fail/macro-reexport-undef.rs)9
-rw-r--r--src/test/ui/macro-reexport-removed.stderr24
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.rs6
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr17
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr24
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr34
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr32
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr20
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr48
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr16
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr12
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr24
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr2
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn.rs1
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn.stderr8
-rw-r--r--src/test/ui/on-unimplemented/no-debug.stderr11
-rw-r--r--src/test/ui/print_type_sizes/repr_int_c.rs35
-rw-r--r--src/test/ui/print_type_sizes/repr_int_c.stdout12
-rw-r--r--src/test/ui/raw-literal-keywords.rs1
-rw-r--r--src/test/ui/raw-literal-keywords.stderr6
-rw-r--r--src/test/ui/repr-align-assign.rs (renamed from src/test/run-pass-fulldeps/proc-macro/use-reexport.rs)14
-rw-r--r--src/test/ui/repr-align-assign.stderr15
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs20
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr14
-rw-r--r--src/test/ui/span/gated-features-attr-spans.rs23
-rw-r--r--src/test/ui/span/gated-features-attr-spans.stderr18
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.fixed22
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed (renamed from src/test/compile-fail/macro-no-implicit-reexport.rs)16
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr2
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.rs2
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed20
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.stderr2
-rw-r--r--src/test/ui/suggestions/issue-45562.fixed16
-rw-r--r--src/test/ui/suggestions/issue-45562.rs2
-rw-r--r--src/test/ui/suggestions/issue-45562.stderr2
-rw-r--r--src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed15
-rw-r--r--src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs2
-rw-r--r--src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr2
-rw-r--r--src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed26
-rw-r--r--src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs2
-rw-r--r--src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr4
-rw-r--r--src/test/ui/suggestions/missing-comma-in-match.fixed21
-rw-r--r--src/test/ui/suggestions/missing-comma-in-match.rs2
-rw-r--r--src/test/ui/suggestions/missing-comma-in-match.stderr2
-rw-r--r--src/test/ui/suggestions/str-as-char.fixed16
-rw-r--r--src/test/ui/suggestions/str-as-char.rs2
-rw-r--r--src/test/ui/suggestions/str-as-char.stderr2
-rw-r--r--src/test/ui/suggestions/tuple-float-index.fixed16
-rw-r--r--src/test/ui/suggestions/tuple-float-index.rs1
-rw-r--r--src/test/ui/suggestions/tuple-float-index.stderr2
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs2
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr4
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr10
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.rs2
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr8
-rwxr-xr-xsrc/test/ui/update-references.sh4
-rw-r--r--src/tools/build-manifest/src/main.rs1
m---------src/tools/cargo0
m---------src/tools/clippy34
-rw-r--r--src/tools/compiletest/Cargo.toml2
-rw-r--r--src/tools/compiletest/src/common.rs43
-rw-r--r--src/tools/compiletest/src/header.rs10
-rw-r--r--src/tools/compiletest/src/main.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs76
m---------src/tools/rls0
-rw-r--r--src/tools/rustdoc-js/tester.js18
m---------src/tools/rustfmt22
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/libcoretest.rs34
-rw-r--r--src/tools/tidy/src/main.rs1
553 files changed, 10881 insertions, 4889 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index e14b9da9713..a2767bd290d 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -390,10 +390,12 @@ dependencies = [
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -996,9 +998,10 @@ dependencies = [
 
 [[package]]
 name = "languageserver-types"
-version = "0.36.0"
+version = "0.39.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1325,16 +1328,16 @@ dependencies = [
 
 [[package]]
 name = "parking_lot"
-version = "0.5.4"
+version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1623,7 +1626,7 @@ dependencies = [
 
 [[package]]
 name = "rls"
-version = "0.126.0"
+version = "0.127.0"
 dependencies = [
  "cargo 0.28.0",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1632,7 +1635,7 @@ dependencies = [
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "languageserver-types 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "languageserver-types 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1644,7 +1647,7 @@ dependencies = [
  "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.6.0",
+ "rustfmt-nightly 0.6.1",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1728,7 +1731,6 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_apfloat 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
@@ -1740,70 +1742,84 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "110.0.0"
+version = "113.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "110.0.0"
+version = "113.0.0"
 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)",
  "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "110.0.0"
+version = "113.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "rustc-ap-rustc_target"
+version = "113.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "rustc-ap-serialize"
-version = "110.0.0"
+version = "113.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "110.0.0"
+version = "113.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "110.0.0"
+version = "113.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1873,15 +1889,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_const_math"
-version = "0.0.0"
-dependencies = [
- "rustc_apfloat 0.0.0",
- "serialize 0.0.0",
- "syntax 0.0.0",
-]
-
-[[package]]
 name = "rustc_cratesio_shim"
 version = "0.0.0"
 dependencies = [
@@ -1896,8 +1903,8 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2026,7 +2033,6 @@ dependencies = [
  "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_apfloat 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
@@ -2053,7 +2059,6 @@ version = "0.0.0"
 dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_mir 0.0.0",
@@ -2154,7 +2159,6 @@ dependencies = [
  "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_incremental 0.0.0",
@@ -2205,7 +2209,6 @@ dependencies = [
  "fmt_macros 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
@@ -2234,21 +2237,34 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustfix"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "rustfmt-nightly"
-version = "0.6.0"
+version = "0.6.1"
 dependencies = [
  "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3063,7 +3079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be"
 "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum languageserver-types 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)" = "174cdfb8bed13225bb419bec66ee1c970099c875688645f9c4a82e3af43ba69d"
+"checksum languageserver-types 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4cdd5e52d71aca47050e5b25f03082609c63a1e76b7362ebdd010895b3f854"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
 "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
 "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
@@ -3096,8 +3112,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
-"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
-"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
+"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac"
+"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
 "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf"
@@ -3134,14 +3150,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0256e318ad99c467d24bd7188f2d4a3028360621bb92d769b4b65fc44717d514"
-"checksum rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83430df7f76ea85c1f70fe145041576eee8fd5d77053bf426df24b480918d185"
-"checksum rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b03f874277103039816f6467b1ff30a81b1d6a29d4de6efccefe4c488f6535a"
-"checksum rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2e47cf949f06b0c7ab7566c2f69d49f28cb3ecf1bb8bf0bda48b1ba5b7945ae"
-"checksum rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "625e6fb41fde299082cda3bceb08f81c9ba56b14a2ec737b4366f9c3c9be07d8"
-"checksum rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474a23ef1a1245ae02c5fd6a1e9a0725ce6fd25ca2294703c03bddce041f867b"
+"checksum rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a01334797c5c4cf56cc40bb9636d7b4c4a076665b9b9b7f100fd666cf0a02ffc"
+"checksum rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03d6f8f7da0de905f6ef80dc14dce3bbc372430622b6aeb421cf13190bc70e8a"
+"checksum rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dfd6183804a685c48601651d8c8c7b0daa8f83b0b5e24edfbcb6a0337085127"
+"checksum rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f223157f51bf0e0621bef099de862468892ee4c4b83056f48f63e1bc00ccb72"
+"checksum rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2104a55a87d65cba8a845656f1f19a35da52af403863cd2a4bd5876ba522d879"
+"checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323"
+"checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
+"checksum rustfix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "165a212dd11124d7070892da20f71d82970ef1d1dd41cd804b70f39740a21c85"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade"
diff --git a/src/Cargo.toml b/src/Cargo.toml
index 814c054c51e..35858ee2868 100644
--- a/src/Cargo.toml
+++ b/src/Cargo.toml
@@ -40,14 +40,6 @@ members = [
   "tools/rls/test_data/workspace_symbol",
 ]
 
-# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
-# MSVC when running the compile-fail test suite when a should-fail test panics.
-# But hey if this is removed and it gets past the bots, sounds good to me.
-[profile.release]
-opt-level = 2
-[profile.bench]
-opt-level = 2
-
 # These options are controlled from our rustc wrapper script, so turn them off
 # here and have them controlled elsewhere.
 [profile.dev]
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 9ff681ac680..98c353eb6ec 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do:
   # execute tests in the standard library in stage0
   ./x.py test --stage 0 src/libstd
 
+  # execute tests in the core and standard library in stage0,
+  # without running doc tests (thus avoid depending on building the compiler)
+  ./x.py test --stage 0 --no-doc src/libcore src/libstd
+
   # execute all doc tests
   ./x.py test src/doc
   ```
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index b6ae824c376..3f97accaa4d 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -107,6 +107,13 @@ fn main() {
              env::join_paths(&dylib_path).unwrap());
     let mut maybe_crate = None;
 
+    // Print backtrace in case of ICE
+    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
+        cmd.env("RUST_BACKTRACE", "1");
+    }
+
+    cmd.env("RUSTC_BREAK_ON_ICE", "1");
+
     if let Some(target) = target {
         // The stage0 compiler has a special sysroot distinct from what we
         // actually downloaded, so we just always pass the `--sysroot` option.
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b9c82127342..9c35cb7f506 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -25,7 +25,7 @@ use compile;
 use install;
 use dist;
 use util::{exe, libdir, add_lib_path};
-use {Build, Mode};
+use {Build, Mode, DocTests};
 use cache::{INTERNER, Interned, Cache};
 use check;
 use test;
@@ -323,7 +323,7 @@ impl<'a> Builder<'a> {
                 test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
                 test::RunMakeFullDeps,
                 test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
-                test::TheBook, test::UnstableBook,
+                test::TheBook, test::UnstableBook, test::RustcBook,
                 test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
                 // Run run-make last, since these won't pass without make on Windows
                 test::RunMake, test::RustdocUi),
@@ -331,7 +331,7 @@ impl<'a> Builder<'a> {
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc,
                 doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample,
-                doc::CargoBook),
+                doc::RustcBook, doc::CargoBook),
             Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc,
                 dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src,
                 dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended,
@@ -591,6 +591,8 @@ impl<'a> Builder<'a> {
                 format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args));
         }
 
+        let want_rustdoc = self.doc_tests != DocTests::No;
+
         // Customize the compiler we're running. Specify the compiler to cargo
         // as our shim and then pass it some various options used to configure
         // how the actual compiler itself is called.
@@ -607,7 +609,7 @@ impl<'a> Builder<'a> {
              .env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
              .env("RUSTC_RPATH", self.config.rust_rpath.to_string())
              .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
-             .env("RUSTDOC_REAL", if cmd == "doc" || cmd == "test" {
+             .env("RUSTDOC_REAL", if cmd == "doc" || (cmd == "test" && want_rustdoc) {
                  self.rustdoc(compiler.host)
              } else {
                  PathBuf::from("/path/to/nowhere/rustdoc/not/required")
@@ -624,7 +626,7 @@ impl<'a> Builder<'a> {
         if let Some(ref error_format) = self.config.rustc_error_format {
             cargo.env("RUSTC_ERROR_FORMAT", error_format);
         }
-        if cmd != "build" && cmd != "check" {
+        if cmd != "build" && cmd != "check" && want_rustdoc {
             cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build)));
         }
 
@@ -706,6 +708,10 @@ impl<'a> Builder<'a> {
             cargo.env("RUSTC_PRINT_STEP_TIMINGS", "1");
         }
 
+        if self.config.backtrace_on_ice {
+            cargo.env("RUSTC_BACKTRACE_ON_ICE", "1");
+        }
+
         cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
 
         // in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful.
@@ -1403,4 +1409,39 @@ mod __test {
             },
         ]);
     }
+
+    #[test]
+    fn test_with_no_doc_stage0() {
+        let mut config = configure(&[], &[]);
+        config.stage = Some(0);
+        config.cmd = Subcommand::Test {
+            paths: vec!["src/libstd".into()],
+            test_args: vec![],
+            rustc_args: vec![],
+            fail_fast: true,
+            doc_tests: DocTests::No,
+        };
+
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+
+        let host = INTERNER.intern_str("A");
+
+        builder.run_step_descriptions(
+            &[StepDescription::from::<test::Crate>()],
+            &["src/libstd".into()],
+        );
+
+        // Ensure we don't build any compiler artifacts.
+        assert!(builder.cache.all::<compile::Rustc>().is_empty());
+        assert_eq!(first(builder.cache.all::<test::Crate>()), &[
+            test::Crate {
+                compiler: Compiler { host, stage: 0 },
+                target: host,
+                mode: Mode::Libstd,
+                test_kind: test::TestKind::Test,
+                krate: INTERNER.intern_str("std"),
+            },
+        ]);
+    }
 }
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 1b4b2c5fb2a..6dd6291be23 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -72,6 +72,7 @@ pub struct Config {
     pub dry_run: bool,
 
     pub deny_warnings: bool,
+    pub backtrace_on_ice: bool,
 
     // llvm codegen options
     pub llvm_enabled: bool,
@@ -306,6 +307,7 @@ struct Rust {
     wasm_syscall: Option<bool>,
     lld: Option<bool>,
     deny_warnings: Option<bool>,
+    backtrace_on_ice: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -325,6 +327,14 @@ struct TomlTarget {
 }
 
 impl Config {
+    fn path_from_python(var_key: &str) -> PathBuf {
+        match env::var_os(var_key) {
+            // Do not trust paths from Python and normalize them slightly (#49785).
+            Some(var_val) => Path::new(&var_val).components().collect(),
+            _ => panic!("expected '{}' to be set", var_key),
+        }
+    }
+
     pub fn default_opts() -> Config {
         let mut config = Config::default();
         config.llvm_enabled = true;
@@ -348,9 +358,9 @@ impl Config {
         config.deny_warnings = true;
 
         // set by bootstrap.py
-        config.src = env::var_os("SRC").map(PathBuf::from).expect("'SRC' to be set");
         config.build = INTERNER.intern_str(&env::var("BUILD").expect("'BUILD' to be set"));
-        config.out = env::var_os("BUILD_DIR").map(PathBuf::from).expect("'BUILD_DIR' set");
+        config.src = Config::path_from_python("SRC");
+        config.out = Config::path_from_python("BUILD_DIR");
 
         let stage0_root = config.out.join(&config.build).join("stage0/bin");
         config.initial_rustc = stage0_root.join(exe("rustc", &config.build));
@@ -523,6 +533,7 @@ impl Config {
             config.musl_root = rust.musl_root.clone().map(PathBuf::from);
             config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
             set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
+            set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
 
             if let Some(ref backends) = rust.codegen_backends {
                 config.rust_codegen_backends = backends.iter()
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index a0123da6d8f..3574b7d210a 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -120,6 +120,8 @@ v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
   "arm-unknown-linux-musleabi install directory")
 v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root",
   "arm-unknown-linux-musleabihf install directory")
+v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root",
+  "armv5te-unknown-linux-musleabi install directory")
 v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root",
   "armv7-unknown-linux-musleabihf install directory")
 v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index ae22260c564..16f4b29dcce 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -71,6 +71,7 @@ book!(
     Nomicon, "src/doc/nomicon", "nomicon";
     Reference, "src/doc/reference", "reference";
     Rustdoc, "src/doc/rustdoc", "rustdoc";
+    RustcBook, "src/doc/rustc", "rustc";
     RustByExample, "src/doc/rust-by-example", "rust-by-example";
 );
 
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 3eb9dca2aa8..5315a3028ff 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -19,7 +19,7 @@ use std::process;
 
 use getopts::Options;
 
-use Build;
+use {Build, DocTests};
 use config::Config;
 use metadata;
 use builder::Builder;
@@ -62,7 +62,7 @@ pub enum Subcommand {
         test_args: Vec<String>,
         rustc_args: Vec<String>,
         fail_fast: bool,
-        doc_tests: bool,
+        doc_tests: DocTests,
     },
     Bench {
         paths: Vec<PathBuf>,
@@ -171,7 +171,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
                     "extra options to pass the compiler when running tests",
                     "ARGS",
                 );
-                opts.optflag("", "doc", "run doc tests");
+                opts.optflag("", "no-doc", "do not run doc tests");
+                opts.optflag("", "doc", "only run doc tests");
             },
             "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
             "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -324,7 +325,13 @@ Arguments:
                     test_args: matches.opt_strs("test-args"),
                     rustc_args: matches.opt_strs("rustc-args"),
                     fail_fast: !matches.opt_present("no-fail-fast"),
-                    doc_tests: matches.opt_present("doc"),
+                    doc_tests: if matches.opt_present("doc") {
+                        DocTests::Only
+                    } else if matches.opt_present("no-doc") {
+                        DocTests::No
+                    } else {
+                        DocTests::Yes
+                    }
                 }
             }
             "bench" => {
@@ -411,10 +418,10 @@ impl Subcommand {
         }
     }
 
-    pub fn doc_tests(&self) -> bool {
+    pub fn doc_tests(&self) -> DocTests {
         match *self {
             Subcommand::Test { doc_tests, .. } => doc_tests,
-            _ => false,
+            _ => DocTests::Yes,
         }
     }
 }
diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs
index fa3ba02482f..6445ce8da33 100644
--- a/src/bootstrap/job.rs
+++ b/src/bootstrap/job.rs
@@ -122,12 +122,10 @@ struct JOBOBJECT_BASIC_LIMIT_INFORMATION {
 }
 
 pub unsafe fn setup(build: &mut Build) {
-    // Tell Windows to not show any UI on errors (such as not finding a required dll
-    // during startup or terminating abnormally).  This is important for running tests,
-    // since some of them use abnormal termination by design.
-    // This mode is inherited by all child processes.
-    let mode = SetErrorMode(SEM_NOGPFAULTERRORBOX); // read inherited flags
-    SetErrorMode(mode | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+    // Enable the Windows Error Reporting dialog which msys disables,
+    // so we can JIT debug rustc
+    let mode = SetErrorMode(0);
+    SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX);
 
     // Create a new job object for us to use
     let job = CreateJobObjectW(0 as *mut _, 0 as *const _);
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 0a7f0e5ff4e..e53fef06786 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -210,6 +210,16 @@ pub struct Compiler {
     host: Interned<String>,
 }
 
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]
+pub enum DocTests {
+    // Default, run normal tests and doc tests.
+    Yes,
+    // Do not run any doc tests.
+    No,
+    // Only run doc tests.
+    Only,
+}
+
 /// Global configuration for the build system.
 ///
 /// This structure transitively contains all configuration for the build system.
@@ -233,7 +243,7 @@ pub struct Build {
     rustfmt_info: channel::GitInfo,
     local_rebuild: bool,
     fail_fast: bool,
-    doc_tests: bool,
+    doc_tests: DocTests,
     verbosity: usize,
 
     // Targets for which to build.
@@ -294,7 +304,7 @@ impl Crate {
 ///
 /// These entries currently correspond to the various output directories of the
 /// build system, with each mod generating output in a different directory.
-#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub enum Mode {
     /// Build the standard library, placing output in the "stageN-std" directory.
     Libstd,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 08bbd68c756..cbb952bab61 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -32,13 +32,13 @@ use dist;
 use native;
 use tool::{self, Tool};
 use util::{self, dylib_path, dylib_path_var};
-use Mode;
+use {Mode, DocTests};
 use toolstate::ToolState;
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
 
 /// The two modes of the test runner; tests or benchmarks.
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
+#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
 pub enum TestKind {
     /// Run `cargo test`
     Test,
@@ -1212,6 +1212,7 @@ test_book!(
     Nomicon, "src/doc/nomicon", "nomicon", default=false;
     Reference, "src/doc/reference", "reference", default=false;
     RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
+    RustcBook, "src/doc/rustc", "rustc", default=true;
     RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
     TheBook, "src/doc/book", "book", default=false;
     UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
@@ -1406,13 +1407,13 @@ impl Step for CrateNotDefault {
 }
 
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Crate {
-    compiler: Compiler,
-    target: Interned<String>,
-    mode: Mode,
-    test_kind: TestKind,
-    krate: Interned<String>,
+    pub compiler: Compiler,
+    pub target: Interned<String>,
+    pub mode: Mode,
+    pub test_kind: TestKind,
+    pub krate: Interned<String>,
 }
 
 impl Step for Crate {
@@ -1518,8 +1519,14 @@ impl Step for Crate {
         if test_kind.subcommand() == "test" && !builder.fail_fast {
             cargo.arg("--no-fail-fast");
         }
-        if builder.doc_tests {
-            cargo.arg("--doc");
+        match builder.doc_tests {
+            DocTests::Only => {
+                cargo.arg("--doc");
+            }
+            DocTests::No => {
+                cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
+            }
+            DocTests::Yes => {}
         }
 
         cargo.arg("-p").arg(krate);
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index 00366301aa1..b195decfcf5 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -43,6 +43,10 @@ ENV STAGING_DIR=/tmp
 
 COPY scripts/musl.sh /build
 RUN env \
+    CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv5te -marm -mfloat-abi=soft" \
+    CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv5te -marm -mfloat-abi=soft" \
+    bash musl.sh armv5te && \
+    env \
     CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv6 -marm" \
     CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \
     bash musl.sh arm && \
@@ -84,6 +88,7 @@ ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi
+ENV TARGETS=$TARGETS,armv5te-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl
 ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
@@ -100,9 +105,12 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
     CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
     CC_armv5te_unknown_linux_gnueabi=arm-linux-gnueabi-gcc \
-    CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft"
+    CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft" \
+    CC_armv5te_unknown_linux_musleabi=arm-linux-gnueabi-gcc \
+    CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft"
 
 ENV RUST_CONFIGURE_ARGS \
+      --musl-root-armv5te=/musl-armv5te \
       --musl-root-arm=/musl-arm \
       --musl-root-armhf=/musl-armhf \
       --musl-root-armv7=/musl-armv7 \
diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile
index ae4641009cf..aab339f399c 100644
--- a/src/ci/docker/mingw-check/Dockerfile
+++ b/src/ci/docker/mingw-check/Dockerfile
@@ -19,4 +19,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu
diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile
index ff6ab1013b4..bdde7ad7fe8 100644
--- a/src/ci/docker/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile
@@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENV PARALLEL_CHECK 1
+ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-debug \
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 119b239d6b2..456f8cc7317 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -78,9 +78,9 @@ fi
 # sccache server at the start of the build, but no need to worry if this fails.
 SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true
 
-if [ "$PARALLEL_CHECK" != "" ]; then
+if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
   $SRC/configure --enable-experimental-parallel-queries
-  python2.7 ../x.py check
+  CARGO_INCREMENTAL=0 python2.7 ../x.py check
   rm -f config.toml
   rm -rf build
 fi
diff --git a/src/doc/book b/src/doc/book
-Subproject b889e1e30c5e9953834aa9fa6c982bb28df46ac
+Subproject f51127530d46b9acbf4747c859da185e771cfcf
diff --git a/src/doc/index.md b/src/doc/index.md
index 2ea889da1fd..3a4f51069fc 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -43,6 +43,10 @@ Rust's standard library has [extensive API documentation](std/index.html),
 with explanations of how to use various things, as well as example code for
 accomplishing various tasks.
 
+## The Rustc Book
+
+[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
+
 ## The Cargo Book
 
 [The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager.
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 3c56329d1bd9038e5341f1962bcd8d043312a71
+Subproject 748a5e6742db4a21c4c630a58087f818828e8a0
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 76296346e97c3702974d3398fdb94af9e10111a
+Subproject 134f419ee62714590b04712fe6072253bc2a782
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject d5ec87eabe5733cc2348c7dada89fc67c086f39
+Subproject eebda16e4b45f2eed4310cf7b9872cc75227816
diff --git a/src/doc/rustc/.gitignore b/src/doc/rustc/.gitignore
new file mode 100644
index 00000000000..7585238efed
--- /dev/null
+++ b/src/doc/rustc/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
new file mode 100644
index 00000000000..8adc05c5137
--- /dev/null
+++ b/src/doc/rustc/book.toml
@@ -0,0 +1,5 @@
+[book]
+authors = ["The Rust Project Developers"]
+multilingual = false
+src = "src"
+title = "The rustc book"
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
new file mode 100644
index 00000000000..e4c0939fd46
--- /dev/null
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -0,0 +1,16 @@
+# The Rustc Book
+
+- [What is rustc?](what-is-rustc.md)
+- [Command-line arguments](command-line-arguments.md)
+- [Lints](lints/index.md)
+    - [Lint levels](lints/levels.md)
+    - [Lint Groups](lints/groups.md)
+    - [Lint listing](lints/listing/index.md)
+        - [Allowed-by-default lints](lints/listing/allowed-by-default.md)
+        - [Warn-by-default lints](lints/listing/warn-by-default.md)
+        - [Deny-by-default lints](lints/listing/deny-by-default.md)
+- [Codegen options](codegen-options/index.md)
+- [Targets](targets/index.md)
+    - [Built-in Targets](targets/built-in.md)
+    - [Custom Targets](targets/custom.md)
+- [Contributing to `rustc`](contributing.md)
\ No newline at end of file
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
new file mode 100644
index 00000000000..eff09428902
--- /dev/null
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -0,0 +1,209 @@
+# Codegen options
+
+All of these options are passed to `rustc` via the `-C` flag, short for "codegen." You can see
+a version of this list for your exact compiler by running `rustc -C help`.
+
+## ar
+
+This option is deprecated and does nothing.
+
+## linker
+
+This flag lets you control which linker `rustc` invokes to link your code.
+
+## link-arg=val
+
+This flag lets you append a single extra argument to the linker invocation.
+
+"Append" is significant; you can pass this flag multiple times to add multiple arguments.
+
+## link-args
+
+This flag lets you append multiple extra arguments to the linker invocation. The
+options should be separated by spaces.
+
+## link-dead-code
+
+Normally, the linker will remove dead code. This flag disables this behavior.
+
+An example of when this flag might be useful is when trying to construct code coverage
+metrics.
+
+## lto
+
+This flag instructs LLVM to use [link time
+optimizations](https://llvm.org/docs/LinkTimeOptimization.html).
+
+It takes one of two values, `thin` and `fat`. 'thin' LTO [is a new feature of
+LLVM](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html),
+'fat' referring to the classic version of LTO.
+
+## target-cpu
+
+This instructs `rustc` to generate code specifically for a particular processor.
+
+You can run `rustc --print target-cpus` to see the valid options to pass
+here. Additionally, `native` can be passed to use the processor of the host
+machine.
+
+## target-feature
+
+Individual targets will support different features; this flag lets you control
+enabling or disabling a feature.
+
+To see the valid options and an example of use, run `rustc --print
+target-features`.
+
+## passes
+
+This flag can be used to add extra LLVM passes to the compilation.
+
+The list must be separated by spaces.
+
+## llvm-args
+
+This flag can be used to pass a list of arguments directly to LLVM.
+
+The list must be separated by spaces.
+
+## save-temps
+
+`rustc` will generate temporary files during compilation; normally it will
+delete them after it's done with its work. This option will cause them to be
+preserved instead of removed.
+
+## rpath
+
+This option allows you to set the value of
+[`rpath`](https://en.wikipedia.org/wiki/Rpath).
+
+## overflow-checks
+
+This flag allows you to control the behavior of integer overflow. This flag
+can be passed many options:
+
+* To turn overflow checks on: `y`, `yes`, or `on`.
+* To turn overflow checks off: `n`, `no`, or `off`.
+
+## no-prepopulate-passes
+
+The pass manager comes pre-populated with a list of passes; this flag
+ensures that list is empty.
+
+## no-vectorize-loops
+
+By default, `rustc` will attempt to [vectorize
+loops](https://llvm.org/docs/Vectorizers.html#the-loop-vectorizer). This
+flag will turn that behavior off.
+
+## no-vectorize-slp
+
+By default, `rustc` will attempt to vectorize loops using [superword-level
+parallelism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This
+flag will turn that behavior off.
+
+## soft-float
+
+This option will make `rustc` generate code using "soft floats." By default,
+a lot of hardware supports floating point instructions, and so the code generated
+will take advantage of this. "soft floats" emulate floating point instructions
+in software.
+
+## prefer-dynamic
+
+By default, `rustc` prefers to statically link dependencies. This option will
+make it use dynamic linking instead.
+
+## no-integrated-as
+
+LLVM comes with an internal assembler; this option will let you use an
+external assembler instead.
+
+## no-redzone
+
+This flag allows you to disable [the
+red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). This flag can
+be passed many options:
+
+* To enable the red zone: `y`, `yes`, or `on`.
+* To disable it: `n`, `no`, or `off`.
+
+## relocation-model
+
+This option lets you choose which relocation model to use.
+
+To find the valid options for this flag, run `rustc --print relocation-models`.
+
+## code-model=val
+
+This option lets you choose which code model to use.
+
+To find the valid options for this flag, run `rustc --print code-models`.
+
+## metadata
+
+This option allows you to control the metadata used for symbol mangling.
+
+## extra-filename
+
+This option allows you to put extra data in each output filename.
+
+## codegen-units
+
+This flag lets you control how many threads are used when doing
+code generation.
+
+Increasing paralellism may speed up compile times, but may also
+produce slower code.
+
+## remark
+
+This flag lets you print remarks for these optimization passes.
+
+The list of passes should be separated by spaces.
+
+`all` will remark on every pass.
+
+## no-stack-check
+
+This option is deprecated and does nothing.
+
+## debuginfo
+
+This flag lets you control debug information:
+
+* `0`: no debug info at all
+* `1`: line tables only
+* `2`: full debug info
+
+## opt-level
+
+This flag lets you control the optimization level.
+
+* `0`: no optimizations
+* `1`: basic optimizations
+* `2`: some optimizations
+* `3`: all optimizations
+* `s`: optimize for binary size
+* `z`: optimize for binary size, but also turn off loop vectorization.
+
+## debug-assertions
+
+This flag lets you turn `cfg(debug_assertions)` on or off.
+
+## inline-threshold
+
+This option lets you set the threshold for inlining a function.
+
+The default is 225.
+
+## panic
+
+This option lets you control what happens when the code panics.
+
+* `abort`: terminate the process upon panic
+* `unwind`: unwind the stack upon panic
+
+## incremental
+
+This flag allows you to enable incremental compilation.
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
new file mode 100644
index 00000000000..e2b001832fe
--- /dev/null
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -0,0 +1,116 @@
+# Command-line arguments
+
+Here's a list of command-line arguments to `rustc` and what they do.
+
+## `-h`/`--help`: get help
+
+This flag will print out help information for `rustc`.
+
+## `--cfg`: configure the compilation environment
+
+This flag can turn on or off various `#[cfg]` settings.
+
+## `-L`: add a directory to the library search path
+
+When looking for external crates, a directory passed to this flag will be searched.
+
+## `-l`: link the generated crate to a native library
+
+This flag allows you to specify linking to a specific native library when building
+a crate.
+
+## `--crate-type`: a list of types of crates for the compiler to emit
+
+This instructs `rustc` on which crate type to build.
+
+## `--crate-name`: specify the name of the crate being built
+
+This informs `rustc` of the name of your crate.
+
+## `--emit`: emit output other than a crate
+
+Instead of producing a crate, this flag can print out things like the assembly or LLVM-IR.
+
+## `--print`: print compiler information
+
+This flag prints out various information about the compiler.
+
+## `-g`: include debug information
+
+A synonym for `-C debug-level=2`.
+
+## `-O`: optimize your code
+
+A synonym for `-C opt-level=2`.
+
+## `-o`: filename of the output
+
+This flag controls the output filename.
+
+## `--out-dir`: directory to write the output in
+
+The outputted crate will be written to this directory.
+
+## `--explain`: provide a detailed explanation of an error message
+
+Each error of `rustc`'s comes with an error code; this will print
+out a longer explanation of a given error.
+
+## `--test`: build a test harness
+
+When compiling this crate, `rustc` will ignore your `main` function
+and instead produce a test harness.
+
+## `--target`: select a target triple to build
+
+This controls which [target](targets/index.html) to produce.
+
+## `-W`: set lint warnings
+
+This flag will set which lints should be set to the [warn level](lints/levels.html#warn).
+
+## `-A`: set lint allowed
+
+This flag will set which lints should be set to the [allow level](lints/levels.html#allow).
+
+## `-D`: set lint denied
+
+This flag will set which lints should be set to the [deny level](lints/levels.html#deny).
+
+## `-F`: set lint forbidden
+
+This flag will set which lints should be set to the [forbid level](lints/levels.html#forbid).
+
+## `--cap-lints`: set the most restrictive lint level
+
+This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-lints).
+
+## `-C`/`--codegen`: code generation options
+
+This flag will allow you to set [codegen options](codegen-options/index.html).
+
+## `-V`/`--version`: print a version
+
+This flag will print out `rustc`'s version.
+
+## `-v`/`--verbose`: use verbose output
+
+This flag, when combined with other flags, makes them produce extra output.
+
+## `--extern`: specify where an external library is located
+
+This flag allows you to pass the name and location of an external crate that will
+be linked into the crate you're buildling.
+
+## `--sysroot`: Override the system root
+
+The "sysroot" is where `rustc` looks for the crates that come with the Rust
+distribution; this flag allows that to be overridden.
+
+## `--error-format`: control how errors are produced
+
+This flag lets you control the format of errors.
+
+## `--color`: configure coloring of output
+
+This flag lets you control color settings of the output.
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
new file mode 100644
index 00000000000..fcb8e6b27db
--- /dev/null
+++ b/src/doc/rustc/src/contributing.md
@@ -0,0 +1,6 @@
+# Contributing to rustc
+
+We'd love to have your help improving `rustc`! To that end, we've written [a
+whole book](https://rust-lang-nursery.github.io/rustc-guide/) on its
+internals, how it works, and how to get started working on it. To learn
+more, you'll want to check that out.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md
new file mode 100644
index 00000000000..46b717f3387
--- /dev/null
+++ b/src/doc/rustc/src/lints/groups.md
@@ -0,0 +1,29 @@
+# Lint Groups
+
+`rustc` has the concept of a "lint group", where you can toggle several warnings
+through one name.
+
+For example, the `nonstandard-style` lint sets `non-camel-case-types`,
+`non-snake-case`, and `non-upper-case-globals` all at once. So these are
+equivalent:
+
+```bash
+$ rustc -D nonstandard-style
+$ rustc -D non-camel-case-types -D non-snake-case -D non-upper-case-globals
+```
+
+Here's a list of each lint group, and the lints that they are made up of:
+
+| group               | description                                                   | lints                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
+|---------------------|---------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| nonstandard-style   | Violation of standard naming conventions                      | non-camel-case-types, non-snake-case, non-upper-case-globals                                                                                                                                                                                                                                                                                                                                                                                                                           |
+| warnings            | all lints that would be issuing warnings                      | all lints that would be issuing warnings                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+| edition-2018        | Lints that will be turned into errors in Rust 2018            | tyvar-behind-raw-pointer                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+| rust-2018-idioms    | Lints to nudge you toward idiomatic features of Rust 2018     | bare-trait-object, unreachable-pub                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+| unused              | These lints detect things being declared but not used         | unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comment, unused-extern-crates, unused-features, unused-parens                                                                                                                                                                                    |
+| future-incompatible | Lints that detect code that has future-compatibility problems | private-in-public, pub-use-of-private-extern-crate, patterns-in-fns-without-body, safe-extern-statics, invalid-type-param-default, legacy-directory-ownership, legacy-imports, legacy-constructor-visibility, missing-fragment-specifier, illegal-floating-point-literal-pattern, anonymous-parameters, parenthesized-params-in-types-and-modules, late-bound-lifetime-arguments, safe-packed-borrows, incoherent-fundamental-impls, tyvar-behind-raw-pointer, unstable-name-collision |
+
+Additionally, there's a `bad-style` lint group that's a deprecated alias for `nonstandard-style`.
+
+Finally, you can also see the table above by invoking `rustc -W help`. This will give you the exact values for the specific
+compiler you have installed.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md
new file mode 100644
index 00000000000..bf345a24389
--- /dev/null
+++ b/src/doc/rustc/src/lints/index.md
@@ -0,0 +1,28 @@
+# Lints
+
+In software, a "lint" is a tool used to help improve your source code. The
+Rust compiler contains a number of lints, and when it compiles your code, it will
+also run the lints. These lints may produce a warning, an error, or nothing at all,
+depending on how you've configured things.
+
+Here's a small example:
+
+```bash
+$ cat main.rs
+fn main() {
+    let x = 5;
+}
+> rustc main.rs
+warning: unused variable: `x`
+ --> main.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^
+  |
+  = note: #[warn(unused_variables)] on by default
+  = note: to avoid this warning, consider using `_x` instead
+```
+
+This is the `unused_variables` lint, and it tells you that you've introduced
+a variable that you don't use in your code. That's not *wrong*, so it's not
+an error, but it might be a bug, so you get a warning.
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
new file mode 100644
index 00000000000..19bb6707d22
--- /dev/null
+++ b/src/doc/rustc/src/lints/levels.md
@@ -0,0 +1,252 @@
+# Lint levels
+
+In `rustc`, lints are divided into four *levels*:
+
+1. allow
+2. warn
+3. deny
+4. forbid
+
+Each lint has a default level (explained in the lint listing later in this
+chapter), and the compiler has a default warning level. First, let's explain
+what these levels mean, and then we'll talk about configuration.
+
+## allow
+
+These lints exist, but by default, do nothing. For example, consider this
+source:
+
+```rust
+pub fn foo() {}
+```
+
+Compiling this file produces no warnings:
+
+```bash
+$ rustc lib.rs --crate-type=lib
+$
+```
+
+But this code violates the `missing_docs` lint.
+
+These lints exist mostly to be manually turned on via configuration, as we'll
+talk about later in this section.
+
+## warn
+
+The 'warn' lint level will produce a warning if you violate the lint. For example,
+this code runs afoul of the `unused_variable` lint:
+
+```rust
+pub fn foo() {
+    let x = 5;
+}
+```
+
+This will produce this warning:
+
+```console
+$ rustc lib.rs --crate-type=lib
+warning: unused variable: `x`
+ --> lib.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^
+  |
+  = note: #[warn(unused_variables)] on by default
+  = note: to avoid this warning, consider using `_x` instead
+```
+
+## deny
+
+A 'deny' lint produces an error if you violate it. For example, this code
+runs into the `exceeding_bitshifts` lint.
+
+```rust,ignore
+fn main() {
+    100u8 << 10;
+}
+```
+
+```bash
+> rustc main.rs
+error: bitshift exceeds the type's number of bits
+ --> main.rs:2:13
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^
+  |
+  = note: #[deny(exceeding_bitshifts)] on by default
+```
+
+What's the difference between an error from a lint and a regular old error?
+Lints are configurable via levels, so in a similar way to 'allow' lints,
+warnings that are 'deny' by default let you allow them. Similarly, you may
+wish to set up a lint that is `warn` by default to produce an error instead.
+This lint level gives you that.
+
+## forbid
+
+'forbid' is a special lint level that's stronger than 'deny'. It's the same
+as 'deny' in that a lint at this level will produce an error, but unlike the
+'deny' level, the 'forbid' level can not be overridden to be anything lower
+than an error.
+
+## Configuring warning levels
+
+Remember our `missing_docs` example from the 'allow' lint level?
+
+```bash
+$ cat lib.rs
+pub fn foo() {}
+$ rustc lib.rs --crate-type=lib
+$
+```
+
+We can configure this lint to operate at a higher level, both with
+compiler flags, as well as with an attribute in the source code.
+
+You can also "cap" lints so that the compiler can choose to ignore
+certain lint levels. We'll talk about that last.
+
+### Via compiler flag
+
+The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints
+into allowed, warning, deny, or forbid levels, like this:
+
+```bash
+$ rustc lib.rs --crate-type=lib -W missing-docs
+warning: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+  |
+  = note: requested on the command line with `-W missing-docs`
+
+warning: missing documentation for a function
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+> rustc lib.rs --crate-type=lib -D missing-docs
+error: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+  |
+  = note: requested on the command line with `-D missing-docs`
+
+error: missing documentation for a function
+ --> lib.rs:1:1
+  |
+1 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+```
+
+You can also pass each flag more than once for changing multiple lints:
+
+```bash
+rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables
+```
+
+And of course, you can mix these four flags together:
+
+```bash
+rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
+```
+
+### Via an attribute
+
+You can also modify the lint level with a crate-wide attribute:
+
+```bash
+> cat lib.rs
+#![warn(missing_docs)]
+
+pub fn foo() {}
+$ rustc lib.rs --crate-type=lib
+warning: missing documentation for crate
+ --> lib.rs:1:1
+  |
+1 | / #![warn(missing_docs)]
+2 | |
+3 | | pub fn foo() {}
+  | |_______________^
+  |
+note: lint level defined here
+ --> lib.rs:1:9
+  |
+1 | #![warn(missing_docs)]
+  |         ^^^^^^^^^^^^
+
+warning: missing documentation for a function
+ --> lib.rs:3:1
+  |
+3 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+```
+
+All four, `warn`, `allow`, `deny`, and `forbid` all work this way.
+
+You can also pass in multiple lints per attribute:
+
+```rust
+#![warn(missing_docs, unused_variables)]
+
+pub fn foo() {}
+```
+
+And use multiple attributes together:
+
+```rust
+#![warn(missing_docs)]
+#![deny(unused_variables)]
+
+pub fn foo() {}
+```
+
+### Capping lints
+
+`rustc` supports a flag, `--cap-lints LEVEL` that sets the "lint cap level."
+This is the maximum level for all lints. So for example, if we take our
+code sample from the "deny" lint level above:
+
+```rust,ignore
+fn main() {
+    100u8 << 10;
+}
+```
+
+And we compile it, capping lints to warn:
+
+```bash
+$ rustc lib.rs --cap-lints warn
+warning: bitshift exceeds the type's number of bits
+ --> lib.rs:2:5
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^
+  |
+  = note: #[warn(exceeding_bitshifts)] on by default
+
+warning: this expression will panic at run-time
+ --> lib.rs:2:5
+  |
+2 |     100u8 << 10;
+  |     ^^^^^^^^^^^ attempt to shift left with overflow
+```
+
+It now only warns, rather than errors. We can go further and allow all lints:
+
+```bash
+$ rustc lib.rs --cap-lints allow
+$
+```
+
+This feature is used heavily by Cargo; it will pass `--cap-lints allow` when
+compiling your dependencies, so that if they have any warnings, they do not
+pollute the output of your build.
diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md
new file mode 100644
index 00000000000..e1a3f96a6fe
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md
@@ -0,0 +1,453 @@
+# Allowed-by-default lints
+
+These lints are all set to the 'allow' level by default. As such, they won't show up
+unless you set them to a higher lint level with a flag or attribute.
+
+## anonymous-parameters
+
+This lint detects anonymous parameters. Some example code that triggers this lint:
+
+```rust
+trait Foo {
+    fn foo(usize);
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: use of deprecated anonymous parameter
+ --> src/lib.rs:5:11
+  |
+5 |     fn foo(usize);
+  |           ^
+  |
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+```
+
+This syntax is mostly a historical accident, and can be worked around quite
+easily:
+
+```rust
+trait Foo {
+    fn foo(_: usize);
+}
+```
+
+## bare-trait-object
+
+This lint suggests using `dyn Trait` for trait objects. Some example code
+that triggers this lint:
+
+```rust
+#![feature(dyn_trait)]
+
+trait Trait { }
+
+fn takes_trait_object(_: Box<Trait>) {
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trait objects without an explicit `dyn` are deprecated
+ --> src/lib.rs:7:30
+  |
+7 | fn takes_trait_object(_: Box<Trait>) {
+  |                              ^^^^^ help: use `dyn`: `dyn Trait`
+  |
+```
+
+To fix it, do as the help message suggests:
+
+```rust
+#![feature(dyn_trait)]
+#![deny(bare_trait_object)]
+
+trait Trait { }
+
+fn takes_trait_object(_: Box<dyn Trait>) {
+}
+```
+
+## box-pointers
+
+This lints use of the Box type. Some example code that triggers this lint:
+
+```rust
+struct Foo {
+    x: Box<isize>,
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type uses owned (Box type) pointers: std::boxed::Box<isize>
+ --> src/lib.rs:6:5
+  |
+6 |     x: Box<isize> //~ ERROR type uses owned
+  |     ^^^^^^^^^^^^^
+  |
+```
+
+This lint is mostly historical, and not particularly useful. `Box<T>` used to
+be built into the language, and the only way to do heap allocation. Today's
+Rust can call into other allocators, etc.
+
+## elided-lifetime-in-path
+
+This lint detects the use of hidden lifetime parameters. Some example code
+that triggers this lint:
+
+```rust
+struct Foo<'a> {
+    x: &'a u32
+}
+
+fn foo(x: &Foo) {
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: hidden lifetime parameters are deprecated, try `Foo<'_>`
+ --> src/lib.rs:5:12
+  |
+5 | fn foo(x: &Foo) {
+  |            ^^^
+  |
+```
+
+Lifetime elision elides this lifetime, but that is being deprecated.
+
+## missing-copy-implementations
+
+This lint detects potentially-forgotten implementations of `Copy`. Some
+example code that triggers this lint:
+
+```rust
+pub struct Foo {
+    pub field: i32
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type could implement `Copy`; consider adding `impl Copy`
+ --> src/main.rs:3:1
+  |
+3 | / pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy`
+4 | |     pub field: i32
+5 | | }
+  | |_^
+  |
+```
+
+You can fix the lint by deriving `Copy`.
+
+This lint is set to 'allow' because this code isn't bad; it's common to write
+newtypes like this specifically so that a `Copy` type is no longer `Copy`.
+
+## missing-debug-implementations
+
+This lint detects missing implementations of `fmt::Debug`. Some example code
+that triggers this lint:
+
+```rust
+pub struct Foo;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation
+ --> src/main.rs:3:1
+  |
+3 | pub struct Foo;
+  | ^^^^^^^^^^^^^^^
+  |
+```
+
+You can fix the lint by deriving `Debug`.
+
+## missing-docs
+
+This lint detects missing documentation for public items. Some example code
+that triggers this lint:
+
+```rust
+pub fn foo() {}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: missing documentation for crate
+ --> src/main.rs:1:1
+  |
+1 | / #![deny(missing_docs)]
+2 | |
+3 | | pub fn foo() {}
+4 | |
+5 | | fn main() {}
+  | |____________^
+  |
+
+error: missing documentation for a function
+ --> src/main.rs:3:1
+  |
+3 | pub fn foo() {}
+  | ^^^^^^^^^^^^
+
+```
+
+To fix the lint, add documentation to all items.
+
+## single-use-lifetime
+
+This lint detects lifetimes that are only used once. Some example code that
+triggers this lint:
+
+```rust
+struct Foo<'x> {
+    x: &'x u32
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: lifetime name `'x` only used once
+ --> src/main.rs:3:12
+  |
+3 | struct Foo<'x> {
+  |            ^^
+  |
+```
+
+## trivial-casts
+
+This lint detects trivial casts which could be removed. Some example code
+that triggers this lint:
+
+```rust
+let x: &u32 = &42;
+let _ = x as *const u32;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trivial cast: `&u32` as `*const u32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
+ --> src/main.rs:5:13
+  |
+5 |     let _ = x as *const u32;
+  |             ^^^^^^^^^^^^^^^
+  |
+note: lint level defined here
+ --> src/main.rs:1:9
+  |
+1 | #![deny(trivial_casts)]
+  |         ^^^^^^^^^^^^^
+```
+
+## trivial-numeric-casts
+
+This lint detects trivial casts of numeric types which could be removed. Some
+example code that triggers this lint:
+
+```rust
+let x = 42i32 as i32;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: trivial numeric cast: `i32` as `i32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
+ --> src/main.rs:4:13
+  |
+4 |     let x = 42i32 as i32;
+  |             ^^^^^^^^^^^^
+  |
+```
+
+## unreachable-pub
+
+This lint triggers for `pub` items not reachable from the crate root. Some
+example code that triggers this lint:
+
+```rust
+mod foo {
+    pub mod bar {
+        
+    }
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unreachable `pub` item
+ --> src/main.rs:4:5
+  |
+4 |     pub mod bar {
+  |     ---^^^^^^^^
+  |     |
+  |     help: consider restricting its visibility: `pub(crate)`
+  |
+```
+
+## unsafe-code
+
+This lint catches usage of `unsafe` code. Some example code that triggers this lint:
+
+```rust
+fn main() {
+    unsafe {
+
+    }
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: usage of an `unsafe` block
+ --> src/main.rs:4:5
+  |
+4 | /     unsafe {
+5 | |         
+6 | |     }
+  | |_____^
+  |
+```
+
+## unstable-features
+
+This lint is deprecated and no longer used.
+
+## unused-extern-crates
+
+This lint guards against `extern crate` items that are never used. Some
+example code that triggers this lint:
+
+```rust,ignore
+extern crate semver;
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused extern crate
+ --> src/main.rs:3:1
+  |
+3 | extern crate semver;
+  | ^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-import-braces
+
+This lint catches unnecessary braces around an imported item. Some example
+code that triggers this lint:
+
+```rust
+use test::{A};
+
+pub mod test {
+    pub struct A;
+}
+# fn main() {}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: braces around A is unnecessary
+ --> src/main.rs:3:1
+  |
+3 | use test::{A};
+  | ^^^^^^^^^^^^^^
+  |
+```
+
+To fix it, `use test::A;`
+
+## unused-qualifications
+
+This lint detects unnecessarily qualified names. Some example code that triggers this lint:
+
+```rust
+mod foo {
+    pub fn bar() {}
+}
+
+fn main() {
+    use foo::bar;
+    foo::bar();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unnecessary qualification
+ --> src/main.rs:9:5
+  |
+9 |     foo::bar();
+  |     ^^^^^^^^
+  |
+```
+
+You can call `bar()` directly, without the `foo::`.
+
+## unused-results
+
+This lint checks for the unused result of an expression in a statement. Some
+example code that triggers this lint:
+
+```rust,no_run
+fn foo<T>() -> T { panic!() }
+
+fn main() {
+    foo::<usize>();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused result
+ --> src/main.rs:6:5
+  |
+6 |     foo::<usize>();
+  |     ^^^^^^^^^^^^^^^
+  |
+```
+
+## variant-size-differences
+
+This lint detects enums with widely varying variant sizes. Some example code that triggers this lint:
+
+```rust
+enum En {
+    V0(u8),
+    VBig([u8; 1024]),
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: enum variant is more than three times larger (1024 bytes) than the next largest
+ --> src/main.rs:5:5
+  |
+5 |     VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+  |     ^^^^^^^^^^^^^^^^
+  |
+```
diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md
new file mode 100644
index 00000000000..e7ec6af8be1
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/deny-by-default.md
@@ -0,0 +1,241 @@
+# Deny-by-default lints
+
+These lints are all set to the 'deny' level by default.
+
+## exceeding-bitshifts
+
+This lint detects that a shift exceeds the type's number of bits. Some
+example code that triggers this lint:
+
+```rust,ignore
+1_i32 << 32;
+```
+
+This will produce:
+
+```text
+error: bitshift exceeds the type's number of bits
+ --> src/main.rs:2:5
+  |
+2 |     1_i32 << 32;
+  |     ^^^^^^^^^^^
+  |
+```
+
+## invalid-type-param-default
+
+This lint detects type parameter default erroneously allowed in invalid location. Some
+example code that triggers this lint:
+
+```rust,ignore
+fn foo<T=i32>(t: T) {}
+```
+
+This will produce:
+
+```text
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+ --> src/main.rs:4:8
+  |
+4 | fn foo<T=i32>(t: T) {}
+  |        ^
+  |
+  = note: #[deny(invalid_type_param_default)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+```
+
+## legacy-constructor-visibility
+
+[RFC 1506](https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md) modified some
+visibility rules, and changed the visibility of struct constructors. Some
+example code that triggers this lint:
+
+```rust,ignore
+mod m {
+    pub struct S(u8);
+    
+    fn f() {
+        // this is trying to use S from the 'use' line, but becuase the `u8` is
+        // not pub, it is private
+        ::S;
+    }
+}
+
+use m::S;
+```
+
+This will produce:
+
+```text
+error: private struct constructors are not usable through re-exports in outer modules
+ --> src/main.rs:5:9
+  |
+5 |         ::S;
+  |         ^^^
+  |
+  = note: #[deny(legacy_constructor_visibility)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #39207 <https://github.com/rust-lang/rust/issues/39207>
+```
+
+
+## legacy-directory-ownership
+
+The legacy_directory_ownership warning is issued when
+
+* There is a non-inline module with a #[path] attribute (e.g. #[path = "foo.rs"] mod bar;),
+* The module's file ("foo.rs" in the above example) is not named "mod.rs", and
+* The module's file contains a non-inline child module without a #[path] attribute.
+
+The warning can be fixed by renaming the parent module to "mod.rs" and moving
+it into its own directory if appropriate.
+
+## legacy-imports
+
+This lint detects names that resolve to ambiguous glob imports. Some example
+code that triggers this lint:
+
+```rust,ignore
+pub struct Foo;
+
+mod bar {
+    struct Foo;
+
+    mod baz {
+        use *;
+        use bar::*;
+        fn f(_: Foo) {}
+    }
+}
+```
+
+This will produce:
+
+```text
+error: `Foo` is ambiguous
+ --> src/main.rs:9:17
+  |
+7 |         use *;
+  |             - `Foo` could refer to the name imported here
+8 |         use bar::*;
+  |             ------ `Foo` could also refer to the name imported here
+9 |         fn f(_: Foo) {}
+  |                 ^^^
+  |
+  = note: #[deny(legacy_imports)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #38260 <https://github.com/rust-lang/rust/issues/38260>
+```
+
+
+## missing-fragment-specifier
+
+The missing_fragment_specifier warning is issued when an unused pattern in a
+`macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not
+followed by a fragment specifier (e.g. `:expr`).
+
+This warning can always be fixed by removing the unused pattern in the
+`macro_rules!` macro definition.
+
+## mutable-transmutes
+
+This lint catches transmuting from `&T` to `&mut T` becuase it is undefined
+behavior. Some example code that triggers this lint:
+
+```rust,ignore
+unsafe {
+    let y = std::mem::transmute::<&i32, &mut i32>(&5);
+}
+```
+
+This will produce:
+
+```text
+error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell
+ --> src/main.rs:3:17
+  |
+3 |         let y = std::mem::transmute::<&i32, &mut i32>(&5);
+  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+
+## no-mangle-const-items
+
+This lint detects any `const` items with the `#[no_mangle]` attribute.
+Constants do not have their symbols exported, and therefore, this probably
+means you meant to use a `static`, not a `const`. Some example code that
+triggers this lint:
+
+```rust,ignore
+#[no_mangle]
+const FOO: i32 = 5;
+```
+
+This will produce:
+
+```text
+error: const items should never be #[no_mangle]
+ --> src/main.rs:3:1
+  |
+3 | const FOO: i32 = 5;
+  | -----^^^^^^^^^^^^^^
+  | |
+  | help: try a static value: `pub static`
+  |
+```
+
+## parenthesized-params-in-types-and-modules
+
+This lint detects incorrect parentheses. Some example code that triggers this
+lint:
+
+```rust,ignore
+let x = 5 as usize();
+```
+
+This will produce:
+
+```text
+error: parenthesized parameters may only be used with a trait
+ --> src/main.rs:2:21
+  |
+2 |   let x = 5 as usize();
+  |                     ^^
+  |
+  = note: #[deny(parenthesized_params_in_types_and_modules)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
+```
+
+To fix it, remove the `()`s.
+
+## pub-use-of-private-extern-crate
+
+This lint detects a specific situation of re-exporting a private `extern crate`;
+
+## safe-extern-statics
+
+In older versions of Rust, there was a soundness issue where `extern static`s were allowed
+to be accessed in safe code. This lint now catches and denies this kind of code.
+
+## unknown-crate-types
+
+This lint detects an unknown crate type found in a `#[crate_type]` directive. Some
+example code that triggers this lint:
+
+```rust,ignore
+#![crate_type="lol"]
+```
+
+This will produce:
+
+```text
+error: invalid `crate_type` value
+ --> src/lib.rs:1:1
+  |
+1 | #![crate_type="lol"]
+  | ^^^^^^^^^^^^^^^^^^^^
+  |
+```
diff --git a/src/doc/rustc/src/lints/listing/index.md b/src/doc/rustc/src/lints/listing/index.md
new file mode 100644
index 00000000000..18cd2fe32a3
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/index.md
@@ -0,0 +1,5 @@
+# Lint listing
+
+This section lists out all of the lints, grouped by their default lint levels.
+
+You can also see this list by running `rustc -W help`.
\ No newline at end of file
diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md
new file mode 100644
index 00000000000..1171f75caa1
--- /dev/null
+++ b/src/doc/rustc/src/lints/listing/warn-by-default.md
@@ -0,0 +1,1039 @@
+# Warn-by-default lints
+
+These lints are all set to the 'warn' level by default.
+
+## const-err
+
+This lint detects an erroneous expression while doing constant evaluation. Some
+example code that triggers this lint:
+
+```rust,ignore
+let b = 200u8 + 200u8;
+```
+
+This will produce:
+
+```text
+warning: attempt to add with overflow
+ --> src/main.rs:2:9
+  |
+2 | let b = 200u8 + 200u8;
+  |         ^^^^^^^^^^^^^
+  |
+```
+
+## dead-code
+
+This lint detects detect unused, unexported items. Some
+example code that triggers this lint:
+
+```rust
+fn foo() {}
+```
+
+This will produce:
+
+```text
+warning: function is never used: `foo`
+ --> src/lib.rs:2:1
+  |
+2 | fn foo() {}
+  | ^^^^^^^^
+  |
+```
+
+## deprecated
+
+This lint detects detects use of deprecated items. Some
+example code that triggers this lint:
+
+```rust
+#[deprecated]
+fn foo() {}
+
+fn bar() {
+    foo();
+}
+```
+
+This will produce:
+
+```text
+warning: use of deprecated item 'foo'
+ --> src/lib.rs:7:5
+  |
+7 |     foo();
+  |     ^^^
+  |
+```
+
+## illegal-floating-point-literal-pattern
+
+This lint detects floating-point literals used in patterns. Some example code
+that triggers this lint:
+
+```rust
+let x = 42.0;
+
+match x {
+    5.0 => {},
+    _ => {},
+}
+```
+
+This will produce:
+
+```text
+warning: floating-point literals cannot be used in patterns
+ --> src/main.rs:4:9
+  |
+4 |         5.0 => {},
+  |         ^^^
+  |
+  = note: #[warn(illegal_floating_point_literal_pattern)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+```
+
+## improper-ctypes
+
+This lint detects proper use of libc types in foreign modules. Some
+example code that triggers this lint:
+
+```rust
+extern "C" {
+    static STATIC: String;
+}
+```
+
+This will produce:
+
+```text
+warning: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type
+ --> src/main.rs:2:20
+  |
+2 |     static STATIC: String;
+  |                    ^^^^^^
+  |
+```
+
+## incoherent-fundamental-impls
+
+This lint detects potentially-conflicting impls that were erroneously allowed. Some
+example code that triggers this lint:
+
+```rust
+pub trait Trait1<X> {
+    type Output;
+}
+
+pub trait Trait2<X> {}
+
+pub struct A;
+
+impl<X, T> Trait1<X> for T where T: Trait2<X> {
+    type Output = ();
+}
+
+impl<X> Trait1<Box<X>> for A {
+    type Output = i32;
+}
+```
+
+This will produce:
+
+```text
+warning: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
+  --> src/main.rs:13:1
+   |
+9  | impl<X, T> Trait1<X> for T where T: Trait2<X> {
+   | --------------------------------------------- first implementation here
+...
+13 | impl<X> Trait1<Box<X>> for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
+   |
+   = note: #[warn(incoherent_fundamental_impls)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
+   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
+```
+
+## late-bound-lifetime-arguments
+
+This lint detects detects generic lifetime arguments in path segments with
+late bound lifetime parameters. Some example code that triggers this lint:
+
+```rust
+struct S;
+
+impl S {
+    fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+}
+
+fn main() {
+    S.late::<'static>(&0, &0);
+}
+```
+
+This will produce:
+
+```text
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> src/main.rs:8:14
+  |
+4 |     fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
+  |             -- the late bound lifetime parameter is introduced here
+...
+8 |     S.late::<'static>(&0, &0);
+  |              ^^^^^^^
+  |
+  = note: #[warn(late_bound_lifetime_arguments)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+```
+
+## non-camel-case-types
+
+This lint detects types, variants, traits and type parameters that don't have
+camel case names. Some example code that triggers this lint:
+
+```rust
+struct s;
+```
+
+This will produce:
+
+```text
+warning: type `s` should have a camel case name such as `S`
+ --> src/main.rs:1:1
+  |
+1 | struct s;
+  | ^^^^^^^^^
+  |
+```
+
+## non-shorthand-field-patterns
+
+This lint detects using `Struct { x: x }` instead of `Struct { x }` in a pattern. Some
+example code that triggers this lint:
+
+```rust
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+
+fn main() {
+    let p = Point {
+        x: 5,
+        y: 5,
+    };
+
+    match p {
+        Point { x: x, y: y } => (),
+    }
+}
+```
+
+This will produce:
+
+```text
+warning: the `x:` in this pattern is redundant
+  --> src/main.rs:14:17
+   |
+14 |         Point { x: x, y: y } => (),
+   |                 --^^
+   |                 |
+   |                 help: remove this
+   |
+
+warning: the `y:` in this pattern is redundant
+  --> src/main.rs:14:23
+   |
+14 |         Point { x: x, y: y } => (),
+   |                       --^^
+   |                       |
+   |                       help: remove this
+
+```
+
+## non-snake-case
+
+This lint detects variables, methods, functions, lifetime parameters and
+modules that don't have snake case names. Some example code that triggers
+this lint:
+
+```rust
+let X = 5;
+```
+
+This will produce:
+
+```text
+warning: variable `X` should have a snake case name such as `x`
+ --> src/main.rs:2:9
+  |
+2 |     let X = 5;
+  |         ^
+  |
+```
+
+## non-upper-case-globals
+
+This lint detects static constants that don't have uppercase identifiers.
+Some example code that triggers this lint:
+
+```rust
+static x: i32 = 5;
+```
+
+This will produce:
+
+```text
+warning: static variable `x` should have an upper case name such as `X`
+ --> src/main.rs:1:1
+  |
+1 | static x: i32 = 5;
+  | ^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## no-mangle-generic-items
+
+This lint detects generic items must be mangled. Some
+example code that triggers this lint:
+
+```rust
+#[no_mangle]
+fn foo<T>(t: T) {
+
+}
+```
+
+This will produce:
+
+```text
+warning: functions generic over types must be mangled
+ --> src/main.rs:2:1
+  |
+1 |   #[no_mangle]
+  |   ------------ help: remove this attribute
+2 | / fn foo<T>(t: T) {
+3 | |     
+4 | | }
+  | |_^
+  |
+```
+
+## overflowing-literals
+
+This lint detects literal out of range for its type. Some
+example code that triggers this lint:
+
+```rust
+let x: u8 = 1000;
+```
+
+This will produce:
+
+```text
+warning: literal out of range for u8
+ --> src/main.rs:2:17
+  |
+2 |     let x: u8 = 1000;
+  |                 ^^^^
+  |
+```
+
+## path-statements
+
+This lint detects path statements with no effect. Some example code that
+triggers this lint:
+
+```rust
+let x = 42;
+
+x;
+```
+
+This will produce:
+
+```text
+warning: path statement with no effect
+ --> src/main.rs:3:5
+  |
+3 |     x;
+  |     ^^
+  |
+```
+
+## patterns-in-fns-without-body
+
+This lint detects patterns in functions without body were that were
+previously erroneously allowed. Some example code that triggers this lint:
+
+```rust
+trait Trait {
+    fn foo(mut arg: u8);
+}
+```
+
+This will produce:
+
+```text
+warning: patterns aren't allowed in methods without bodies
+ --> src/main.rs:2:12
+  |
+2 |     fn foo(mut arg: u8);
+  |            ^^^^^^^
+  |
+  = note: #[warn(patterns_in_fns_without_body)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
+```
+
+To fix this, remove the pattern; it can be used in the implementation without
+being used in the definition. That is:
+
+```rust
+trait Trait {
+    fn foo(arg: u8);
+}
+
+impl Trait for i32 {
+    fn foo(mut arg: u8) {
+
+    }
+}
+```
+
+## plugin-as-library
+
+This lint detects when compiler plugins are used as ordinary library in
+non-plugin crate. Some example code that triggers this lint:
+
+```rust,ignore
+#![feature(plugin)]
+#![plugin(macro_crate_test)]
+
+extern crate macro_crate_test;
+```
+
+## private-in-public
+
+This lint detects detect private items in public interfaces not caught by the old implementation. Some
+example code that triggers this lint:
+
+```rust,ignore
+pub trait Trait {
+    type A;
+}
+
+pub struct S;
+
+mod foo {
+    struct Z;
+
+    impl ::Trait for ::S {
+        type A = Z;
+    }
+}
+# fn main() {}
+```
+
+This will produce:
+
+```text
+error[E0446]: private type `foo::Z` in public interface
+  --> src/main.rs:11:9
+   |
+11 |         type A = Z;
+   |         ^^^^^^^^^^^ can't leak private type
+```
+
+## private-no-mangle-fns
+
+This lint detects functions marked `#[no_mangle]` that are also private.
+Given that private functions aren't exposed publicly, and `#[no_mangle]`
+controls the public symbol, this combination is erroneous. Some example code
+that triggers this lint:
+
+```rust
+#[no_mangle]
+fn foo() {}
+```
+
+This will produce:
+
+```text
+warning: function is marked #[no_mangle], but not exported
+ --> src/main.rs:2:1
+  |
+2 | fn foo() {}
+  | -^^^^^^^^^^
+  | |
+  | help: try making it public: `pub`
+  |
+```
+
+To fix this, either make it public or remove the `#[no_mangle]`.
+
+## private-no-mangle-statics
+
+This lint detects any statics marked `#[no_mangle]` that are private.
+Given that private statics aren't exposed publicly, and `#[no_mangle]`
+controls the public symbol, this combination is erroneous. Some example code
+that triggers this lint:
+
+```rust
+#[no_mangle]
+static X: i32 = 4;
+```
+
+This will produce:
+
+```text
+warning: static is marked #[no_mangle], but not exported
+ --> src/main.rs:2:1
+  |
+2 | static X: i32 = 4;
+  | -^^^^^^^^^^^^^^^^^
+  | |
+  | help: try making it public: `pub`
+  |
+```
+
+To fix this, either make it public or remove the `#[no_mangle]`.
+
+## renamed-and-removed-lints
+
+This lint detects lints that have been renamed or removed. Some
+example code that triggers this lint:
+
+```rust
+#![deny(raw_pointer_derive)]
+```
+
+This will produce:
+
+```text
+warning: lint raw_pointer_derive has been removed: using derive with raw pointers is ok
+ --> src/main.rs:1:9
+  |
+1 | #![deny(raw_pointer_derive)]
+  |         ^^^^^^^^^^^^^^^^^^
+  |
+```
+
+To fix this, either remove the lint or use the new name.
+
+## safe-packed-borrows
+
+This lint detects borrowing a field in the interior of a packed structure
+with alignment other than 1. Some example code that triggers this lint:
+
+```rust
+#[repr(packed)]
+pub struct Unaligned<T>(pub T);
+
+pub struct Foo {
+    start: u8,
+    data: Unaligned<u32>,
+}
+
+fn main() {
+    let x = Foo { start: 0, data: Unaligned(1) };
+    let y = &x.data.0;
+}
+```
+
+This will produce:
+
+```text
+warning: borrow of packed field requires unsafe function or block (error E0133)
+  --> src/main.rs:11:13
+   |
+11 |     let y = &x.data.0; 
+   |             ^^^^^^^^^
+   |
+   = note: #[warn(safe_packed_borrows)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+```
+
+## stable-features
+
+This lint detects a `#[feature]` attribute that's since been made stable. Some
+example code that triggers this lint:
+
+```rust
+#![feature(test_accepted_feature)]
+```
+
+This will produce:
+
+```text
+warning: this feature has been stable since 1.0.0. Attribute no longer needed
+ --> src/main.rs:1:12
+  |
+1 | #![feature(test_accepted_feature)]
+  |            ^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+To fix, simply remove the `#![feature]` attribute, as it's no longer needed.
+
+## type-alias-bounds
+
+This lint detects bounds in type aliases. These are not currently enforced.
+Some example code that triggers this lint:
+
+```rust
+type SendVec<T: Send> = Vec<T>;
+```
+
+This will produce:
+
+```text
+warning: type alias is never used: `SendVec`
+ --> src/main.rs:1:1
+  |
+1 | type SendVec<T: Send> = Vec<T>;
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## tyvar-behind-raw-pointer
+
+This lint detects raw pointer to an inference variable. Some
+example code that triggers this lint:
+
+```rust
+let data = std::ptr::null();
+let _ = &data as *const *const ();
+
+if data.is_null() {}
+```
+
+This will produce:
+
+```text
+warning: type annotations needed
+ --> src/main.rs:4:13
+  |
+4 |     if data.is_null() {}
+  |             ^^^^^^^
+  |
+  = note: #[warn(tyvar_behind_raw_pointer)] on by default
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+  = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+```
+
+## unconditional-recursion
+
+This lint detects functions that cannot return without calling themselves.
+Some example code that triggers this lint:
+
+```rust
+fn foo() {
+    foo();
+}
+```
+
+This will produce:
+
+```text
+warning: function cannot return without recurring
+ --> src/main.rs:1:1
+  |
+1 | fn foo() {
+  | ^^^^^^^^ cannot return without recurring
+2 |     foo();
+  |     ----- recursive call site
+  |
+```
+
+## unions-with-drop-fields
+
+This lint detects use of unions that contain fields with possibly non-trivial drop code. Some
+example code that triggers this lint:
+
+```rust
+#![feature(untagged_unions)]
+
+union U {
+    s: String,
+}
+```
+
+This will produce:
+
+```text
+warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union
+ --> src/main.rs:4:5
+  |
+4 |     s: String,
+  |     ^^^^^^^^^
+  |
+```
+
+## unknown-lints
+
+This lint detects unrecognized lint attribute. Some
+example code that triggers this lint:
+
+```rust,ignore
+#[allow(not_a_real_lint)]
+```
+
+This will produce:
+
+```text
+warning: unknown lint: `not_a_real_lint`
+ --> src/main.rs:1:10
+  |
+1 | #![allow(not_a_real_lint)]
+  |          ^^^^^^^^^^^^^^^
+  |
+```
+
+## unreachable-code
+
+This lint detects detects unreachable code paths. Some example code that
+triggers this lint:
+
+```rust,no_run
+panic!("we never go past here!");
+
+let x = 5;
+```
+
+This will produce:
+
+```text
+warning: unreachable statement
+ --> src/main.rs:4:5
+  |
+4 |     let x = 5;
+  |     ^^^^^^^^^^
+  |
+```
+
+## unreachable-patterns
+
+This lint detects detects unreachable patterns. Some
+example code that triggers this lint:
+
+```rust
+let x = 5;
+match x {
+    y => (),
+    5 => (),
+}
+```
+
+This will produce:
+
+```text
+warning: unreachable pattern
+ --> src/main.rs:5:5
+  |
+5 |     5 => (),
+  |     ^
+  |
+```
+
+The `y` pattern will always match, so the five is impossible to reach.
+Remember, match arms match in order, you probably wanted to put the `5` case
+above the `y` case.
+
+## unstable-name-collision
+
+This lint detects that you've used a name that the standard library plans to
+add in the future, which means that your code may fail to compile without
+additional type annotations in the future. Either rename, or add those
+annotations now.
+
+## unused-allocation
+
+This lint detects detects unnecessary allocations that can be eliminated.
+
+## unused-assignments
+
+This lint detects detect assignments that will never be read. Some
+example code that triggers this lint:
+
+```rust
+let mut x = 5;
+x = 6;
+```
+
+This will produce:
+
+```text
+warning: value assigned to `x` is never read
+ --> src/main.rs:4:5
+  |
+4 |     x = 6;
+  |     ^
+  |
+```
+
+## unused-attributes
+
+This lint detects detects attributes that were not used by the compiler. Some
+example code that triggers this lint:
+
+```rust
+#![feature(custom_attribute)]
+
+#![mutable_doc]
+```
+
+This will produce:
+
+```text
+warning: unused attribute
+ --> src/main.rs:4:1
+  |
+4 | #![mutable_doc]
+  | ^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-comparisons
+
+This lint detects comparisons made useless by limits of the types involved. Some
+example code that triggers this lint:
+
+```rust
+fn foo(x: u8) {
+    x >= 0;
+}
+```
+
+This will produce:
+
+```text
+warning: comparison is useless due to type limits
+ --> src/main.rs:6:5
+  |
+6 |     x >= 0;
+  |     ^^^^^^
+  |
+```
+
+## unused-doc-comment
+
+This lint detects detects doc comments that aren't used by rustdoc. Some
+example code that triggers this lint:
+
+```rust
+/// docs for x
+let x = 12;
+```
+
+This will produce:
+
+```text
+warning: doc comment not used by rustdoc
+ --> src/main.rs:2:5
+  |
+2 |     /// docs for x
+  |     ^^^^^^^^^^^^^^
+  |
+```
+
+## unused-features
+
+This lint detects unused or unknown features found in crate-level #[feature] directives.
+To fix this, simply remove the feature flag.
+
+## unused-imports
+
+This lint detects imports that are never used. Some
+example code that triggers this lint:
+
+```rust
+use std::collections::HashMap;
+```
+
+This will produce:
+
+```text
+warning: unused import: `std::collections::HashMap`
+ --> src/main.rs:1:5
+  |
+1 | use std::collections::HashMap;
+  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-macros
+
+This lint detects detects macros that were not used. Some example code that
+triggers this lint:
+
+```rust
+macro_rules! unused {
+    () => {};
+}
+
+fn main() {
+}
+```
+
+This will produce:
+
+```text
+warning: unused macro definition
+ --> src/main.rs:1:1
+  |
+1 | / macro_rules! unused {
+2 | |     () => {};
+3 | | }
+  | |_^
+  |
+```
+
+## unused-must-use
+
+This lint detects unused result of a type flagged as #[must_use]. Some
+example code that triggers this lint:
+
+```rust
+fn returns_result() -> Result<(), ()> {
+    Ok(())
+}
+
+fn main() {
+    returns_result();
+}
+```
+
+This will produce:
+
+```text
+warning: unused `std::result::Result` which must be used
+ --> src/main.rs:6:5
+  |
+6 |     returns_result();
+  |     ^^^^^^^^^^^^^^^^^
+  |
+```
+
+## unused-mut
+
+This lint detects detect mut variables which don't need to be mutable. Some
+example code that triggers this lint:
+
+```rust
+let mut x = 5;
+```
+
+This will produce:
+
+```text
+warning: variable does not need to be mutable
+ --> src/main.rs:2:9
+  |
+2 |     let mut x = 5;
+  |         ----^
+  |         |
+  |         help: remove this `mut`
+  |
+```
+
+## unused-parens
+
+This lint detects `if`, `match`, `while` and `return` with parentheses; they
+do not need them. Some example code that triggers this lint:
+
+```rust
+if(true) {}
+```
+
+This will produce:
+
+```text
+warning: unnecessary parentheses around `if` condition
+ --> src/main.rs:2:7
+  |
+2 |     if(true) {}
+  |       ^^^^^^ help: remove these parentheses
+  |
+```
+
+## unused-unsafe
+
+This lint detects unnecessary use of an `unsafe` block. Some
+example code that triggers this lint:
+
+```rust
+unsafe {}
+```
+
+This will produce:
+
+```text
+warning: unnecessary `unsafe` block
+ --> src/main.rs:2:5
+  |
+2 |     unsafe {}
+  |     ^^^^^^ unnecessary `unsafe` block
+  |
+```
+
+## unused-variables
+
+This lint detects detect variables which are not used in any way. Some
+example code that triggers this lint:
+
+```rust
+let x = 5;
+```
+
+This will produce:
+
+```text
+warning: unused variable: `x`
+ --> src/main.rs:2:9
+  |
+2 |     let x = 5;
+  |         ^ help: consider using `_x` instead
+  |
+```
+
+## warnings
+
+This lint is a bit special; by changing its level, you change every other warning
+that would produce a warning to whatever value you'd like:
+
+```rust
+#![deny(warnings)]
+```
+
+As such, you won't ever trigger this lint in your code directly.
+
+## while-true
+
+This lint detects `while true { }`. Some example code that triggers this
+lint:
+
+```rust,no_run
+while true {
+
+}
+```
+
+This will produce:
+
+```text
+warning: denote infinite loops with `loop { ... }`
+ --> src/main.rs:2:5
+  |
+2 |     while true {
+  |     ^^^^^^^^^^ help: use `loop`
+  |
+```
diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md
new file mode 100644
index 00000000000..8620346e5b7
--- /dev/null
+++ b/src/doc/rustc/src/targets/built-in.md
@@ -0,0 +1,10 @@
+# Built-in Targets
+
+`rustc` ships with the ability to compile to many targets automatically, we
+call these "built-in" targets, and they generally correspond to targets that
+the team is supporting directly.
+
+To see the list of built-in targets, you can run `rustc --print target-list`,
+or look at [the API
+docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/#modules).
+Each module there defines a builder for a particular target.
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md
new file mode 100644
index 00000000000..0691afc60ea
--- /dev/null
+++ b/src/doc/rustc/src/targets/custom.md
@@ -0,0 +1,17 @@
+# Custom Targets
+
+If you'd like to build for a target that is not yet supported by `rustc`, you can use a
+"custom target specification" to define a target. These target specification files
+are JSON. To see the JSON for the host target, you can run:
+
+```bash
+$ rustc +nightly -Z unstable-options --print target-spec-json
+```
+
+To see it for a different target, add the `--target` flag:
+
+```bash
+$ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json
+```
+
+To use a custom target, see [`xargo`](https://github.com/japaric/xargo).
\ No newline at end of file
diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md
new file mode 100644
index 00000000000..07e3a79471f
--- /dev/null
+++ b/src/doc/rustc/src/targets/index.md
@@ -0,0 +1,13 @@
+# Targets
+
+`rustc` is a cross-compiler by default. This means that you can use any compiler to build for any
+architecture. The list of *targets* are the possible architectures that you can build for.
+
+To see all the options that you can set with a target, see the docs
+[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html).
+
+To compile to a particular target, use the `--target` flag:
+
+```bash
+$ rustc src/main.rs --target=wasm32-unknown-unknown
+```
diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md
new file mode 100644
index 00000000000..bed1b71c24e
--- /dev/null
+++ b/src/doc/rustc/src/what-is-rustc.md
@@ -0,0 +1,68 @@
+# What is rustc?
+
+Welcome to "The rustc book"! `rustc` is the compiler for the Rust programming
+language, provided by the project itself. Compilers take your source code and
+produce binary code, either as a library or executable.
+
+Most Rust programmers don't invoke `rustc` directly, but instead do it through
+[Cargo](../cargo/index.html). It's all in service of `rustc` though! If you
+want to see how Cargo calls `rustc`, you can
+
+```bash
+$ cargo build --verbose
+```
+
+And it will print out each `rustc` invocation. This book can help you
+understand what each of these options does. Additionally, while most
+Rustaceans use Cargo, not all do: sometimes they integrate `rustc` into other
+build systems. This book should provide a guide to all of the options you'd
+need to do so.
+
+## Basic usage
+
+Let's say you've got a little hello world program in a file `hello.rs`:
+
+```rust
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+To turn this source code into an executable, you can use `rustc`:
+
+```bash
+$ rustc hello.rs
+$ ./hello # on a *NIX
+$ .\hello.exe # on Windows
+```
+
+Note that we only ever pass `rustc` the *crate root*, not every file we wish
+to compile. For example, if we had a `main.rs` that looked like this:
+
+```rust,ignore
+mod foo;
+
+fn main() {
+    foo::hello();
+}
+```
+
+And a `foo.rs` that had this:
+
+```rust,ignore
+fn hello() {
+    println!("Hello, world!");
+}
+```
+
+To compile this, we'd run this command:
+
+```bash
+$ rustc main.rs
+```
+
+No need to tell `rustc` about `foo.rs`; the `mod` statements give it
+everything that it needs. This is different than how you would use a C
+compiler, where you invoke the compiler on each file, and then link
+everything together. In other words, the *crate* is a translation unit, not a
+particular module.
\ No newline at end of file
diff --git a/src/doc/unstable-book/src/language-features/fn-must-use.md b/src/doc/unstable-book/src/language-features/fn-must-use.md
deleted file mode 100644
index 71b6cd663a0..00000000000
--- a/src/doc/unstable-book/src/language-features/fn-must-use.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# `fn_must_use`
-
-The tracking issue for this feature is [#43302].
-
-[#43302]: https://github.com/rust-lang/rust/issues/43302
-
-------------------------
-
-The `fn_must_use` feature allows functions and methods to be annotated with
-`#[must_use]`, indicating that the `unused_must_use` lint should require their
-return values to be used (similarly to how types annotated with `must_use`,
-most notably `Result`, are linted if not used).
-
-## Examples
-
-```rust
-#![feature(fn_must_use)]
-
-#[must_use]
-fn double(x: i32) -> i32 {
-    2 * x
-}
-
-fn main() {
-    double(4); // warning: unused return value of `double` which must be used
-
-    let _ = double(4); // (no warning)
-}
-
-```
diff --git a/src/doc/unstable-book/src/language-features/tool-attributes.md b/src/doc/unstable-book/src/language-features/tool-attributes.md
new file mode 100644
index 00000000000..15fc84a3e2a
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/tool-attributes.md
@@ -0,0 +1,26 @@
+# `tool_attributes`
+
+The tracking issue for this feature is: [#44690]
+
+[#44690]: https://github.com/rust-lang/rust/issues/44690
+
+------------------------
+
+Tool attributes let you use scoped attributes to control the behavior
+of certain tools.
+
+Currently tool names which can be appear in scoped attributes are restricted to
+`clippy` and `rustfmt`.
+
+## An example
+
+```rust
+#![feature(tool_attributes)]
+
+#[rustfmt::skip]
+fn foo() { println!("hello, world"); }
+
+fn main() {
+    foo();
+}
+```
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index c0372d24ed5..f59c9f7fd61 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -16,7 +16,7 @@
             issue = "32838")]
 
 use core::intrinsics::{min_align_of_val, size_of_val};
-use core::ptr::NonNull;
+use core::ptr::{NonNull, Unique};
 use core::usize;
 
 #[doc(inline)]
@@ -152,9 +152,17 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
     }
 }
 
-#[cfg_attr(not(test), lang = "box_free")]
+#[cfg(stage0)]
+#[lang = "box_free"]
+#[inline]
+unsafe fn old_box_free<T: ?Sized>(ptr: *mut T) {
+    box_free(Unique::new_unchecked(ptr))
+}
+
+#[cfg_attr(not(any(test, stage0)), lang = "box_free")]
 #[inline]
-pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
+    let ptr = ptr.as_ptr();
     let size = size_of_val(&*ptr);
     let align = min_align_of_val(&*ptr);
     // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index e52a0216dd3..d0950bff9ce 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -566,7 +566,8 @@ impl<T: ?Sized> Arc<T> {
 
     fn from_box(v: Box<T>) -> Arc<T> {
         unsafe {
-            let bptr = Box::into_raw(v);
+            let box_unique = Box::into_unique(v);
+            let bptr = box_unique.as_ptr();
 
             let value_size = size_of_val(&*bptr);
             let ptr = Self::allocate_for_ptr(bptr);
@@ -578,7 +579,7 @@ impl<T: ?Sized> Arc<T> {
                 value_size);
 
             // Free the allocation without dropping its contents
-            box_free(bptr);
+            box_free(box_unique);
 
             Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 5ebd2cc6146..1b4f86dcfac 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -184,6 +184,7 @@ impl<T: ?Sized> Box<T> {
 
     #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
     #[inline]
+    #[doc(hidden)]
     pub fn into_unique(b: Box<T>) -> Unique<T> {
         let unique = b.0;
         mem::forget(b);
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 021395d0c82..da4b76a4d52 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -96,7 +96,7 @@
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
 #![feature(fmt_internals)]
-#![feature(fn_must_use)]
+#![cfg_attr(stage0, feature(fn_must_use))]
 #![feature(from_ref)]
 #![feature(fundamental)]
 #![feature(lang_items)]
@@ -122,8 +122,9 @@
 #![feature(on_unimplemented)]
 #![feature(exact_chunks)]
 #![feature(pointer_methods)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 #![cfg_attr(stage0, feature(generic_param_attrs))]
+#![feature(rustc_const_unstable)]
 
 #![cfg_attr(not(test), feature(fn_traits, i128))]
 #![cfg_attr(test, feature(test))]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 7ef0a27fc72..eb25ae17511 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -56,14 +56,16 @@ pub struct RawVec<T, A: Alloc = Global> {
 impl<T, A: Alloc> RawVec<T, A> {
     /// Like `new` but parameterized over the choice of allocator for
     /// the returned RawVec.
-    pub fn new_in(a: A) -> Self {
+    pub const fn new_in(a: A) -> Self {
         // !0 is usize::MAX. This branch should be stripped at compile time.
-        let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+        // FIXME(mark-i-m): use this line when `if`s are allowed in `const`
+        //let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
 
         // Unique::empty() doubles as "unallocated" and "zero-sized allocation"
         RawVec {
             ptr: Unique::empty(),
-            cap,
+            // FIXME(mark-i-m): use `cap` when ifs are allowed in const
+            cap: [0, !0][(mem::size_of::<T>() == 0) as usize],
             a,
         }
     }
@@ -120,7 +122,7 @@ impl<T> RawVec<T, Global> {
     /// RawVec with capacity 0. If T has 0 size, then it makes a
     /// RawVec with capacity `usize::MAX`. Useful for implementing
     /// delayed allocation.
-    pub fn new() -> Self {
+    pub const fn new() -> Self {
         Self::new_in(Global)
     }
 
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 8fb8e111754..d0188c6e828 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -681,7 +681,8 @@ impl<T: ?Sized> Rc<T> {
 
     fn from_box(v: Box<T>) -> Rc<T> {
         unsafe {
-            let bptr = Box::into_raw(v);
+            let box_unique = Box::into_unique(v);
+            let bptr = box_unique.as_ptr();
 
             let value_size = size_of_val(&*bptr);
             let ptr = Self::allocate_for_ptr(bptr);
@@ -693,7 +694,7 @@ impl<T: ?Sized> Rc<T> {
                 value_size);
 
             // Free the allocation without dropping its contents
-            box_free(bptr);
+            box_free(box_unique);
 
             Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 32272169307..1c8ff316e55 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -25,7 +25,7 @@
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(exact_chunks)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 
 extern crate alloc_system;
 extern crate core;
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index 99d9c51efc7..6fd0b33f02a 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -1282,6 +1282,7 @@ fn test_box_slice_clone() {
 }
 
 #[test]
+#[allow(unused_must_use)] // here, we care about the side effects of `.clone()`
 #[cfg_attr(target_os = "emscripten", ignore)]
 fn test_box_slice_clone_panics() {
     use std::sync::Arc;
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index b184404c15b..35d0a69a05a 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -322,7 +322,8 @@ impl<T> Vec<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> Vec<T> {
+    #[rustc_const_unstable(feature = "const_vec_new")]
+    pub const fn new() -> Vec<T> {
         Vec {
             buf: RawVec::new(),
             len: 0,
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index c91aa06609d..13e838773a5 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -106,6 +106,8 @@ use self::Ordering::*;
 /// ```
 #[lang = "eq"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
@@ -160,6 +162,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
 /// }
 /// impl Eq for Book {}
 /// ```
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Eq: PartialEq<Self> {
     // this method is used solely by #[deriving] to assert
@@ -428,6 +432,10 @@ impl<T: Ord> Ord for Reverse<T> {
 /// }
 /// ```
 #[lang = "ord"]
+#[doc(alias = "<")]
+#[doc(alias = ">")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an `Ordering` between `self` and `other`.
@@ -599,6 +607,10 @@ impl PartialOrd for Ordering {
 /// ```
 #[lang = "partial_ord"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = ">")]
+#[doc(alias = "<")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values if one exists.
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index a8430f14410..5820fe58932 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -542,11 +542,12 @@ impl<'a> Display for Arguments<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
-    on(crate_local, label="`{Self}` cannot be formatted using `:?`; \
-                            add `#[derive(Debug)]` or manually implement `{Debug}`"),
+    on(crate_local, label="`{Self}` cannot be formatted using `{{:?}}`",
+                    note="add `#[derive(Debug)]` or manually implement `{Debug}`"),
     message="`{Self}` doesn't implement `{Debug}`",
-    label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`",
+    label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`",
 )]
+#[doc(alias = "{:?}")]
 #[lang = "debug_trait"]
 pub trait Debug {
     /// Formats the value using the given formatter.
@@ -609,9 +610,11 @@ pub trait Debug {
 /// ```
 #[rustc_on_unimplemented(
     message="`{Self}` doesn't implement `{Display}`",
-    label="`{Self}` cannot be formatted with the default formatter; \
-           try using `:?` instead if you are using a format string",
+    label="`{Self}` cannot be formatted with the default formatter",
+    note="in format strings you may be able to use `{{:?}}` \
+          (or {{:#?}} for pretty-print) instead",
 )]
+#[doc(alias = "{}")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Display {
     /// Formats the value using the given formatter.
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 6a77de2c986..b27bd3142e1 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -1094,6 +1094,8 @@ pub trait Iterator {
     /// `flatten()` a three-dimensional array the result will be
     /// two-dimensional and not one-dimensional. To get a one-dimensional
     /// structure, you have to `flatten()` again.
+    ///
+    /// [`flat_map()`]: #method.flat_map
     #[inline]
     #[unstable(feature = "iterator_flatten", issue = "48213")]
     fn flatten(self) -> Flatten<Self>
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 0e21a3327fd..54f35d17974 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -50,6 +50,15 @@
 
 // Since libcore defines many fundamental lang items, all tests live in a
 // separate crate, libcoretest, to avoid bizarre issues.
+//
+// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
+// this, both the generated test artifact and the linked libtest (which
+// transitively includes libcore) will both define the same set of lang items,
+// and this will cause the E0152 "duplicate lang item found" error. See
+// discussion in #50466 for details.
+//
+// This cfg won't affect doc tests.
+#![cfg(not(test))]
 
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -76,7 +85,6 @@
 #![feature(doc_cfg)]
 #![feature(doc_spotlight)]
 #![feature(extern_types)]
-#![feature(fn_must_use)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
 #![feature(iterator_flatten)]
@@ -103,6 +111,7 @@
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(doc_alias)]
+#![feature(inclusive_range_methods)]
 
 #![cfg_attr(not(stage0), feature(mmx_target_feature))]
 #![cfg_attr(not(stage0), feature(tbm_target_feature))]
@@ -114,6 +123,7 @@
 
 #![cfg_attr(stage0, feature(target_feature))]
 #![cfg_attr(stage0, feature(cfg_target_feature))]
+#![cfg_attr(stage0, feature(fn_must_use))]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index f9371ed0575..c830c22ee5f 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -606,8 +606,8 @@ mod builtin {
     #[macro_export]
     #[cfg(dox)]
     macro_rules! concat_idents {
-        ($($e:ident),*) => ({ /* compiler built-in */ });
-        ($($e:ident,)*) => ({ /* compiler built-in */ });
+        ($($e:ident),+) => ({ /* compiler built-in */ });
+        ($($e:ident,)+) => ({ /* compiler built-in */ });
     }
 
     /// Concatenates literals into a static string slice.
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index feb689dbc1f..c074adfd570 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -602,6 +602,8 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 /// `Pin` pointer.
 ///
 /// This trait is automatically implemented for almost every type.
+///
+/// [`Pin`]: ../mem/struct.Pin.html
 #[unstable(feature = "pin", issue = "49150")]
 pub unsafe auto trait Unpin {}
 
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index a1f6030428f..a1bc5463f73 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -94,6 +94,7 @@ pub trait Add<RHS=Self> {
     type Output;
 
     /// Performs the `+` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn add(self, rhs: RHS) -> Self::Output;
 }
@@ -191,6 +192,7 @@ pub trait Sub<RHS=Self> {
     type Output;
 
     /// Performs the `-` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn sub(self, rhs: RHS) -> Self::Output;
 }
@@ -310,6 +312,7 @@ pub trait Mul<RHS=Self> {
     type Output;
 
     /// Performs the `*` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn mul(self, rhs: RHS) -> Self::Output;
 }
@@ -433,6 +436,7 @@ pub trait Div<RHS=Self> {
     type Output;
 
     /// Performs the `/` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn div(self, rhs: RHS) -> Self::Output;
 }
@@ -517,6 +521,7 @@ pub trait Rem<RHS=Self> {
     type Output = Self;
 
     /// Performs the `%` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn rem(self, rhs: RHS) -> Self::Output;
 }
@@ -601,6 +606,7 @@ pub trait Neg {
     type Output;
 
     /// Performs the unary `-` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn neg(self) -> Self::Output;
 }
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
index 81c4455cef4..3900f365b0a 100644
--- a/src/libcore/ops/bit.rs
+++ b/src/libcore/ops/bit.rs
@@ -46,6 +46,7 @@ pub trait Not {
     type Output;
 
     /// Performs the unary `!` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn not(self) -> Self::Output;
 }
@@ -119,6 +120,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 & bv2, expected);
 /// ```
 #[lang = "bitand"]
+#[doc(alias = "&")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
                          label="no implementation for `{Self} & {RHS}`")]
@@ -128,6 +130,7 @@ pub trait BitAnd<RHS=Self> {
     type Output;
 
     /// Performs the `&` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitand(self, rhs: RHS) -> Self::Output;
 }
@@ -201,6 +204,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 | bv2, expected);
 /// ```
 #[lang = "bitor"]
+#[doc(alias = "|")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
                          label="no implementation for `{Self} | {RHS}`")]
@@ -210,6 +214,7 @@ pub trait BitOr<RHS=Self> {
     type Output;
 
     /// Performs the `|` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitor(self, rhs: RHS) -> Self::Output;
 }
@@ -286,6 +291,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(bv1 ^ bv2, expected);
 /// ```
 #[lang = "bitxor"]
+#[doc(alias = "^")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
                          label="no implementation for `{Self} ^ {RHS}`")]
@@ -295,6 +301,7 @@ pub trait BitXor<RHS=Self> {
     type Output;
 
     /// Performs the `^` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn bitxor(self, rhs: RHS) -> Self::Output;
 }
@@ -372,6 +379,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 ///            SpinVector { vec: vec![2, 3, 4, 0, 1] });
 /// ```
 #[lang = "shl"]
+#[doc(alias = "<<")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
                          label="no implementation for `{Self} << {RHS}`")]
@@ -381,6 +389,7 @@ pub trait Shl<RHS=Self> {
     type Output;
 
     /// Performs the `<<` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn shl(self, rhs: RHS) -> Self::Output;
 }
@@ -479,6 +488,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 ///            SpinVector { vec: vec![3, 4, 0, 1, 2] });
 /// ```
 #[lang = "shr"]
+#[doc(alias = ">>")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
                          label="no implementation for `{Self} >> {RHS}`")]
@@ -488,6 +498,7 @@ pub trait Shr<RHS=Self> {
     type Output;
 
     /// Performs the `>>` operation.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn shr(self, rhs: RHS) -> Self::Output;
 }
@@ -593,6 +604,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// assert_eq!(bv, expected);
 /// ```
 #[lang = "bitand_assign"]
+#[doc(alias = "&=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
                          label="no implementation for `{Self} &= {Rhs}`")]
@@ -641,6 +653,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
 /// ```
 #[lang = "bitor_assign"]
+#[doc(alias = "|=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
                          label="no implementation for `{Self} |= {Rhs}`")]
@@ -689,6 +702,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
 /// ```
 #[lang = "bitxor_assign"]
+#[doc(alias = "^=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
                          label="no implementation for `{Self} ^= {Rhs}`")]
@@ -735,6 +749,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 /// assert_eq!(scalar, Scalar(16));
 /// ```
 #[lang = "shl_assign"]
+#[doc(alias = "<<=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
                          label="no implementation for `{Self} <<= {Rhs}`")]
@@ -802,6 +817,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 /// assert_eq!(scalar, Scalar(4));
 /// ```
 #[lang = "shr_assign"]
+#[doc(alias = ">>=")]
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
                          label="no implementation for `{Self} >>= {Rhs}`")]
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index 4ce0740130b..54eecc82e19 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -68,6 +68,8 @@
 /// assert_eq!('a', *x);
 /// ```
 #[lang = "deref"]
+#[doc(alias = "*")]
+#[doc(alias = "&*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
     /// The resulting type after dereferencing.
@@ -75,6 +77,7 @@ pub trait Deref {
     type Target: ?Sized;
 
     /// Dereferences the value.
+    #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn deref(&self) -> &Self::Target;
 }
@@ -162,6 +165,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
 /// assert_eq!('b', *x);
 /// ```
 #[lang = "deref_mut"]
+#[doc(alias = "*")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait DerefMut: Deref {
     /// Mutably dereferences the value.
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 6f3e3b50885..b01a769eda7 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -45,6 +45,7 @@ use fmt;
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFull;
@@ -74,6 +75,7 @@ impl fmt::Debug for RangeFull {
 /// assert_eq!(arr[1.. ], [     'b', 'c', 'd']);
 /// assert_eq!(arr[1..3], [     'b', 'c'     ]);  // Range
 /// ```
+#[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
@@ -175,6 +177,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
 /// ```
 ///
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
+#[doc(alias = "..")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
@@ -256,6 +259,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeTo<Idx> {
@@ -314,26 +318,101 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// # Examples
 ///
 /// ```
-/// #![feature(inclusive_range_fields)]
+/// #![feature(inclusive_range_methods)]
 ///
-/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
+/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
 /// assert_eq!(3 + 4 + 5, (3..=5).sum());
 ///
 /// let arr = [0, 1, 2, 3];
 /// assert_eq!(arr[ ..=2], [0,1,2  ]);
 /// assert_eq!(arr[1..=2], [  1,2  ]);  // RangeInclusive
 /// ```
+#[doc(alias = "..=")]
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeInclusive<Idx> {
+    // FIXME: The current representation follows RFC 1980,
+    // but it is known that LLVM is not able to optimize loops following that RFC.
+    // Consider adding an extra `bool` field to indicate emptiness of the range.
+    // See #45222 for performance test cases.
+    #[cfg(not(stage0))]
+    pub(crate) start: Idx,
+    #[cfg(not(stage0))]
+    pub(crate) end: Idx,
     /// The lower bound of the range (inclusive).
+    #[cfg(stage0)]
     #[unstable(feature = "inclusive_range_fields", issue = "49022")]
     pub start: Idx,
     /// The upper bound of the range (inclusive).
+    #[cfg(stage0)]
     #[unstable(feature = "inclusive_range_fields", issue = "49022")]
     pub end: Idx,
 }
 
+impl<Idx> RangeInclusive<Idx> {
+    /// Creates a new inclusive range. Equivalent to writing `start..=end`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inclusive_range_methods)]
+    /// use std::ops::RangeInclusive;
+    ///
+    /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
+    /// ```
+    #[unstable(feature = "inclusive_range_methods", issue = "49022")]
+    #[inline]
+    pub const fn new(start: Idx, end: Idx) -> Self {
+        Self { start, end }
+    }
+
+    /// Returns the lower bound of the range (inclusive).
+    ///
+    /// When using an inclusive range for iteration, the values of `start()` and
+    /// [`end()`] are unspecified after the iteration ended. To determine
+    /// whether the inclusive range is empty, use the [`is_empty()`] method
+    /// instead of comparing `start() > end()`.
+    ///
+    /// [`end()`]: #method.end
+    /// [`is_empty()`]: #method.is_empty
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inclusive_range_methods)]
+    ///
+    /// assert_eq!((3..=5).start(), &3);
+    /// ```
+    #[unstable(feature = "inclusive_range_methods", issue = "49022")]
+    #[inline]
+    pub fn start(&self) -> &Idx {
+        &self.start
+    }
+
+    /// Returns the upper bound of the range (inclusive).
+    ///
+    /// When using an inclusive range for iteration, the values of [`start()`]
+    /// and `end()` are unspecified after the iteration ended. To determine
+    /// whether the inclusive range is empty, use the [`is_empty()`] method
+    /// instead of comparing `start() > end()`.
+    ///
+    /// [`start()`]: #method.start
+    /// [`is_empty()`]: #method.is_empty
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(inclusive_range_methods)]
+    ///
+    /// assert_eq!((3..=5).end(), &5);
+    /// ```
+    #[unstable(feature = "inclusive_range_methods", issue = "49022")]
+    #[inline]
+    pub fn end(&self) -> &Idx {
+        &self.end
+    }
+}
+
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
@@ -449,6 +528,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
+#[doc(alias = "..=")]
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "inclusive_range", since = "1.26.0")]
 pub struct RangeToInclusive<Idx> {
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 74bb264cc67..5d0b675e8e4 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2513,6 +2513,7 @@ impl<T: ?Sized> PartialOrd for *mut T {
            reason = "use NonNull instead and consider PhantomData<T> \
                      (if you also use #[may_dangle]), Send, and/or Sync")]
 #[allow(deprecated)]
+#[doc(hidden)]
 pub struct Unique<T: ?Sized> {
     pointer: NonZero<*const T>,
     // NOTE: this marker has no consequences for variance, but is necessary
@@ -2551,10 +2552,9 @@ impl<T: Sized> Unique<T> {
     /// This is useful for initializing types which lazily allocate, like
     /// `Vec::new` does.
     // FIXME: rename to dangling() to match NonNull?
-    pub fn empty() -> Self {
+    pub const fn empty() -> Self {
         unsafe {
-            let ptr = mem::align_of::<T>() as *mut T;
-            Unique::new_unchecked(ptr)
+            Unique::new_unchecked(mem::align_of::<T>() as *mut T)
         }
     }
 }
diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs
index 69c9cb37dcf..7b62e7b0620 100644
--- a/src/libcore/slice/memchr.rs
+++ b/src/libcore/slice/memchr.rs
@@ -39,21 +39,10 @@ fn repeat_byte(b: u8) -> usize {
     (b as usize) << 8 | b as usize
 }
 
-#[cfg(target_pointer_width = "32")]
+#[cfg(not(target_pointer_width = "16"))]
 #[inline]
 fn repeat_byte(b: u8) -> usize {
-    let mut rep = (b as usize) << 8 | b as usize;
-    rep = rep << 16 | rep;
-    rep
-}
-
-#[cfg(target_pointer_width = "64")]
-#[inline]
-fn repeat_byte(b: u8) -> usize {
-    let mut rep = (b as usize) << 8 | b as usize;
-    rep = rep << 16 | rep;
-    rep = rep << 32 | rep;
-    rep
+    (b as usize) * (::usize::MAX / 255)
 }
 
 /// Return the first index matching the byte `x` in `text`.
@@ -146,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     // find the byte before the point the body loop stopped
     text[..offset].iter().rposition(|elt| *elt == x)
 }
-
-// test fallback implementations on all platforms
-#[test]
-fn matches_one() {
-    assert_eq!(Some(0), memchr(b'a', b"a"));
-}
-
-#[test]
-fn matches_begin() {
-    assert_eq!(Some(0), memchr(b'a', b"aaaa"));
-}
-
-#[test]
-fn matches_end() {
-    assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
-}
-
-#[test]
-fn matches_nul() {
-    assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
-}
-
-#[test]
-fn matches_past_nul() {
-    assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
-}
-
-#[test]
-fn no_match_empty() {
-    assert_eq!(None, memchr(b'a', b""));
-}
-
-#[test]
-fn no_match() {
-    assert_eq!(None, memchr(b'a', b"xyz"));
-}
-
-#[test]
-fn matches_one_reversed() {
-    assert_eq!(Some(0), memrchr(b'a', b"a"));
-}
-
-#[test]
-fn matches_begin_reversed() {
-    assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
-}
-
-#[test]
-fn matches_end_reversed() {
-    assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
-}
-
-#[test]
-fn matches_nul_reversed() {
-    assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
-}
-
-#[test]
-fn matches_past_nul_reversed() {
-    assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
-}
-
-#[test]
-fn no_match_empty_reversed() {
-    assert_eq!(None, memrchr(b'a', b""));
-}
-
-#[test]
-fn no_match_reversed() {
-    assert_eq!(None, memrchr(b'a', b"xyz"));
-}
-
-#[test]
-fn each_alignment_reversed() {
-    let mut data = [1u8; 64];
-    let needle = 2;
-    let pos = 40;
-    data[pos] = needle;
-    for start in 0..16 {
-        assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
-    }
-}
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index cc42acd77ae..83e8a6e4b68 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -880,7 +880,6 @@ macro_rules! slice_core_methods { () => {
     #[inline]
     pub fn split_last(&self) -> Option<(&T, &[T])> {
         SliceExt::split_last(self)
-
     }
 
     /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 111cf58c2c6..28dac02654b 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -44,9 +44,10 @@
 #![feature(exact_chunks)]
 #![cfg_attr(stage0, feature(atomic_nand))]
 #![feature(reverse_bits)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 #![feature(iterator_find_map)]
 #![feature(inner_deref)]
+#![feature(slice_internals)]
 
 extern crate core;
 extern crate test;
@@ -75,4 +76,5 @@ mod result;
 mod slice;
 mod str;
 mod str_lossy;
+mod time;
 mod tuple;
diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs
index ca6906f7310..257f6ea20d4 100644
--- a/src/libcore/tests/num/uint_macros.rs
+++ b/src/libcore/tests/num/uint_macros.rs
@@ -98,6 +98,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg(not(stage0))]
     fn test_reverse_bits() {
         assert_eq!(A.reverse_bits().reverse_bits(), A);
         assert_eq!(B.reverse_bits().reverse_bits(), B);
diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs
index bed08f86d72..d66193b1687 100644
--- a/src/libcore/tests/ops.rs
+++ b/src/libcore/tests/ops.rs
@@ -50,21 +50,21 @@ fn test_full_range() {
 
 #[test]
 fn test_range_inclusive() {
-    let mut r = RangeInclusive { start: 1i8, end: 2 };
+    let mut r = RangeInclusive::new(1i8, 2);
     assert_eq!(r.next(), Some(1));
     assert_eq!(r.next(), Some(2));
     assert_eq!(r.next(), None);
 
-    r = RangeInclusive { start: 127i8, end: 127 };
+    r = RangeInclusive::new(127i8, 127);
     assert_eq!(r.next(), Some(127));
     assert_eq!(r.next(), None);
 
-    r = RangeInclusive { start: -128i8, end: -128 };
+    r = RangeInclusive::new(-128i8, -128);
     assert_eq!(r.next_back(), Some(-128));
     assert_eq!(r.next_back(), None);
 
     // degenerate
-    r = RangeInclusive { start: 1, end: -1 };
+    r = RangeInclusive::new(1, -1);
     assert_eq!(r.size_hint(), (0, Some(0)));
     assert_eq!(r.next(), None);
 }
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 53fdfa06827..c81e5e97cbb 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -550,3 +550,89 @@ fn sort_unstable() {
     v.sort_unstable();
     assert!(v == [0xDEADBEEF]);
 }
+
+pub mod memchr {
+    use core::slice::memchr::{memchr, memrchr};
+
+    // test fallback implementations on all platforms
+    #[test]
+    fn matches_one() {
+        assert_eq!(Some(0), memchr(b'a', b"a"));
+    }
+
+    #[test]
+    fn matches_begin() {
+        assert_eq!(Some(0), memchr(b'a', b"aaaa"));
+    }
+
+    #[test]
+    fn matches_end() {
+        assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
+    }
+
+    #[test]
+    fn matches_nul() {
+        assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn matches_past_nul() {
+        assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
+    }
+
+    #[test]
+    fn no_match_empty() {
+        assert_eq!(None, memchr(b'a', b""));
+    }
+
+    #[test]
+    fn no_match() {
+        assert_eq!(None, memchr(b'a', b"xyz"));
+    }
+
+    #[test]
+    fn matches_one_reversed() {
+        assert_eq!(Some(0), memrchr(b'a', b"a"));
+    }
+
+    #[test]
+    fn matches_begin_reversed() {
+        assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
+    }
+
+    #[test]
+    fn matches_end_reversed() {
+        assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
+    }
+
+    #[test]
+    fn matches_nul_reversed() {
+        assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn matches_past_nul_reversed() {
+        assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
+    }
+
+    #[test]
+    fn no_match_empty_reversed() {
+        assert_eq!(None, memrchr(b'a', b""));
+    }
+
+    #[test]
+    fn no_match_reversed() {
+        assert_eq!(None, memrchr(b'a', b"xyz"));
+    }
+
+    #[test]
+    fn each_alignment_reversed() {
+        let mut data = [1u8; 64];
+        let needle = 2;
+        let pos = 40;
+        data[pos] = needle;
+        for start in 0..16 {
+            assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
+        }
+    }
+}
diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs
new file mode 100644
index 00000000000..042c523f25f
--- /dev/null
+++ b/src/libcore/tests/time.rs
@@ -0,0 +1,124 @@
+// Copyright 2018 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 core::time::Duration;
+
+#[test]
+fn creation() {
+    assert!(Duration::from_secs(1) != Duration::from_secs(0));
+    assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
+               Duration::from_secs(3));
+    assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
+               Duration::new(4, 10 * 1_000_000));
+    assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
+}
+
+#[test]
+fn secs() {
+    assert_eq!(Duration::new(0, 0).as_secs(), 0);
+    assert_eq!(Duration::from_secs(1).as_secs(), 1);
+    assert_eq!(Duration::from_millis(999).as_secs(), 0);
+    assert_eq!(Duration::from_millis(1001).as_secs(), 1);
+}
+
+#[test]
+fn nanos() {
+    assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
+    assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
+    assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
+    assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
+    assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
+    assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
+}
+
+#[test]
+fn add() {
+    assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
+               Duration::new(0, 1));
+    assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
+               Duration::new(1, 1));
+}
+
+#[test]
+fn checked_add() {
+    assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)),
+               Some(Duration::new(0, 1)));
+    assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
+               Some(Duration::new(1, 1)));
+    assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None);
+}
+
+#[test]
+fn sub() {
+    assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
+               Duration::new(0, 1));
+    assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
+               Duration::new(0, 1));
+    assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
+               Duration::new(0, 999_999_999));
+}
+
+#[test]
+fn checked_sub() {
+    let zero = Duration::new(0, 0);
+    let one_nano = Duration::new(0, 1);
+    let one_sec = Duration::new(1, 0);
+    assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
+    assert_eq!(one_sec.checked_sub(one_nano),
+               Some(Duration::new(0, 999_999_999)));
+    assert_eq!(zero.checked_sub(one_nano), None);
+    assert_eq!(zero.checked_sub(one_sec), None);
+}
+
+#[test]
+#[should_panic]
+fn sub_bad1() {
+    let _ = Duration::new(0, 0) - Duration::new(0, 1);
+}
+
+#[test]
+#[should_panic]
+fn sub_bad2() {
+    let _ = Duration::new(0, 0) - Duration::new(1, 0);
+}
+
+#[test]
+fn mul() {
+    assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
+    assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
+    assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
+    assert_eq!(Duration::new(0, 500_000_001) * 4000,
+               Duration::new(2000, 4000));
+}
+
+#[test]
+fn checked_mul() {
+    assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
+    assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
+    assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
+    assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000),
+               Some(Duration::new(2000, 4000)));
+    assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None);
+}
+
+#[test]
+fn div() {
+    assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
+    assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
+    assert_eq!(Duration::new(99, 999_999_000) / 100,
+               Duration::new(0, 999_999_990));
+}
+
+#[test]
+fn checked_div() {
+    assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
+    assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
+    assert_eq!(Duration::new(2, 0).checked_div(0), None);
+}
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
index e22fe450bb1..8e8b1691c65 100644
--- a/src/libcore/time.rs
+++ b/src/libcore/time.rs
@@ -481,119 +481,3 @@ impl<'a> Sum<&'a Duration> for Duration {
         iter.fold(Duration::new(0, 0), |a, b| a + *b)
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::Duration;
-
-    #[test]
-    fn creation() {
-        assert!(Duration::from_secs(1) != Duration::from_secs(0));
-        assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
-                   Duration::from_secs(3));
-        assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
-                   Duration::new(4, 10 * 1_000_000));
-        assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
-    }
-
-    #[test]
-    fn secs() {
-        assert_eq!(Duration::new(0, 0).as_secs(), 0);
-        assert_eq!(Duration::from_secs(1).as_secs(), 1);
-        assert_eq!(Duration::from_millis(999).as_secs(), 0);
-        assert_eq!(Duration::from_millis(1001).as_secs(), 1);
-    }
-
-    #[test]
-    fn nanos() {
-        assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
-        assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
-        assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
-        assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
-        assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
-        assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
-    }
-
-    #[test]
-    fn add() {
-        assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
-                   Duration::new(1, 1));
-    }
-
-    #[test]
-    fn checked_add() {
-        assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)),
-                   Some(Duration::new(0, 1)));
-        assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
-                   Some(Duration::new(1, 1)));
-        assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None);
-    }
-
-    #[test]
-    fn sub() {
-        assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
-                   Duration::new(0, 999_999_999));
-    }
-
-    #[test]
-    fn checked_sub() {
-        let zero = Duration::new(0, 0);
-        let one_nano = Duration::new(0, 1);
-        let one_sec = Duration::new(1, 0);
-        assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
-        assert_eq!(one_sec.checked_sub(one_nano),
-                   Some(Duration::new(0, 999_999_999)));
-        assert_eq!(zero.checked_sub(one_nano), None);
-        assert_eq!(zero.checked_sub(one_sec), None);
-    }
-
-    #[test] #[should_panic]
-    fn sub_bad1() {
-        Duration::new(0, 0) - Duration::new(0, 1);
-    }
-
-    #[test] #[should_panic]
-    fn sub_bad2() {
-        Duration::new(0, 0) - Duration::new(1, 0);
-    }
-
-    #[test]
-    fn mul() {
-        assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
-        assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
-        assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
-        assert_eq!(Duration::new(0, 500_000_001) * 4000,
-                   Duration::new(2000, 4000));
-    }
-
-    #[test]
-    fn checked_mul() {
-        assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
-        assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
-        assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
-        assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000),
-                   Some(Duration::new(2000, 4000)));
-        assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None);
-    }
-
-    #[test]
-    fn div() {
-        assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
-        assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
-        assert_eq!(Duration::new(99, 999_999_000) / 100,
-                   Duration::new(0, 999_999_990));
-    }
-
-    #[test]
-    fn checked_div() {
-        assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
-        assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
-        assert_eq!(Duration::new(2, 0).checked_div(0), None);
-    }
-}
diff --git a/src/libcore/unicode/bool_trie.rs b/src/libcore/unicode/bool_trie.rs
index 3e45b08f399..0e6437fded5 100644
--- a/src/libcore/unicode/bool_trie.rs
+++ b/src/libcore/unicode/bool_trie.rs
@@ -42,15 +42,15 @@ pub struct BoolTrie {
 }
 impl BoolTrie {
     pub fn lookup(&self, c: char) -> bool {
-        let c = c as usize;
+        let c = c as u32;
         if c < 0x800 {
-            trie_range_leaf(c, self.r1[c >> 6])
+            trie_range_leaf(c, self.r1[(c >> 6) as usize])
         } else if c < 0x10000 {
-            let child = self.r2[(c >> 6) - 0x20];
+            let child = self.r2[(c >> 6) as usize - 0x20];
             trie_range_leaf(c, self.r3[child as usize])
         } else {
-            let child = self.r4[(c >> 12) - 0x10];
-            let leaf = self.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)];
+            let child = self.r4[(c >> 12) as usize - 0x10];
+            let leaf = self.r5[((child as usize) << 6) + ((c >> 6) as usize & 0x3f)];
             trie_range_leaf(c, self.r6[leaf as usize])
         }
     }
@@ -63,14 +63,14 @@ pub struct SmallBoolTrie {
 
 impl SmallBoolTrie {
     pub fn lookup(&self, c: char) -> bool {
-        let c = c as usize;
-        match self.r1.get(c >> 6) {
+        let c = c as u32;
+        match self.r1.get((c >> 6) as usize) {
             Some(&child) => trie_range_leaf(c, self.r2[child as usize]),
             None => false,
         }
     }
 }
 
-fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool {
+fn trie_range_leaf(c: u32, bitmap_chunk: u64) -> bool {
     ((bitmap_chunk >> (c & 63)) & 1) != 0
 }
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index e171216523a..8451e5987e9 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -74,6 +74,11 @@ use syntax_pos::hygiene::Mark;
 #[derive(Clone)]
 pub struct TokenStream(tokenstream::TokenStream);
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for TokenStream {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for TokenStream {}
+
 /// Error returned from `TokenStream::from_str`.
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 #[derive(Debug)]
@@ -81,6 +86,11 @@ pub struct LexError {
     _inner: (),
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for LexError {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for LexError {}
+
 impl TokenStream {
     /// Returns an empty `TokenStream`.
     #[unstable(feature = "proc_macro", issue = "38356")]
@@ -231,6 +241,11 @@ pub fn quote_span(span: Span) -> TokenStream {
 #[derive(Copy, Clone)]
 pub struct Span(syntax_pos::Span);
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Span {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Span {}
+
 macro_rules! diagnostic_method {
     ($name:ident, $level:expr) => (
         /// Create a new `Diagnostic` with the given `message` at the span
@@ -270,7 +285,7 @@ impl Span {
     /// `self` was generated from, if any.
     #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn parent(&self) -> Option<Span> {
-        self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site))
+        self.0.parent().map(Span)
     }
 
     /// The span for the origin source code that `self` was generated from. If
@@ -363,6 +378,11 @@ pub struct LineColumn {
     pub column: usize
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for LineColumn {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for LineColumn {}
+
 /// The source file of a given `Span`.
 #[unstable(feature = "proc_macro", issue = "38356")]
 #[derive(Clone)]
@@ -393,7 +413,7 @@ impl SourceFile {
 
     /// Returns `true` if this source file is a real source file, and not generated by an external
     /// macro's expansion.
-    # [unstable(feature = "proc_macro", issue = "38356")]
+    #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn is_real(&self) -> bool {
         // This is a hack until intercrate spans are implemented and we can have real source files
         // for spans generated in external macros.
@@ -450,6 +470,11 @@ pub enum TokenTree {
     Literal(Literal),
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for TokenTree {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for TokenTree {}
+
 impl TokenTree {
     /// Returns the span of this token, accessing the `span` method of each of
     /// the internal tokens.
@@ -546,6 +571,11 @@ pub struct Group {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Group {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Group {}
+
 /// Describes how a sequence of token trees is delimited.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
@@ -628,6 +658,11 @@ pub struct Op {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Op {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Op {}
+
 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
@@ -694,6 +729,11 @@ pub struct Term {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Term {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Term {}
+
 impl Term {
     /// Creates a new `Term` with the given `string` as well as the specified
     /// `span`.
@@ -752,6 +792,11 @@ pub struct Literal {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Literal {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Literal {}
+
 macro_rules! suffixed_int_literals {
     ($($name:ident => $kind:ident,)*) => ($(
         /// Creates a new suffixed integer literal with the specified value.
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 357ebb89fb6..af108188ce0 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -19,7 +19,6 @@ log = { version = "0.4", features = ["release_max_level_info", "std"] }
 proc_macro = { path = "../libproc_macro" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 18bf54297af..e4f432e7caf 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -70,7 +70,8 @@ use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use std::fmt;
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{CanonicalProjectionGoal,
+                    CanonicalTyGoal, CanonicalPredicateGoal};
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
 use ty::subst::Substs;
 
@@ -643,6 +644,7 @@ define_dep_nodes!( <'tcx>
     [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
     [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
     [] DropckOutlives(CanonicalTyGoal<'tcx>),
+    [] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
 
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 956cd17f38f..24a1256c9d3 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -30,6 +30,8 @@ enum Target {
     ForeignMod,
     Expression,
     Statement,
+    Closure,
+    Static,
     Other,
 }
 
@@ -42,6 +44,7 @@ impl Target {
             hir::ItemEnum(..) => Target::Enum,
             hir::ItemConst(..) => Target::Const,
             hir::ItemForeignMod(..) => Target::ForeignMod,
+            hir::ItemStatic(..) => Target::Static,
             _ => Target::Other,
         }
     }
@@ -101,16 +104,17 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
         }
 
         self.check_repr(item, target);
+        self.check_used(item, target);
     }
 
-    /// Check if an `#[inline]` is applied to a function.
+    /// Check if an `#[inline]` is applied to a function or a closure.
     fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) {
-        if target != Target::Fn {
+        if target != Target::Fn && target != Target::Closure {
             struct_span_err!(self.tcx.sess,
                              attr.span,
                              E0518,
-                             "attribute should be applied to function")
-                .span_label(*span, "not a function")
+                             "attribute should be applied to function or closure")
+                .span_label(*span, "not a function or closure")
                 .emit();
         }
     }
@@ -149,10 +153,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
         // ```
         let hints: Vec<_> = item.attrs
             .iter()
-            .filter(|attr| match attr.name() {
-                Some(name) => name == "repr",
-                None => false,
-            })
+            .filter(|attr| attr.name() == "repr")
             .filter_map(|attr| attr.meta_item_list())
             .flat_map(|hints| hints)
             .collect();
@@ -286,9 +287,13 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
     }
 
     fn check_expr_attributes(&self, expr: &hir::Expr) {
+        let target = match expr.node {
+            hir::ExprClosure(..) => Target::Closure,
+            _ => Target::Expression,
+        };
         for attr in expr.attrs.iter() {
             if attr.check_name("inline") {
-                self.check_inline(attr, &expr.span, Target::Expression);
+                self.check_inline(attr, &expr.span, target);
             }
             if attr.check_name("repr") {
                 self.emit_repr_error(
@@ -300,6 +305,15 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
             }
         }
     }
+
+    fn check_used(&self, item: &hir::Item, target: Target) {
+        for attr in &item.attrs {
+            if attr.name() == "used" && target != Target::Static {
+                self.tcx.sess
+                    .span_err(attr.span, "attribute must be applied to a `static` variable");
+            }
+        }
+    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 62f3f9f4486..3e5dcee113a 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -404,7 +404,7 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
     // Intentionally visiting the expr first - the initialization expr
     // dominates the local's definition.
     walk_list!(visitor, visit_expr, &local.init);
-
+    walk_list!(visitor, visit_attribute, local.attrs.iter());
     visitor.visit_id(local.id);
     visitor.visit_pat(&local.pat);
     walk_list!(visitor, visit_ty, &local.ty);
@@ -731,6 +731,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
             visitor.visit_name(ty_param.span, ty_param.name);
             walk_list!(visitor, visit_ty_param_bound, &ty_param.bounds);
             walk_list!(visitor, visit_ty, &ty_param.default);
+            walk_list!(visitor, visit_attribute, ty_param.attrs.iter());
         }
     }
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 4023521147e..51f0c1d7047 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -655,7 +655,7 @@ impl<'a> LoweringContext<'a> {
                 self.resolver.definitions().create_def_with_parent(
                     parent_id.index,
                     def_node_id,
-                    DefPathData::LifetimeDef(str_name),
+                    DefPathData::LifetimeDef(str_name.as_interned_str()),
                     DefIndexAddressSpace::High,
                     Mark::root(),
                     span,
@@ -1302,7 +1302,7 @@ impl<'a> LoweringContext<'a> {
                     self.context.resolver.definitions().create_def_with_parent(
                         self.parent,
                         def_node_id,
-                        DefPathData::LifetimeDef(name.name().as_str()),
+                        DefPathData::LifetimeDef(name.name().as_interned_str()),
                         DefIndexAddressSpace::High,
                         Mark::root(),
                         lifetime.span,
@@ -3119,6 +3119,20 @@ impl<'a> LoweringContext<'a> {
             ExprKind::Index(ref el, ref er) => {
                 hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
             }
+            // Desugar `<start>..=<end>` to `std::ops::RangeInclusive::new(<start>, <end>)`
+            ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
+                // FIXME: Use e.span directly after RangeInclusive::new() is stabilized in stage0.
+                let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
+                let id = self.next_id();
+                let e1 = self.lower_expr(e1);
+                let e2 = self.lower_expr(e2);
+                let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false));
+                let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path));
+                let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new")));
+                let new_path = hir::QPath::TypeRelative(ty, new_seg);
+                let new = P(self.expr(span, hir::ExprPath(new_path), ThinVec::new()));
+                hir::ExprCall(new, hir_vec![e1, e2])
+            }
             ExprKind::Range(ref e1, ref e2, lims) => {
                 use syntax::ast::RangeLimits::*;
 
@@ -3128,7 +3142,7 @@ impl<'a> LoweringContext<'a> {
                     (&None, &Some(..), HalfOpen) => "RangeTo",
                     (&Some(..), &Some(..), HalfOpen) => "Range",
                     (&None, &Some(..), Closed) => "RangeToInclusive",
-                    (&Some(..), &Some(..), Closed) => "RangeInclusive",
+                    (&Some(..), &Some(..), Closed) => unreachable!(),
                     (_, &None, Closed) => self.diagnostic()
                         .span_fatal(e.span, "inclusive range with no end")
                         .raise(),
@@ -4107,15 +4121,13 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) {
-        if self.sess.features_untracked().dyn_trait {
-            self.sess.buffer_lint_with_diagnostic(
-                builtin::BARE_TRAIT_OBJECT,
-                id,
-                span,
-                "trait objects without an explicit `dyn` are deprecated",
-                builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
-            )
-        }
+        self.sess.buffer_lint_with_diagnostic(
+            builtin::BARE_TRAIT_OBJECT,
+            id,
+            span,
+            "trait objects without an explicit `dyn` are deprecated",
+            builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
+        )
     }
 
     fn wrap_in_try_constructor(
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bfe21549e45..ebd8e623582 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -107,18 +107,18 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         // information we encapsulate into
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
-            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()),
+            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
             ItemKind::TraitAlias(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.name.as_str()),
+                DefPathData::TypeNs(i.ident.name.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
-            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.name.as_str()),
-            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
+                DefPathData::ValueNs(i.ident.name.as_interned_str()),
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
@@ -133,7 +133,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.ident.name.as_str()),
+                                            DefPathData::EnumVariant(v.node.ident
+                                                                      .name.as_interned_str()),
                                             REGULAR_SPACE,
                                             v.span);
                         this.with_parent(variant_def_index, |this| {
@@ -141,7 +142,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                                 let name = field.ident.map(|ident| ident.name)
                                     .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                                 this.create_def(field.id,
-                                                DefPathData::Field(name.as_str()),
+                                                DefPathData::Field(name.as_interned_str()),
                                                 REGULAR_SPACE,
                                                 field.span);
                             }
@@ -165,7 +166,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                         let name = field.ident.map(|ident| ident.name)
                             .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                         this.create_def(field.id,
-                                        DefPathData::Field(name.as_str()),
+                                        DefPathData::Field(name.as_interned_str()),
                                         REGULAR_SPACE,
                                         field.span);
                     }
@@ -187,7 +188,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         }
 
         let def = self.create_def(foreign_item.id,
-                                  DefPathData::ValueNs(foreign_item.ident.name.as_str()),
+                                  DefPathData::ValueNs(foreign_item.ident.name.as_interned_str()),
                                   REGULAR_SPACE,
                                   foreign_item.span);
 
@@ -201,7 +202,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             GenericParam::Lifetime(ref lifetime_def) => {
                 self.create_def(
                     lifetime_def.lifetime.id,
-                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_str()),
+                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()),
                     REGULAR_SPACE,
                     lifetime_def.lifetime.ident.span
                 );
@@ -209,7 +210,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             GenericParam::Type(ref ty_param) => {
                 self.create_def(
                     ty_param.id,
-                    DefPathData::TypeParam(ty_param.ident.name.as_str()),
+                    DefPathData::TypeParam(ty_param.ident.name.as_interned_str()),
                     REGULAR_SPACE,
                     ty_param.ident.span
                 );
@@ -222,8 +223,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name.as_str()),
-            TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()),
+                DefPathData::ValueNs(ti.ident.name.as_interned_str()),
+            TraitItemKind::Type(..) => {
+                DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str())
+            },
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
         };
 
@@ -240,8 +243,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.name.as_str()),
-            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()),
+                DefPathData::ValueNs(ii.ident.name.as_interned_str()),
+            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
         };
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 12f146ef491..616dc22486d 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -701,7 +701,7 @@ impl DefPathData {
             Typeof => "{{typeof}}",
         };
 
-        Symbol::intern(s).as_str()
+        Symbol::intern(s).as_interned_str()
     }
 
     pub fn to_string(&self) -> String {
@@ -731,7 +731,7 @@ macro_rules! define_global_metadata_kind {
                     definitions.create_def_with_parent(
                         CRATE_DEF_INDEX,
                         ast::DUMMY_NODE_ID,
-                        DefPathData::GlobalMetaData(instance.name().as_str()),
+                        DefPathData::GlobalMetaData(instance.name().as_interned_str()),
                         GLOBAL_MD_ADDRESS_SPACE,
                         Mark::root(),
                         DUMMY_SP
@@ -746,7 +746,7 @@ macro_rules! define_global_metadata_kind {
                 let def_key = DefKey {
                     parent: Some(CRATE_DEF_INDEX),
                     disambiguated_data: DisambiguatedDefPathData {
-                        data: DefPathData::GlobalMetaData(self.name().as_str()),
+                        data: DefPathData::GlobalMetaData(self.name().as_interned_str()),
                         disambiguator: 0,
                     }
                 };
diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs
deleted file mode 100644
index 5f3ff461c0c..00000000000
--- a/src/librustc/ich/impls_const_math.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.
-
-//! This module contains `HashStable` implementations for various data types
-//! from `rustc_const_math` in no particular order.
-
-impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat {
-    ty,
-    bits
-});
-
-impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr {
-    NotInRange,
-    CmpBetweenUnequalTypes,
-    UnequalTypes(op),
-    Overflow(op),
-    ShiftNegative,
-    DivisionByZero,
-    RemainderByZero,
-    UnsignedNegation,
-    ULitOutOfRange(int_ty),
-    LitOutOfRange(int_ty)
-});
-
-impl_stable_hash_for!(enum ::rustc_const_math::Op {
-    Add,
-    Sub,
-    Mul,
-    Div,
-    Rem,
-    Shr,
-    Shl,
-    Neg,
-    BitAnd,
-    BitOr,
-    BitXor
-});
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index c73f171806e..33f43e53394 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -227,27 +227,6 @@ for mir::TerminatorKind<'gcx> {
     }
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for mir::AssertMessage<'gcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            mir::AssertMessage::BoundsCheck { ref len, ref index } => {
-                len.hash_stable(hcx, hasher);
-                index.hash_stable(hcx, hasher);
-            }
-            mir::AssertMessage::Math(ref const_math_err) => {
-                const_math_err.hash_stable(hcx, hasher);
-            }
-            mir::AssertMessage::GeneratorResumedAfterReturn => (),
-            mir::AssertMessage::GeneratorResumedAfterPanic => (),
-        }
-    }
-}
-
 impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
@@ -563,6 +542,11 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Literal<'gcx> {
 
 impl_stable_hash_for!(struct mir::Location { block, statement_index });
 
+impl_stable_hash_for!(struct mir::BorrowCheckResult<'tcx> {
+    closure_requirements,
+    used_mut_upvars
+});
+
 impl_stable_hash_for!(struct mir::ClosureRegionRequirements<'tcx> {
     num_external_vids,
     outlives_requirements
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index d7e16ab3620..1cf9b7bf478 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -19,7 +19,7 @@ use std::mem;
 use syntax::ast;
 use syntax::feature_gate;
 use syntax::parse::token;
-use syntax::symbol::InternedString;
+use syntax::symbol::{InternedString, LocalInternedString};
 use syntax::tokenstream;
 use syntax_pos::FileMap;
 
@@ -34,8 +34,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for InternedString {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        let s: &str = &**self;
-        s.hash_stable(hcx, hasher);
+        self.with(|s| s.hash_stable(hcx, hasher))
     }
 }
 
@@ -50,6 +49,27 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for InternedString {
     }
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let s: &str = &**self;
+        s.hash_stable(hcx, hasher);
+    }
+}
+
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
+    type KeyType = LocalInternedString;
+
+    #[inline]
+    fn to_stable_hash_key(&self,
+                          _: &StableHashingContext<'a>)
+                          -> LocalInternedString {
+        self.clone()
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
@@ -66,7 +86,7 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
     fn to_stable_hash_key(&self,
                           _: &StableHashingContext<'a>)
                           -> InternedString {
-        self.as_str()
+        self.as_interned_str()
     }
 }
 
@@ -179,8 +199,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
         let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
             .iter()
             .filter(|attr| {
-                !attr.is_sugared_doc &&
-                attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
+                !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
             })
             .collect();
 
@@ -191,12 +210,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
     }
 }
 
+impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        self.segments.len().hash_stable(hcx, hasher);
+        for segment in &self.segments {
+            segment.ident.name.hash_stable(hcx, hasher);
+        }
+    }
+}
+
 impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         // Make sure that these have been filtered out.
-        debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
+        debug_assert!(!hcx.is_ignored_attr(self.name()));
         debug_assert!(!self.is_sugared_doc);
 
         let ast::Attribute {
@@ -209,10 +239,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
         } = *self;
 
         style.hash_stable(hcx, hasher);
-        path.segments.len().hash_stable(hcx, hasher);
-        for segment in &path.segments {
-            segment.ident.name.hash_stable(hcx, hasher);
-        }
+        path.hash_stable(hcx, hasher);
         for tt in tokens.trees() {
             tt.hash_stable(hcx, hasher);
         }
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 5ab8d6eb7b3..a40d8e09277 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -505,9 +505,6 @@ for ::middle::const_val::ErrKind<'gcx> {
                 len.hash_stable(hcx, hasher);
                 index.hash_stable(hcx, hasher);
             }
-            Math(ref const_math_err) => {
-                const_math_err.hash_stable(hcx, hasher);
-            }
             LayoutError(ref layout_error) => {
                 layout_error.hash_stable(hcx, hasher);
             }
@@ -528,16 +525,26 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
     predicates
 });
 
+
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
 for ::mir::interpret::EvalError<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
+        self.kind.hash_stable(hcx, hasher)
+    }
+}
+
+impl<'a, 'gcx, O: HashStable<StableHashingContext<'a>>> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::EvalErrorKind<'gcx, O> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
         use mir::interpret::EvalErrorKind::*;
 
-        mem::discriminant(&self.kind).hash_stable(hcx, hasher);
+        mem::discriminant(&self).hash_stable(hcx, hasher);
 
-        match self.kind {
+        match *self {
             DanglingPointerDeref |
             DoubleFree |
             InvalidMemoryAccess |
@@ -568,8 +575,12 @@ for ::mir::interpret::EvalError<'gcx> {
             TypeckError |
             DerefFunctionPointer |
             ExecuteMemory |
-            ReferencedConstant |
-            OverflowingMath => {}
+            OverflowNeg |
+            RemainderByZero |
+            DivisionByZero |
+            GeneratorResumedAfterReturn |
+            GeneratorResumedAfterPanic |
+            ReferencedConstant => {}
             MachineError(ref err) => err.hash_stable(hcx, hasher),
             FunctionPointerTyMismatch(a, b) => {
                 a.hash_stable(hcx, hasher);
@@ -588,14 +599,9 @@ for ::mir::interpret::EvalError<'gcx> {
             },
             InvalidBoolOp(bop) => bop.hash_stable(hcx, hasher),
             Unimplemented(ref s) => s.hash_stable(hcx, hasher),
-            ArrayIndexOutOfBounds(sp, a, b) => {
-                sp.hash_stable(hcx, hasher);
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher)
-            },
-            Math(sp, ref err) => {
-                sp.hash_stable(hcx, hasher);
-                err.hash_stable(hcx, hasher)
+            BoundsCheck { ref len, ref index } => {
+                len.hash_stable(hcx, hasher);
+                index.hash_stable(hcx, hasher)
             },
             Intrinsic(ref s) => s.hash_stable(hcx, hasher),
             InvalidChar(c) => c.hash_stable(hcx, hasher),
@@ -668,6 +674,7 @@ for ::mir::interpret::EvalError<'gcx> {
             Layout(lay) => lay.hash_stable(hcx, hasher),
             HeapAllocNonPowerOfTwoAlignment(n) => n.hash_stable(hcx, hasher),
             PathNotFound(ref v) => v.hash_stable(hcx, hasher),
+            Overflow(op) => op.hash_stable(hcx, hasher),
         }
     }
 }
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index 1b77a2e7c82..a0c6bbbb239 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -18,7 +18,6 @@ mod fingerprint;
 mod caching_codemap_view;
 mod hcx;
 
-mod impls_const_math;
 mod impls_cstore;
 mod impls_hir;
 mod impls_mir;
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index 096aed85f55..ccba5a09cf6 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -407,7 +407,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
                             drop(variables);
                             self.relate(&u, &u)
                         }
-                        TypeVariableValue::Unknown { .. } => {
+                        TypeVariableValue::Unknown { universe } => {
                             match self.ambient_variance {
                                 // Invariant: no need to make a fresh type variable.
                                 ty::Invariant => return Ok(t),
@@ -424,7 +424,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
                             }
 
                             let origin = *variables.var_origin(vid);
-                            let new_var_id = variables.new_var(false, origin);
+                            let new_var_id = variables.new_var(universe, false, origin);
                             let u = self.tcx().mk_var(new_var_id);
                             debug!("generalize: replacing original vid={:?} with new={:?}",
                                    vid, u);
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index c23836071ff..b8437e39ddc 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -19,7 +19,7 @@ use super::{CombinedSnapshot,
 use super::combine::CombineFields;
 use super::region_constraints::{TaintDirections};
 
-use std::collections::BTreeMap;
+use rustc_data_structures::lazy_btree_map::LazyBTreeMap;
 use ty::{self, TyCtxt, Binder, TypeFoldable};
 use ty::error::TypeError;
 use ty::relate::{Relate, RelateResult, TypeRelation};
@@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
             // Second, we instantiate each bound region in the supertype with a
             // fresh concrete region.
             let (b_prime, skol_map) =
-                self.infcx.skolemize_late_bound_regions(b, snapshot);
+                self.infcx.skolemize_late_bound_regions(b);
 
             debug!("a_prime={:?}", a_prime);
             debug!("b_prime={:?}", b_prime);
@@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
             // First, we instantiate each bound region in the matcher
             // with a skolemized region.
             let ((a_match, a_value), skol_map) =
-                self.infcx.skolemize_late_bound_regions(a_pair, snapshot);
+                self.infcx.skolemize_late_bound_regions(a_pair);
 
             debug!("higher_ranked_match: a_match={:?}", a_match);
             debug!("higher_ranked_match: skol_map={:?}", skol_map);
@@ -247,7 +247,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                              snapshot: &CombinedSnapshot<'a, 'tcx>,
                                              debruijn: ty::DebruijnIndex,
                                              new_vars: &[ty::RegionVid],
-                                             a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+                                             a_map: &LazyBTreeMap<ty::BoundRegion,
+                                                                  ty::Region<'tcx>>,
                                              r0: ty::Region<'tcx>)
                                              -> ty::Region<'tcx> {
             // Regions that pre-dated the LUB computation stay as they are.
@@ -343,7 +344,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                              snapshot: &CombinedSnapshot<'a, 'tcx>,
                                              debruijn: ty::DebruijnIndex,
                                              new_vars: &[ty::RegionVid],
-                                             a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+                                             a_map: &LazyBTreeMap<ty::BoundRegion,
+                                                                  ty::Region<'tcx>>,
                                              a_vars: &[ty::RegionVid],
                                              b_vars: &[ty::RegionVid],
                                              r0: ty::Region<'tcx>)
@@ -412,7 +414,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
 
         fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                       span: Span,
-                                      a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
+                                      a_map: &LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
                                       r: ty::Region<'tcx>) -> ty::Region<'tcx>
         {
             for (a_br, a_r) in a_map {
@@ -435,7 +437,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
 }
 
 fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>,
-                           map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+                           map: &LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
                            -> Vec<ty::RegionVid> {
     map.iter()
        .map(|(_, &r)| match *r {
@@ -585,14 +587,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     ///
     /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
     pub fn skolemize_late_bound_regions<T>(&self,
-                                           binder: &ty::Binder<T>,
-                                           snapshot: &CombinedSnapshot<'a, 'tcx>)
+                                           binder: &ty::Binder<T>)
                                            -> (T, SkolemizationMap<'tcx>)
         where T : TypeFoldable<'tcx>
     {
         let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
-            self.borrow_region_constraints()
-                .push_skolemized(self.tcx, br, &snapshot.region_constraints_snapshot)
+            self.universe.set(self.universe().subuniverse());
+            self.tcx.mk_region(ty::ReSkolemized(self.universe(), br))
         });
 
         debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})",
@@ -777,7 +778,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         debug!("pop_skolemized({:?})", skol_map);
         let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect();
         self.borrow_region_constraints()
-            .pop_skolemized(self.tcx, &skol_regions, &snapshot.region_constraints_snapshot);
+            .pop_skolemized(self.universe(), &skol_regions, &snapshot.region_constraints_snapshot);
+        self.universe.set(snapshot.universe);
         if !skol_map.is_empty() {
             self.projection_cache.borrow_mut().rollback_skolemized(
                 &snapshot.projection_cache_snapshot);
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 00b2ac7449f..5984a831e6f 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -15,7 +15,7 @@ use infer::RegionVariableOrigin;
 use infer::region_constraints::Constraint;
 use infer::region_constraints::GenericKind;
 use infer::region_constraints::RegionConstraintData;
-use infer::region_constraints::VarOrigins;
+use infer::region_constraints::VarInfos;
 use infer::region_constraints::VerifyBound;
 use middle::free_region::RegionRelations;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
@@ -37,7 +37,7 @@ mod graphviz;
 /// all the variables as well as a set of errors that must be reported.
 pub fn resolve<'tcx>(
     region_rels: &RegionRelations<'_, '_, 'tcx>,
-    var_origins: VarOrigins,
+    var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
 ) -> (
     LexicalRegionResolutions<'tcx>,
@@ -47,7 +47,7 @@ pub fn resolve<'tcx>(
     let mut errors = vec![];
     let mut resolver = LexicalResolver {
         region_rels,
-        var_origins,
+        var_infos,
         data,
     };
     let values = resolver.infer_variable_values(&mut errors);
@@ -103,7 +103,7 @@ type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
 
 struct LexicalResolver<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     region_rels: &'cx RegionRelations<'cx, 'gcx, 'tcx>,
-    var_origins: VarOrigins,
+    var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
 }
 
@@ -132,7 +132,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
     }
 
     fn num_vars(&self) -> usize {
-        self.var_origins.len()
+        self.var_infos.len()
     }
 
     /// Initially, the value for all variables is set to `'empty`, the
@@ -279,7 +279,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
 
             (&ReVar(v_id), _) | (_, &ReVar(v_id)) => {
                 span_bug!(
-                    self.var_origins[v_id].span(),
+                    self.var_infos[v_id].origin.span(),
                     "lub_concrete_regions invoked with non-concrete \
                      regions: {:?}, {:?}",
                     a,
@@ -576,7 +576,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
                 if !self.region_rels
                     .is_subregion_of(lower_bound.region, upper_bound.region)
                 {
-                    let origin = self.var_origins[node_idx].clone();
+                    let origin = self.var_infos[node_idx].origin.clone();
                     debug!(
                         "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
                          sup: {:?}",
@@ -598,7 +598,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
         }
 
         span_bug!(
-            self.var_origins[node_idx].span(),
+            self.var_infos[node_idx].origin.span(),
             "collect_error_for_expanding_node() could not find \
              error for var {:?}, lower_bounds={:?}, \
              upper_bounds={:?}",
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 40cc43c3ca6..c62e7f8d9b6 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -28,9 +28,9 @@ use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::TypeFoldable;
 use ty::relate::RelateResult;
 use traits::{self, ObligationCause, PredicateObligations};
+use rustc_data_structures::lazy_btree_map::LazyBTreeMap;
 use rustc_data_structures::unify as ut;
 use std::cell::{Cell, RefCell, Ref, RefMut};
-use std::collections::BTreeMap;
 use std::fmt;
 use syntax::ast;
 use errors::DiagnosticBuilder;
@@ -42,7 +42,7 @@ use arena::SyncDroplessArena;
 use self::combine::CombineFields;
 use self::higher_ranked::HrMatchResult;
 use self::region_constraints::{RegionConstraintCollector, RegionSnapshot};
-use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarOrigins};
+use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarInfos};
 use self::lexical_region_resolve::LexicalRegionResolutions;
 use self::outlives::env::OutlivesEnvironment;
 use self::type_variable::TypeVariableOrigin;
@@ -183,11 +183,22 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // obligations within. This is expected to be done 'late enough'
     // that all type inference variables have been bound and so forth.
     pub region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
+
+    /// What is the innermost universe we have created? Starts out as
+    /// `UniverseIndex::root()` but grows from there as we enter
+    /// universal quantifiers.
+    ///
+    /// NB: At present, we exclude the universal quantifiers on the
+    /// item we are type-checking, and just consider those names as
+    /// part of the root universe. So this would only get incremented
+    /// when we enter into a higher-ranked (`for<..>`) type or trait
+    /// bound.
+    universe: Cell<ty::UniverseIndex>,
 }
 
 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
 /// region that each late-bound region was replaced with.
-pub type SkolemizationMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
+pub type SkolemizationMap<'tcx> = LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
 
 /// See `error_reporting` module for more details
 #[derive(Clone, Debug)]
@@ -455,6 +466,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
             err_count_on_creation: tcx.sess.err_count(),
             in_snapshot: Cell::new(false),
             region_obligations: RefCell::new(vec![]),
+            universe: Cell::new(ty::UniverseIndex::ROOT),
         }))
     }
 }
@@ -489,6 +501,7 @@ pub struct CombinedSnapshot<'a, 'tcx:'a> {
     float_snapshot: ut::Snapshot<ut::InPlace<ty::FloatVid>>,
     region_constraints_snapshot: RegionSnapshot,
     region_obligations_snapshot: usize,
+    universe: ty::UniverseIndex,
     was_in_snapshot: bool,
     _in_progress_tables: Option<Ref<'a, ty::TypeckTables<'tcx>>>,
 }
@@ -618,6 +631,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
             region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(),
             region_obligations_snapshot: self.region_obligations.borrow().len(),
+            universe: self.universe(),
             was_in_snapshot: in_snapshot,
             // Borrow tables "in progress" (i.e. during typeck)
             // to ban writes from within a snapshot to them.
@@ -635,10 +649,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                float_snapshot,
                                region_constraints_snapshot,
                                region_obligations_snapshot,
+                               universe,
                                was_in_snapshot,
                                _in_progress_tables } = snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
+        self.universe.set(universe);
 
         self.projection_cache
             .borrow_mut()
@@ -667,6 +683,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                float_snapshot,
                                region_constraints_snapshot,
                                region_obligations_snapshot: _,
+                               universe: _,
                                was_in_snapshot,
                                _in_progress_tables } = snapshot;
 
@@ -811,7 +828,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
         Some(self.commit_if_ok(|snapshot| {
             let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) =
-                self.skolemize_late_bound_regions(predicate, snapshot);
+                self.skolemize_late_bound_regions(predicate);
 
             let cause_span = cause.span;
             let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@@ -828,7 +845,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     {
         self.commit_if_ok(|snapshot| {
             let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
-                self.skolemize_late_bound_regions(predicate, snapshot);
+                self.skolemize_late_bound_regions(predicate);
             let origin =
                 SubregionOrigin::from_obligation_cause(cause,
                                                        || RelateRegionParamBound(cause.span));
@@ -841,7 +858,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
         self.type_variables
             .borrow_mut()
-            .new_var(diverging, origin)
+            .new_var(self.universe(), diverging, origin)
     }
 
     pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
@@ -872,12 +889,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     ///   during diagnostics / error-reporting.
     pub fn next_region_var(&self, origin: RegionVariableOrigin)
                            -> ty::Region<'tcx> {
-        self.tcx.mk_region(ty::ReVar(self.borrow_region_constraints().new_region_var(origin)))
+        let region_var = self.borrow_region_constraints()
+            .new_region_var(self.universe(), origin);
+        self.tcx.mk_region(ty::ReVar(region_var))
     }
 
     /// Number of region variables created so far.
     pub fn num_region_vars(&self) -> usize {
-        self.borrow_region_constraints().var_origins().len()
+        self.borrow_region_constraints().num_region_vars()
     }
 
     /// Just a convenient wrapper of `next_region_var` for using during NLL.
@@ -909,7 +928,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                             -> Ty<'tcx> {
         let ty_var_id = self.type_variables
                             .borrow_mut()
-                            .new_var(false,
+                            .new_var(self.universe(),
+                                     false,
                                      TypeVariableOrigin::TypeParameterDefinition(span, def.name));
 
         self.tcx.mk_var(ty_var_id)
@@ -1004,12 +1024,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                 region_context,
                                                 region_map,
                                                 outlives_env.free_region_map());
-        let (var_origins, data) = self.region_constraints.borrow_mut()
+        let (var_infos, data) = self.region_constraints.borrow_mut()
                                                          .take()
                                                          .expect("regions already resolved")
-                                                         .into_origins_and_data();
+                                                         .into_infos_and_data();
         let (lexical_region_resolutions, errors) =
-            lexical_region_resolve::resolve(region_rels, var_origins, data);
+            lexical_region_resolve::resolve(region_rels, var_infos, data);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
@@ -1057,13 +1077,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// hence that `resolve_regions_and_report_errors` can never be
     /// called. This is used only during NLL processing to "hand off" ownership
     /// of the set of region vairables into the NLL region context.
-    pub fn take_region_var_origins(&self) -> VarOrigins {
-        let (var_origins, data) = self.region_constraints.borrow_mut()
+    pub fn take_region_var_origins(&self) -> VarInfos {
+        let (var_infos, data) = self.region_constraints.borrow_mut()
                                                          .take()
                                                          .expect("regions already resolved")
-                                                         .into_origins_and_data();
+                                                         .into_infos_and_data();
         assert!(data.is_empty());
-        var_origins
+        var_infos
     }
 
     pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
@@ -1216,7 +1236,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         span: Span,
         lbrct: LateBoundRegionConversionTime,
         value: &ty::Binder<T>)
-        -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+        -> (T, LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where T : TypeFoldable<'tcx>
     {
         self.tcx.replace_late_bound_regions(
@@ -1356,6 +1376,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.evaluation_cache.clear();
         self.projection_cache.borrow_mut().clear();
     }
+
+    fn universe(&self) -> ty::UniverseIndex {
+        self.universe.get()
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> {
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 4113a2dd417..c388fa21371 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -22,18 +22,16 @@ use rustc_data_structures::unify as ut;
 use ty::{self, Ty, TyCtxt};
 use ty::{Region, RegionVid};
 use ty::ReStatic;
-use ty::{BrFresh, ReLateBound, ReSkolemized, ReVar};
+use ty::{BrFresh, ReLateBound, ReVar};
 
 use std::collections::BTreeMap;
-use std::fmt;
-use std::mem;
-use std::u32;
+use std::{cmp, fmt, mem, u32};
 
 mod taint;
 
 pub struct RegionConstraintCollector<'tcx> {
     /// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
-    var_origins: IndexVec<RegionVid, RegionVariableOrigin>,
+    var_infos: IndexVec<RegionVid, RegionVariableInfo>,
 
     data: RegionConstraintData<'tcx>,
 
@@ -47,9 +45,6 @@ pub struct RegionConstraintCollector<'tcx> {
     /// exist). This prevents us from making many such regions.
     glbs: CombineMap<'tcx>,
 
-    /// Number of skolemized variables currently active.
-    skolemization_count: u32,
-
     /// Global counter used during the GLB algorithm to create unique
     /// names for fresh bound regions
     bound_count: u32,
@@ -76,7 +71,7 @@ pub struct RegionConstraintCollector<'tcx> {
     unification_table: ut::UnificationTable<ut::InPlace<ty::RegionVid>>,
 }
 
-pub type VarOrigins = IndexVec<RegionVid, RegionVariableOrigin>;
+pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
 
 /// The full set of region constraints gathered up by the collector.
 /// Describes constraints between the region variables and other
@@ -230,10 +225,15 @@ enum CombineMapType {
 
 type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
 
+#[derive(Debug, Clone, Copy)]
+pub struct RegionVariableInfo {
+    pub origin: RegionVariableOrigin,
+    pub universe: ty::UniverseIndex,
+}
+
 pub struct RegionSnapshot {
     length: usize,
     region_snapshot: ut::Snapshot<ut::InPlace<ty::RegionVid>>,
-    skolemization_count: u32,
 }
 
 /// When working with skolemized regions, we often wish to find all of
@@ -273,19 +273,18 @@ impl TaintDirections {
 impl<'tcx> RegionConstraintCollector<'tcx> {
     pub fn new() -> RegionConstraintCollector<'tcx> {
         RegionConstraintCollector {
-            var_origins: VarOrigins::default(),
+            var_infos: VarInfos::default(),
             data: RegionConstraintData::default(),
             lubs: FxHashMap(),
             glbs: FxHashMap(),
-            skolemization_count: 0,
             bound_count: 0,
             undo_log: Vec::new(),
             unification_table: ut::UnificationTable::new(),
         }
     }
 
-    pub fn var_origins(&self) -> &VarOrigins {
-        &self.var_origins
+    pub fn num_region_vars(&self) -> usize {
+        self.var_infos.len()
     }
 
     pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
@@ -295,9 +294,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     /// Once all the constraints have been gathered, extract out the final data.
     ///
     /// Not legal during a snapshot.
-    pub fn into_origins_and_data(self) -> (VarOrigins, RegionConstraintData<'tcx>) {
+    pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
         assert!(!self.in_snapshot());
-        (self.var_origins, self.data)
+        (self.var_infos, self.data)
     }
 
     /// Takes (and clears) the current set of constraints. Note that
@@ -319,18 +318,15 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         // should think carefully about whether it needs to be cleared
         // or updated in some way.
         let RegionConstraintCollector {
-            var_origins,
+            var_infos,
             data,
             lubs,
             glbs,
-            skolemization_count,
             bound_count: _,
             undo_log: _,
             unification_table,
         } = self;
 
-        assert_eq!(*skolemization_count, 0);
-
         // Clear the tables of (lubs, glbs), so that we will create
         // fresh regions if we do a LUB operation. As it happens,
         // LUB/GLB are not performed by the MIR type-checker, which is
@@ -343,7 +339,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         // also insert `a <= b` and a `b <= a` edges, so the
         // `RegionConstraintData` contains the relationship here.
         *unification_table = ut::UnificationTable::new();
-        for vid in var_origins.indices() {
+        for vid in var_infos.indices() {
             unification_table.new_key(unify_key::RegionVidKey { min_vid: vid });
         }
 
@@ -365,7 +361,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         RegionSnapshot {
             length,
             region_snapshot: self.unification_table.snapshot(),
-            skolemization_count: self.skolemization_count,
         }
     }
 
@@ -373,12 +368,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         debug!("RegionConstraintCollector: commit({})", snapshot.length);
         assert!(self.undo_log.len() > snapshot.length);
         assert!(self.undo_log[snapshot.length] == OpenSnapshot);
-        assert!(
-            self.skolemization_count == snapshot.skolemization_count,
-            "failed to pop skolemized regions: {} now vs {} at start",
-            self.skolemization_count,
-            snapshot.skolemization_count
-        );
 
         if snapshot.length == 0 {
             self.undo_log.truncate(0);
@@ -398,7 +387,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         }
         let c = self.undo_log.pop().unwrap();
         assert!(c == OpenSnapshot);
-        self.skolemization_count = snapshot.skolemization_count;
         self.unification_table.rollback_to(snapshot.region_snapshot);
     }
 
@@ -411,8 +399,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
                 // nothing to do here
             }
             AddVar(vid) => {
-                self.var_origins.pop().unwrap();
-                assert_eq!(self.var_origins.len(), vid.index() as usize);
+                self.var_infos.pop().unwrap();
+                assert_eq!(self.var_infos.len(), vid.index() as usize);
             }
             AddConstraint(ref constraint) => {
                 self.data.constraints.remove(constraint);
@@ -433,8 +421,13 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         }
     }
 
-    pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid {
-        let vid = self.var_origins.push(origin.clone());
+    pub fn new_region_var(&mut self,
+                          universe: ty::UniverseIndex,
+                          origin: RegionVariableOrigin) -> RegionVid {
+        let vid = self.var_infos.push(RegionVariableInfo {
+            origin,
+            universe,
+        });
 
         let u_vid = self.unification_table
             .new_key(unify_key::RegionVidKey { min_vid: vid });
@@ -450,44 +443,14 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         return vid;
     }
 
-    /// Returns the origin for the given variable.
-    pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
-        self.var_origins[vid].clone()
+    /// Returns the universe for the given variable.
+    pub fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
+        self.var_infos[vid].universe
     }
 
-    /// Creates a new skolemized region. Skolemized regions are fresh
-    /// regions used when performing higher-ranked computations. They
-    /// must be used in a very particular way and are never supposed
-    /// to "escape" out into error messages or the code at large.
-    ///
-    /// The idea is to always create a snapshot. Skolemized regions
-    /// can be created in the context of this snapshot, but before the
-    /// snapshot is committed or rolled back, they must be popped
-    /// (using `pop_skolemized_regions`), so that their numbers can be
-    /// recycled. Normally you don't have to think about this: you use
-    /// the APIs in `higher_ranked/mod.rs`, such as
-    /// `skolemize_late_bound_regions` and `plug_leaks`, which will
-    /// guide you on this path (ensure that the `SkolemizationMap` is
-    /// consumed and you are good). For more info on how skolemization
-    /// for HRTBs works, see the [rustc guide].
-    ///
-    /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
-    ///
-    /// The `snapshot` argument to this function is not really used;
-    /// it's just there to make it explicit which snapshot bounds the
-    /// skolemized region that results. It should always be the top-most snapshot.
-    pub fn push_skolemized(
-        &mut self,
-        tcx: TyCtxt<'_, '_, 'tcx>,
-        br: ty::BoundRegion,
-        snapshot: &RegionSnapshot,
-    ) -> Region<'tcx> {
-        assert!(self.in_snapshot());
-        assert!(self.undo_log[snapshot.length] == OpenSnapshot);
-
-        let sc = self.skolemization_count;
-        self.skolemization_count = sc + 1;
-        tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br))
+    /// Returns the origin for the given variable.
+    pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
+        self.var_infos[vid].origin
     }
 
     /// Removes all the edges to/from the skolemized regions that are
@@ -496,7 +459,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     /// created in that time.
     pub fn pop_skolemized(
         &mut self,
-        _tcx: TyCtxt<'_, '_, 'tcx>,
+        skolemization_count: ty::UniverseIndex,
         skols: &FxHashSet<ty::Region<'tcx>>,
         snapshot: &RegionSnapshot,
     ) {
@@ -505,36 +468,28 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         assert!(self.in_snapshot());
         assert!(self.undo_log[snapshot.length] == OpenSnapshot);
         assert!(
-            self.skolemization_count as usize >= skols.len(),
+            skolemization_count.as_usize() >= skols.len(),
             "popping more skolemized variables than actually exist, \
-             sc now = {}, skols.len = {}",
-            self.skolemization_count,
+             sc now = {:?}, skols.len = {:?}",
+            skolemization_count,
             skols.len()
         );
 
-        let last_to_pop = self.skolemization_count;
-        let first_to_pop = last_to_pop - (skols.len() as u32);
+        let last_to_pop = skolemization_count.subuniverse();
+        let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - skols.len() as u32);
 
-        assert!(
-            first_to_pop >= snapshot.skolemization_count,
-            "popping more regions than snapshot contains, \
-             sc now = {}, sc then = {}, skols.len = {}",
-            self.skolemization_count,
-            snapshot.skolemization_count,
-            skols.len()
-        );
         debug_assert! {
             skols.iter()
                  .all(|&k| match *k {
-                     ty::ReSkolemized(index, _) =>
-                         index.index >= first_to_pop &&
-                         index.index < last_to_pop,
+                     ty::ReSkolemized(universe, _) =>
+                         universe >= first_to_pop &&
+                         universe < last_to_pop,
                      _ =>
                          false
                  }),
-            "invalid skolemization keys or keys out of range ({}..{}): {:?}",
-            snapshot.skolemization_count,
-            self.skolemization_count,
+            "invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}",
+            first_to_pop,
+            last_to_pop,
             skols
         }
 
@@ -551,7 +506,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
             self.rollback_undo_entry(undo_entry);
         }
 
-        self.skolemization_count = snapshot.skolemization_count;
         return;
 
         fn kill_constraint<'tcx>(
@@ -805,7 +759,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         if let Some(&c) = self.combine_map(t).get(&vars) {
             return tcx.mk_region(ReVar(c));
         }
-        let c = self.new_region_var(MiscVariable(origin.span()));
+        let a_universe = self.universe(a);
+        let b_universe = self.universe(b);
+        let c_universe = cmp::max(a_universe, b_universe);
+        let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
         self.combine_map(t).insert(vars, c);
         if self.in_snapshot() {
             self.undo_log.push(AddCombination(t, vars));
@@ -821,6 +778,24 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         new_r
     }
 
+    fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
+        match *region {
+            ty::ReScope(..) |
+            ty::ReStatic |
+            ty::ReEmpty |
+            ty::ReErased |
+            ty::ReFree(..) |
+            ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
+            ty::ReSkolemized(universe, _) => universe,
+            ty::ReClosureBound(vid) |
+            ty::ReVar(vid) => self.var_universe(vid),
+            ty::ReLateBound(..) =>
+                bug!("universe(): encountered bound region {:?}", region),
+            ty::ReCanonical(..) =>
+                bug!("region_universe(): encountered canonical region {:?}", region),
+        }
+    }
+
     pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
         self.undo_log[mark.length..]
             .iter()
@@ -865,12 +840,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
 
 impl fmt::Debug for RegionSnapshot {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(
-            f,
-            "RegionSnapshot(length={},skolemization={})",
-            self.length,
-            self.skolemization_count
-        )
+        write!(f, "RegionSnapshot(length={})", self.length)
     }
 }
 
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index 5e96f4eb576..d40e1b3760f 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -78,10 +78,12 @@ struct TypeVariableData {
 #[derive(Copy, Clone, Debug)]
 pub enum TypeVariableValue<'tcx> {
     Known { value: Ty<'tcx> },
-    Unknown,
+    Unknown { universe: ty::UniverseIndex },
 }
 
 impl<'tcx> TypeVariableValue<'tcx> {
+    /// If this value is known, returns the type it is known to be.
+    /// Otherwise, `None`.
     pub fn known(&self) -> Option<Ty<'tcx>> {
         match *self {
             TypeVariableValue::Unknown { .. } => None,
@@ -181,10 +183,11 @@ impl<'tcx> TypeVariableTable<'tcx> {
     ///   The code in this module doesn't care, but it can be useful
     ///   for improving error messages.
     pub fn new_var(&mut self,
+                   universe: ty::UniverseIndex,
                    diverging: bool,
                    origin: TypeVariableOrigin)
                    -> ty::TyVid {
-        let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown);
+        let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown { universe });
 
         let sub_key = self.sub_relations.new_key(());
         assert_eq!(eq_key.vid, sub_key);
@@ -437,7 +440,16 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
             (&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2),
 
             // If both sides are *unknown*, it hardly matters, does it?
-            (&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1),
+            (&TypeVariableValue::Unknown { universe: universe1 },
+             &TypeVariableValue::Unknown { universe: universe2 }) =>  {
+                // If we unify two unbound variables, ?T and ?U, then whatever
+                // value they wind up taking (which must be the same value) must
+                // be nameable by both universes. Therefore, the resulting
+                // universe is the minimum of the two universes, because that is
+                // the one which contains the fewest names in scope.
+                let universe = cmp::min(universe1, universe2);
+                Ok(TypeVariableValue::Unknown { universe })
+            }
         }
     }
 }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index f85d0a9bf0c..879d38c4894 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -45,8 +45,8 @@
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
-#![feature(dyn_trait)]
 #![feature(entry_or_default)]
+#![cfg_attr(stage0, feature(dyn_trait))]
 #![feature(from_ref)]
 #![feature(fs_read_write)]
 #![cfg_attr(windows, feature(libc))]
@@ -58,6 +58,7 @@
 #![feature(nonzero)]
 #![feature(proc_macro_internals)]
 #![feature(quote)]
+#![feature(optin_builtin_traits)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
@@ -68,7 +69,7 @@
 #![feature(trusted_len)]
 #![feature(catch_expr)]
 #![feature(test)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 
 #![recursion_limit="512"]
 
@@ -84,7 +85,6 @@ extern crate libc;
 extern crate rustc_target;
 #[macro_use] extern crate rustc_data_structures;
 extern crate serialize;
-extern crate rustc_const_math;
 extern crate rustc_errors as errors;
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index e8b536d5267..d158f52c643 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -198,7 +198,7 @@ impl<'a> LintLevelsBuilder<'a> {
                       "malformed lint attribute");
         };
         for attr in attrs {
-            let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) {
+            let level = match Level::from_str(&attr.name().as_str()) {
                 None => continue,
                 Some(lvl) => lvl,
             };
@@ -221,7 +221,7 @@ impl<'a> LintLevelsBuilder<'a> {
                         continue
                     }
                 };
-                let name = word.ident.name;
+                let name = word.name();
                 match store.check_lint_name(&name.as_str()) {
                     CheckLintNameResult::Ok(ids) => {
                         let src = LintSource::Node(name, li.span);
@@ -260,7 +260,7 @@ impl<'a> LintLevelsBuilder<'a> {
                                                 Some(li.span.into()),
                                                 &msg);
                         if name.as_str().chars().any(|c| c.is_uppercase()) {
-                            let name_lower = name.as_str().to_lowercase();
+                            let name_lower = name.as_str().to_lowercase().to_string();
                             if let CheckLintNameResult::NoLint =
                                     store.check_lint_name(&name_lower) {
                                 db.emit();
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 0d4fd99995f..d6c6f9dc0f6 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -507,7 +507,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
 
         let explanation = if lint_id == LintId::of(::lint::builtin::UNSTABLE_NAME_COLLISION) {
             "once this method is added to the standard library, \
-             there will be ambiguity here, which will cause a hard error!"
+             the ambiguity may cause an error or change in behavior!"
                 .to_owned()
         } else if let Some(edition) = future_incompatible.edition {
             format!("{} in the {} edition!", STANDARD_MESSAGE, edition)
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index 19a7576b7ce..0ecab50dda2 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -11,7 +11,6 @@
 use hir::def_id::DefId;
 use ty::{self, TyCtxt, layout};
 use ty::subst::Substs;
-use rustc_const_math::*;
 use mir::interpret::{Value, PrimVal};
 use errors::DiagnosticBuilder;
 
@@ -62,7 +61,6 @@ pub enum ErrKind<'tcx> {
     UnimplementedConstVal(&'static str),
     IndexOutOfBounds { len: u64, index: u64 },
 
-    Math(ConstMathErr),
     LayoutError(layout::LayoutError<'tcx>),
 
     TypeckError,
@@ -76,15 +74,6 @@ pub struct FrameInfo {
     pub location: String,
 }
 
-impl<'tcx> From<ConstMathErr> for ErrKind<'tcx> {
-    fn from(err: ConstMathErr) -> ErrKind<'tcx> {
-        match err {
-            ConstMathErr::UnsignedNegation => ErrKind::TypeckError,
-            _ => ErrKind::Math(err)
-        }
-    }
-}
-
 #[derive(Clone, Debug)]
 pub enum ConstEvalErrDescription<'a, 'tcx: 'a> {
     Simple(Cow<'a, str>),
@@ -122,7 +111,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
                         len, index)
             }
 
-            Math(ref err) => Simple(err.description().into_cow()),
             LayoutError(ref err) => Simple(err.to_string().into_cow()),
 
             TypeckError => simple!("type-checking failed"),
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 2cc5a4a8fe6..725fcf1e646 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -28,6 +28,7 @@ use ty::{self, TyCtxt, adjustment};
 
 use hir::{self, PatKind};
 use rustc_data_structures::sync::Lrc;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax_pos::Span;
@@ -44,7 +45,7 @@ pub trait Delegate<'tcx> {
     fn consume(&mut self,
                consume_id: ast::NodeId,
                consume_span: Span,
-               cmt: mc::cmt<'tcx>,
+               cmt: &mc::cmt_<'tcx>,
                mode: ConsumeMode);
 
     // The value found at `cmt` has been determined to match the
@@ -61,14 +62,14 @@ pub trait Delegate<'tcx> {
     // called on a subpart of an input passed to `matched_pat).
     fn matched_pat(&mut self,
                    matched_pat: &hir::Pat,
-                   cmt: mc::cmt<'tcx>,
+                   cmt: &mc::cmt_<'tcx>,
                    mode: MatchMode);
 
     // The value found at `cmt` is either copied or moved via the
     // pattern binding `consume_pat`, depending on mode.
     fn consume_pat(&mut self,
                    consume_pat: &hir::Pat,
-                   cmt: mc::cmt<'tcx>,
+                   cmt: &mc::cmt_<'tcx>,
                    mode: ConsumeMode);
 
     // The value found at `borrow` is being borrowed at the point
@@ -76,7 +77,7 @@ pub trait Delegate<'tcx> {
     fn borrow(&mut self,
               borrow_id: ast::NodeId,
               borrow_span: Span,
-              cmt: mc::cmt<'tcx>,
+              cmt: &mc::cmt_<'tcx>,
               loan_region: ty::Region<'tcx>,
               bk: ty::BorrowKind,
               loan_cause: LoanCause);
@@ -90,7 +91,7 @@ pub trait Delegate<'tcx> {
     fn mutate(&mut self,
               assignment_id: ast::NodeId,
               assignment_span: Span,
-              assignee_cmt: mc::cmt<'tcx>,
+              assignee_cmt: &mc::cmt_<'tcx>,
               mode: MutateMode);
 }
 
@@ -316,11 +317,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
 
             let fn_body_scope_r =
                 self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id)));
-            let arg_cmt = self.mc.cat_rvalue(
+            let arg_cmt = Rc::new(self.mc.cat_rvalue(
                 arg.id,
                 arg.pat.span,
                 fn_body_scope_r, // Args live only as long as the fn body.
-                arg_ty);
+                arg_ty));
 
             self.walk_irrefutable_pat(arg_cmt, &arg.pat);
         }
@@ -335,11 +336,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     fn delegate_consume(&mut self,
                         consume_id: ast::NodeId,
                         consume_span: Span,
-                        cmt: mc::cmt<'tcx>) {
+                        cmt: &mc::cmt_<'tcx>) {
         debug!("delegate_consume(consume_id={}, cmt={:?})",
                consume_id, cmt);
 
-        let mode = copy_or_move(&self.mc, self.param_env, &cmt, DirectRefMove);
+        let mode = copy_or_move(&self.mc, self.param_env, cmt, DirectRefMove);
         self.delegate.consume(consume_id, consume_span, cmt, mode);
     }
 
@@ -353,7 +354,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         debug!("consume_expr(expr={:?})", expr);
 
         let cmt = return_if_err!(self.mc.cat_expr(expr));
-        self.delegate_consume(expr.id, expr.span, cmt);
+        self.delegate_consume(expr.id, expr.span, &cmt);
         self.walk_expr(expr);
     }
 
@@ -362,7 +363,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                    expr: &hir::Expr,
                    mode: MutateMode) {
         let cmt = return_if_err!(self.mc.cat_expr(expr));
-        self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode);
+        self.delegate.mutate(assignment_expr.id, assignment_expr.span, &cmt, mode);
         self.walk_expr(expr);
     }
 
@@ -375,7 +376,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                expr, r, bk);
 
         let cmt = return_if_err!(self.mc.cat_expr(expr));
-        self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
+        self.delegate.borrow(expr.id, expr.span, &cmt, r, bk, cause);
 
         self.walk_expr(expr)
     }
@@ -435,7 +436,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
             }
 
             hir::ExprMatch(ref discr, ref arms, _) => {
-                let discr_cmt = return_if_err!(self.mc.cat_expr(&discr));
+                let discr_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&discr)));
                 let r = self.tcx().types.re_empty;
                 self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant);
 
@@ -619,7 +620,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 // "assigns", which is handled by
                 // `walk_pat`:
                 self.walk_expr(&expr);
-                let init_cmt = return_if_err!(self.mc.cat_expr(&expr));
+                let init_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&expr)));
                 self.walk_irrefutable_pat(init_cmt, &local.pat);
             }
         }
@@ -652,7 +653,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
             None => { return; }
         };
 
-        let with_cmt = return_if_err!(self.mc.cat_expr(&with_expr));
+        let with_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&with_expr)));
 
         // Select just those fields of the `with`
         // expression that will actually be used
@@ -671,7 +672,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                             with_field.name,
                             with_field.ty(self.tcx(), substs)
                         );
-                        self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
+                        self.delegate_consume(with_expr.id, with_expr.span, &cmt_field);
                     }
                 }
             }
@@ -710,7 +711,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 adjustment::Adjust::Unsize => {
                     // Creating a closure/fn-pointer or unsizing consumes
                     // the input and stores it into the resulting rvalue.
-                    self.delegate_consume(expr.id, expr.span, cmt.clone());
+                    self.delegate_consume(expr.id, expr.span, &cmt);
                 }
 
                 adjustment::Adjust::Deref(None) => {}
@@ -722,12 +723,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 // this is an autoref of `x`.
                 adjustment::Adjust::Deref(Some(ref deref)) => {
                     let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
-                    self.delegate.borrow(expr.id, expr.span, cmt.clone(),
-                                         deref.region, bk, AutoRef);
+                    self.delegate.borrow(expr.id, expr.span, &cmt, deref.region, bk, AutoRef);
                 }
 
                 adjustment::Adjust::Borrow(ref autoref) => {
-                    self.walk_autoref(expr, cmt.clone(), autoref);
+                    self.walk_autoref(expr, &cmt, autoref);
                 }
             }
             cmt = return_if_err!(self.mc.cat_expr_adjusted(expr, cmt, &adjustment));
@@ -739,7 +739,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     /// after all relevant autoderefs have occurred.
     fn walk_autoref(&mut self,
                     expr: &hir::Expr,
-                    cmt_base: mc::cmt<'tcx>,
+                    cmt_base: &mc::cmt_<'tcx>,
                     autoref: &adjustment::AutoBorrow<'tcx>) {
         debug!("walk_autoref(expr.id={} cmt_base={:?} autoref={:?})",
                expr.id,
@@ -852,7 +852,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
                 let def = Def::Local(canonical_id);
-                if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) {
+                if let Ok(ref binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) {
                     delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
                 }
 
@@ -861,13 +861,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                     ty::BindByReference(m) => {
                         if let ty::TyRef(r, _) = pat_ty.sty {
                             let bk = ty::BorrowKind::from_mutbl(m);
-                            delegate.borrow(pat.id, pat.span, cmt_pat, r, bk, RefBinding);
+                            delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding);
                         }
                     }
                     ty::BindByValue(..) => {
                         let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove);
                         debug!("walk_pat binding consuming pat");
-                        delegate.consume_pat(pat, cmt_pat, mode);
+                        delegate.consume_pat(pat, &cmt_pat, mode);
                     }
                 }
             }
@@ -891,12 +891,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                     let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
 
                     debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
-                    delegate.matched_pat(pat, downcast_cmt, match_mode);
+                    delegate.matched_pat(pat, &downcast_cmt, match_mode);
                 }
                 Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
                 Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
                     debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
-                    delegate.matched_pat(pat, cmt_pat, match_mode);
+                    delegate.matched_pat(pat, &cmt_pat, match_mode);
                 }
                 _ => {}
             }
@@ -924,12 +924,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                                                 self.param_env,
                                                 &cmt_var,
                                                 CaptureMove);
-                        self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
+                        self.delegate.consume(closure_expr.id, freevar.span, &cmt_var, mode);
                     }
                     ty::UpvarCapture::ByRef(upvar_borrow) => {
                         self.delegate.borrow(closure_expr.id,
                                              fn_decl_span,
-                                             cmt_var,
+                                             &cmt_var,
                                              upvar_borrow.region,
                                              upvar_borrow.kind,
                                              ClosureCapture(freevar.span));
@@ -943,7 +943,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                         closure_id: ast::NodeId,
                         closure_span: Span,
                         upvar: &hir::Freevar)
-                        -> mc::McResult<mc::cmt<'tcx>> {
+                        -> mc::McResult<mc::cmt_<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
         let var_hir_id = self.tcx().hir.node_to_hir_id(upvar.var_id());
@@ -954,7 +954,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
 
 fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
                                 param_env: ty::ParamEnv<'tcx>,
-                                cmt: &mc::cmt<'tcx>,
+                                cmt: &mc::cmt_<'tcx>,
                                 move_reason: MoveReason)
                                 -> ConsumeMode
 {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 17c114bc3b3..d1a46f5f155 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -111,6 +111,7 @@ use ty::{self, TyCtxt};
 use lint;
 use util::nodemap::{NodeMap, NodeSet};
 
+use std::collections::VecDeque;
 use std::{fmt, usize};
 use std::io::prelude::*;
 use std::io;
@@ -412,18 +413,43 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
 }
 
 fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
-    for pat in &arm.pats {
-        // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`)
+    for mut pat in &arm.pats {
+        // For struct patterns, take note of which fields used shorthand
+        // (`x` rather than `x: x`).
         //
-        // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased
-        // out in favor of `HirId`s; however, we need to match the signature of `each_binding`,
-        // which uses `NodeIds`.
+        // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be
+        // phased out in favor of `HirId`s; however, we need to match the signature of
+        // `each_binding`, which uses `NodeIds`.
         let mut shorthand_field_ids = NodeSet();
-        if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
-            for field in fields {
-                if field.node.is_shorthand {
-                    shorthand_field_ids.insert(field.node.pat.id);
+        let mut pats = VecDeque::new();
+        pats.push_back(pat);
+        while let Some(pat) = pats.pop_front() {
+            use hir::PatKind::*;
+            match pat.node {
+                Binding(_, _, _, ref inner_pat) => {
+                    pats.extend(inner_pat.iter());
                 }
+                Struct(_, ref fields, _) => {
+                    for field in fields {
+                        if field.node.is_shorthand {
+                            shorthand_field_ids.insert(field.node.pat.id);
+                        }
+                    }
+                }
+                Ref(ref inner_pat, _) |
+                Box(ref inner_pat) => {
+                    pats.push_back(inner_pat);
+                }
+                TupleStruct(_, ref inner_pats, _) |
+                Tuple(ref inner_pats, _) => {
+                    pats.extend(inner_pats.iter());
+                }
+                Slice(ref pre_pats, ref inner_pat, ref post_pats) => {
+                    pats.extend(pre_pats.iter());
+                    pats.extend(inner_pat.iter());
+                    pats.extend(post_pats.iter());
+                }
+                _ => {}
             }
         }
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 6f41f07dce8..f40a41cd299 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -572,13 +572,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         Ok(ret_ty)
     }
 
-    pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
+    pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt_<'tcx>> {
         // This recursion helper avoids going through *too many*
         // adjustments, since *only* non-overloaded deref recurses.
         fn helper<'a, 'gcx, 'tcx>(mc: &MemCategorizationContext<'a, 'gcx, 'tcx>,
                                   expr: &hir::Expr,
                                   adjustments: &[adjustment::Adjustment<'tcx>])
-                                   -> McResult<cmt<'tcx>> {
+                                   -> McResult<cmt_<'tcx>> {
             match adjustments.split_last() {
                 None => mc.cat_expr_unadjusted(expr),
                 Some((adjustment, previous)) => {
@@ -591,24 +591,24 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     }
 
     pub fn cat_expr_adjusted(&self, expr: &hir::Expr,
-                             previous: cmt<'tcx>,
+                             previous: cmt_<'tcx>,
                              adjustment: &adjustment::Adjustment<'tcx>)
-                             -> McResult<cmt<'tcx>> {
+                             -> McResult<cmt_<'tcx>> {
         self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
     }
 
     fn cat_expr_adjusted_with<F>(&self, expr: &hir::Expr,
                                  previous: F,
                                  adjustment: &adjustment::Adjustment<'tcx>)
-                                 -> McResult<cmt<'tcx>>
-        where F: FnOnce() -> McResult<cmt<'tcx>>
+                                 -> McResult<cmt_<'tcx>>
+        where F: FnOnce() -> McResult<cmt_<'tcx>>
     {
         debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
         let target = self.resolve_type_vars_if_possible(&adjustment.target);
         match adjustment.kind {
             adjustment::Adjust::Deref(overloaded) => {
                 // Equivalent to *expr or something similar.
-                let base = if let Some(deref) = overloaded {
+                let base = Rc::new(if let Some(deref) = overloaded {
                     let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut {
                         ty: target,
                         mutbl: deref.mutbl,
@@ -616,7 +616,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                     self.cat_rvalue_node(expr.id, expr.span, ref_ty)
                 } else {
                     previous()?
-                };
+                });
                 self.cat_deref(expr, base, false)
             }
 
@@ -633,7 +633,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
+    pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt_<'tcx>> {
         debug!("cat_expr: id={} expr={:?}", expr.id, expr);
 
         let expr_ty = self.expr_ty(expr)?;
@@ -642,13 +642,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             if self.tables.is_method_call(expr) {
                 self.cat_overloaded_place(expr, e_base, false)
             } else {
-                let base_cmt = self.cat_expr(&e_base)?;
+                let base_cmt = Rc::new(self.cat_expr(&e_base)?);
                 self.cat_deref(expr, base_cmt, false)
             }
           }
 
           hir::ExprField(ref base, f_name) => {
-            let base_cmt = self.cat_expr(&base)?;
+            let base_cmt = Rc::new(self.cat_expr(&base)?);
             debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
                    expr.id,
                    expr,
@@ -666,7 +666,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 // dereferencing.
                 self.cat_overloaded_place(expr, base, true)
             } else {
-                let base_cmt = self.cat_expr(&base)?;
+                let base_cmt = Rc::new(self.cat_expr(&base)?);
                 self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
             }
           }
@@ -701,7 +701,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                    span: Span,
                    expr_ty: Ty<'tcx>,
                    def: Def)
-                   -> McResult<cmt<'tcx>> {
+                   -> McResult<cmt_<'tcx>> {
         debug!("cat_def: id={} expr={:?} def={:?}",
                id, expr_ty, def);
 
@@ -718,14 +718,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                     return Ok(self.cat_rvalue_node(id, span, expr_ty));
                 }
             }
-              Ok(Rc::new(cmt_ {
+              Ok(cmt_ {
                   id:id,
                   span:span,
                   cat:Categorization::StaticItem,
                   mutbl: if mutbl { McDeclared } else { McImmutable},
                   ty:expr_ty,
                   note: NoteNone
-              }))
+              })
           }
 
           Def::Upvar(var_id, _, fn_node_id) => {
@@ -733,14 +733,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
           }
 
           Def::Local(vid) => {
-            Ok(Rc::new(cmt_ {
+            Ok(cmt_ {
                 id,
                 span,
                 cat: Categorization::Local(vid),
                 mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
                 ty: expr_ty,
                 note: NoteNone
-            }))
+            })
           }
 
           def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
@@ -754,7 +754,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                  span: Span,
                  var_id: ast::NodeId,
                  fn_node_id: ast::NodeId)
-                 -> McResult<cmt<'tcx>>
+                 -> McResult<cmt_<'tcx>>
     {
         let fn_hir_id = self.tcx.hir.node_to_hir_id(fn_node_id);
 
@@ -861,7 +861,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
         };
 
-        let ret = Rc::new(cmt_result);
+        let ret = cmt_result;
         debug!("cat_upvar ret={:?}", ret);
         Ok(ret)
     }
@@ -938,7 +938,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                            id: ast::NodeId,
                            span: Span,
                            expr_ty: Ty<'tcx>)
-                           -> cmt<'tcx> {
+                           -> cmt_<'tcx> {
         let hir_id = self.tcx.hir.node_to_hir_id(id);
         let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id))
                                                             .unwrap_or(false);
@@ -966,15 +966,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                       cmt_id: ast::NodeId,
                       span: Span,
                       temp_scope: ty::Region<'tcx>,
-                      expr_ty: Ty<'tcx>) -> cmt<'tcx> {
-        let ret = Rc::new(cmt_ {
+                      expr_ty: Ty<'tcx>) -> cmt_<'tcx> {
+        let ret = cmt_ {
             id:cmt_id,
             span:span,
             cat:Categorization::Rvalue(temp_scope),
             mutbl:McDeclared,
             ty:expr_ty,
             note: NoteNone
-        });
+        };
         debug!("cat_rvalue ret {:?}", ret);
         ret
     }
@@ -985,15 +985,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                                  f_index: usize,
                                  f_name: Name,
                                  f_ty: Ty<'tcx>)
-                                 -> cmt<'tcx> {
-        let ret = Rc::new(cmt_ {
+                                 -> cmt_<'tcx> {
+        let ret = cmt_ {
             id: node.id(),
             span: node.span(),
             mutbl: base_cmt.mutbl.inherit(),
             cat: Categorization::Interior(base_cmt, InteriorField(FieldIndex(f_index, f_name))),
             ty: f_ty,
             note: NoteNone
-        });
+        };
         debug!("cat_field ret {:?}", ret);
         ret
     }
@@ -1002,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                              expr: &hir::Expr,
                              base: &hir::Expr,
                              implicit: bool)
-                             -> McResult<cmt<'tcx>> {
+                             -> McResult<cmt_<'tcx>> {
         debug!("cat_overloaded_place: implicit={}", implicit);
 
         // Reconstruct the output assuming it's a reference with the
@@ -1022,7 +1022,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             mutbl,
         });
 
-        let base_cmt = self.cat_rvalue_node(expr.id, expr.span, ref_ty);
+        let base_cmt = Rc::new(self.cat_rvalue_node(expr.id, expr.span, ref_ty));
         self.cat_deref(expr, base_cmt, implicit)
     }
 
@@ -1030,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                                  node: &N,
                                  base_cmt: cmt<'tcx>,
                                  implicit: bool)
-                                 -> McResult<cmt<'tcx>> {
+                                 -> McResult<cmt_<'tcx>> {
         debug!("cat_deref: base_cmt={:?}", base_cmt);
 
         let base_cmt_ty = base_cmt.ty;
@@ -1052,7 +1052,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
             ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
         };
-        let ret = Rc::new(cmt_ {
+        let ret = cmt_ {
             id: node.id(),
             span: node.span(),
             // For unique ptrs, we inherit mutability from the owning reference.
@@ -1060,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             cat: Categorization::Deref(base_cmt, ptr),
             ty: deref_ty,
             note: NoteNone
-        });
+        };
         debug!("cat_deref ret {:?}", ret);
         Ok(ret)
     }
@@ -1070,7 +1070,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                              base_cmt: cmt<'tcx>,
                              element_ty: Ty<'tcx>,
                              context: InteriorOffsetKind)
-                             -> McResult<cmt<'tcx>> {
+                             -> McResult<cmt_<'tcx>> {
         //! Creates a cmt for an indexing operation (`[]`).
         //!
         //! One subtle aspect of indexing that may not be
@@ -1089,8 +1089,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         //! - `base_cmt`: the cmt of `elt`
 
         let interior_elem = InteriorElement(context);
-        let ret =
-            self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem);
+        let ret = self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem);
         debug!("cat_index ret {:?}", ret);
         return Ok(ret);
     }
@@ -1100,15 +1099,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                                         base_cmt: cmt<'tcx>,
                                         interior_ty: Ty<'tcx>,
                                         interior: InteriorKind)
-                                        -> cmt<'tcx> {
-        let ret = Rc::new(cmt_ {
+                                        -> cmt_<'tcx> {
+        let ret = cmt_ {
             id: node.id(),
             span: node.span(),
             mutbl: base_cmt.mutbl.inherit(),
             cat: Categorization::Interior(base_cmt, interior),
             ty: interior_ty,
             note: NoteNone
-        });
+        };
         debug!("cat_imm_interior ret={:?}", ret);
         ret
     }
@@ -1232,7 +1231,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                         .get(pat.hir_id)
                         .map(|v| v.len())
                         .unwrap_or(0) {
-            cmt = self.cat_deref(pat, cmt, true /* implicit */)?;
+            cmt = Rc::new(self.cat_deref(pat, cmt, true /* implicit */)?);
         }
         let cmt = cmt; // lose mutability
 
@@ -1279,7 +1278,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
                 let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
                 let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
-                let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
+                let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
                 self.cat_pattern_(subcmt, &subpat, op)?;
             }
           }
@@ -1302,7 +1301,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             for fp in field_pats {
                 let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
                 let f_index = self.tcx.field_index(fp.node.id, self.tables);
-                let cmt_field = self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty);
+                let cmt_field =
+                    Rc::new(self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty));
                 self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
             }
           }
@@ -1320,7 +1320,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
                 let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
                 let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
-                let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
+                let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
                 self.cat_pattern_(subcmt, &subpat, op)?;
             }
           }
@@ -1329,7 +1329,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             // box p1, &p1, &mut p1.  we can ignore the mutability of
             // PatKind::Ref since that information is already contained
             // in the type.
-            let subcmt = self.cat_deref(pat, cmt, false)?;
+            let subcmt = Rc::new(self.cat_deref(pat, cmt, false)?);
             self.cat_pattern_(subcmt, &subpat, op)?;
           }
 
@@ -1342,7 +1342,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 }
             };
             let context = InteriorOffsetKind::Pattern;
-            let elt_cmt = self.cat_index(pat, cmt, element_ty, context)?;
+            let elt_cmt = Rc::new(self.cat_index(pat, cmt, element_ty, context)?);
             for before_pat in before {
                 self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
             }
@@ -1379,7 +1379,7 @@ pub enum AliasableReason {
 }
 
 impl<'tcx> cmt_<'tcx> {
-    pub fn guarantor(&self) -> cmt<'tcx> {
+    pub fn guarantor(&self) -> cmt_<'tcx> {
         //! Returns `self` after stripping away any derefs or
         //! interior content. The return value is basically the `cmt` which
         //! determines how long the value in `self` remains live.
@@ -1392,7 +1392,7 @@ impl<'tcx> cmt_<'tcx> {
             Categorization::Deref(_, BorrowedPtr(..)) |
             Categorization::Deref(_, Implicit(..)) |
             Categorization::Upvar(..) => {
-                Rc::new((*self).clone())
+                (*self).clone()
             }
             Categorization::Downcast(ref b, _) |
             Categorization::Interior(ref b, _) |
@@ -1442,16 +1442,17 @@ impl<'tcx> cmt_<'tcx> {
         }
     }
 
-    // Digs down through one or two layers of deref and grabs the cmt
-    // for the upvar if a note indicates there is one.
-    pub fn upvar(&self) -> Option<cmt<'tcx>> {
+    // Digs down through one or two layers of deref and grabs the
+    // Categorization of the cmt for the upvar if a note indicates there is
+    // one.
+    pub fn upvar_cat(&self) -> Option<&Categorization<'tcx>> {
         match self.note {
             NoteClosureEnv(..) | NoteUpvarRef(..) => {
                 Some(match self.cat {
                     Categorization::Deref(ref inner, _) => {
                         match inner.cat {
-                            Categorization::Deref(ref inner, _) => inner.clone(),
-                            Categorization::Upvar(..) => inner.clone(),
+                            Categorization::Deref(ref inner, _) => &inner.cat,
+                            Categorization::Upvar(..) => &inner.cat,
                             _ => bug!()
                         }
                     }
@@ -1462,7 +1463,6 @@ impl<'tcx> cmt_<'tcx> {
         }
     }
 
-
     pub fn descriptive_string(&self, tcx: TyCtxt) -> String {
         match self.cat {
             Categorization::StaticItem => {
@@ -1479,8 +1479,7 @@ impl<'tcx> cmt_<'tcx> {
                 }
             }
             Categorization::Deref(_, pk) => {
-                let upvar = self.upvar();
-                match upvar.as_ref().map(|i| &i.cat) {
+                match self.upvar_cat() {
                     Some(&Categorization::Upvar(ref var)) => {
                         var.to_string()
                     }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 5f4efbeeaa8..bfc9ff6660d 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -690,21 +690,22 @@ impl<'tcx> ScopeTree {
         // the start. So this algorithm is faster.
         let mut ma = Some(scope_a);
         let mut mb = Some(scope_b);
-        let mut seen: SmallVec<[Scope; 32]> = SmallVec::new();
+        let mut seen_a: SmallVec<[Scope; 32]> = SmallVec::new();
+        let mut seen_b: SmallVec<[Scope; 32]> = SmallVec::new();
         loop {
             if let Some(a) = ma {
-                if seen.iter().position(|s| *s == a).is_some() {
+                if seen_b.iter().position(|s| *s == a).is_some() {
                     return a;
                 }
-                seen.push(a);
+                seen_a.push(a);
                 ma = self.parent_map.get(&a).map(|s| *s);
             }
 
             if let Some(b) = mb {
-                if seen.iter().position(|s| *s == b).is_some() {
+                if seen_a.iter().position(|s| *s == b).is_some() {
                     return b;
                 }
-                seen.push(b);
+                seen_b.push(b);
                 mb = self.parent_map.get(&b).map(|s| *s);
             }
 
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 328b2db2b58..279908d2b67 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -205,7 +205,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
         } else {
             // Emit errors for non-staged-api crates.
             for attr in attrs {
-                let tag = unwrap_or!(attr.name(), continue);
+                let tag = attr.name();
                 if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
                     attr::mark_used(attr);
                     self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 1ed5a22257c..41ba526b73f 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -68,7 +68,7 @@ fn calculate_predecessors(mir: &Mir) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
     let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
     for (bb, data) in mir.basic_blocks().iter_enumerated() {
         if let Some(ref term) = data.terminator {
-            for &tgt in term.successors().iter() {
+            for &tgt in term.successors() {
                 result[tgt].push(bb);
             }
         }
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index b919f4d15a8..1e1d50c3fc0 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -1,4 +1,3 @@
-use std::error::Error;
 use std::{fmt, env};
 
 use mir;
@@ -8,18 +7,16 @@ use super::{
     MemoryPointer, Lock, AccessKind
 };
 
-use rustc_const_math::ConstMathErr;
-use syntax::codemap::Span;
 use backtrace::Backtrace;
 
 #[derive(Debug, Clone)]
 pub struct EvalError<'tcx> {
-    pub kind: EvalErrorKind<'tcx>,
+    pub kind: EvalErrorKind<'tcx, u64>,
     pub backtrace: Option<Backtrace>,
 }
 
-impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
-    fn from(kind: EvalErrorKind<'tcx>) -> Self {
+impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
+    fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
         let backtrace = match env::var("MIRI_BACKTRACE") {
             Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
             _ => None
@@ -31,8 +28,10 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
     }
 }
 
-#[derive(Debug, Clone)]
-pub enum EvalErrorKind<'tcx> {
+pub type AssertMessage<'tcx> = EvalErrorKind<'tcx, mir::Operand<'tcx>>;
+
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub enum EvalErrorKind<'tcx, O> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant
     MachineError(String),
@@ -60,10 +59,12 @@ pub enum EvalErrorKind<'tcx> {
     Unimplemented(String),
     DerefFunctionPointer,
     ExecuteMemory,
-    ArrayIndexOutOfBounds(Span, u64, u64),
-    Math(Span, ConstMathErr),
+    BoundsCheck { len: O, index: O },
+    Overflow(mir::BinOp),
+    OverflowNeg,
+    DivisionByZero,
+    RemainderByZero,
     Intrinsic(String),
-    OverflowingMath,
     InvalidChar(u128),
     StackFrameLimitReached,
     OutOfTls,
@@ -121,14 +122,16 @@ pub enum EvalErrorKind<'tcx> {
     /// Cannot compute this constant because it depends on another one
     /// which already produced an error
     ReferencedConstant,
+    GeneratorResumedAfterReturn,
+    GeneratorResumedAfterPanic,
 }
 
 pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
 
-impl<'tcx> Error for EvalError<'tcx> {
-    fn description(&self) -> &str {
+impl<'tcx, O> EvalErrorKind<'tcx, O> {
+    pub fn description(&self) -> &str {
         use self::EvalErrorKind::*;
-        match self.kind {
+        match *self {
             MachineError(ref inner) => inner,
             FunctionPointerTyMismatch(..) =>
                 "tried to call a function through a function pointer of a different type",
@@ -175,14 +178,10 @@ impl<'tcx> Error for EvalError<'tcx> {
                 "tried to dereference a function pointer",
             ExecuteMemory =>
                 "tried to treat a memory pointer as a function pointer",
-            ArrayIndexOutOfBounds(..) =>
+            BoundsCheck{..} =>
                 "array index out of bounds",
-            Math(..) =>
-                "mathematical operation failed",
             Intrinsic(..) =>
                 "intrinsic failed",
-            OverflowingMath =>
-                "attempted to do overflowing math",
             NoMirFor(..) =>
                 "mir not found",
             InvalidChar(..) =>
@@ -232,7 +231,7 @@ impl<'tcx> Error for EvalError<'tcx> {
                 "the evaluated program panicked",
             ReadFromReturnPointer =>
                 "tried to read from the return pointer",
-            EvalErrorKind::PathNotFound(_) =>
+            PathNotFound(_) =>
                 "a path could not be resolved, maybe the crate is not loaded",
             UnimplementedTraitSelection =>
                 "there were unresolved type arguments during trait selection",
@@ -240,14 +239,33 @@ impl<'tcx> Error for EvalError<'tcx> {
                 "encountered constants with type errors, stopping evaluation",
             ReferencedConstant =>
                 "referenced constant has errors",
+            Overflow(mir::BinOp::Add) => "attempt to add with overflow",
+            Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
+            Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow",
+            Overflow(mir::BinOp::Div) => "attempt to divide with overflow",
+            Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow",
+            OverflowNeg => "attempt to negate with overflow",
+            Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow",
+            Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow",
+            Overflow(op) => bug!("{:?} cannot overflow", op),
+            DivisionByZero => "attempt to divide by zero",
+            RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
+            GeneratorResumedAfterReturn => "generator resumed after completion",
+            GeneratorResumedAfterPanic => "generator resumed after panicking",
         }
     }
 }
 
 impl<'tcx> fmt::Display for EvalError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}", self.kind)
+    }
+}
+
+impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::EvalErrorKind::*;
-        match self.kind {
+        match *self {
             PointerOutOfBounds { ptr, access, allocation_size } => {
                 write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}",
                        if access { "memory access" } else { "pointer computed" },
@@ -275,14 +293,12 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
             NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
             FunctionPointerTyMismatch(sig, got) =>
                 write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
-            ArrayIndexOutOfBounds(span, len, index) =>
-                write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
+            BoundsCheck { ref len, ref index } =>
+                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             ReallocatedWrongMemoryKind(ref old, ref new) =>
                 write!(f, "tried to reallocate memory from {} to {}", old, new),
             DeallocatedWrongMemoryKind(ref old, ref new) =>
                 write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
-            Math(_, ref err) =>
-                write!(f, "{}", err.description()),
             Intrinsic(ref err) =>
                 write!(f, "{}", err),
             InvalidChar(c) =>
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index c9eed0e4a28..546c7a920d5 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -8,7 +8,7 @@ macro_rules! err {
 mod error;
 mod value;
 
-pub use self::error::{EvalError, EvalResult, EvalErrorKind};
+pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
 
 pub use self::value::{PrimVal, PrimValKind, Value, Pointer};
 
@@ -23,7 +23,7 @@ use std::iter;
 use syntax::ast::Mutability;
 use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum Lock {
     NoLock,
     WriteLock(DynamicLifetime),
@@ -31,13 +31,13 @@ pub enum Lock {
     ReadLock(Vec<DynamicLifetime>),
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct DynamicLifetime {
     pub frame: usize,
     pub region: Option<region::Scope>, // "None" indicates "until the function ends"
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum AccessKind {
     Read,
     Write,
@@ -88,12 +88,12 @@ pub trait PointerArithmetic: layout::HasDataLayout {
 
     fn signed_offset<'tcx>(self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
         let (res, over) = self.overflowing_signed_offset(val, i as i128);
-        if over { err!(OverflowingMath) } else { Ok(res) }
+        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
     }
 
     fn offset<'tcx>(self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
         let (res, over) = self.overflowing_offset(val, i);
-        if over { err!(OverflowingMath) } else { Ok(res) }
+        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
     }
 
     fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index c525c4ed651..37f6d47ff84 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -15,17 +15,17 @@
 use graphviz::IntoCow;
 use middle::const_val::ConstVal;
 use middle::region;
-use rustc_const_math::ConstMathErr;
 use rustc_data_structures::sync::{Lrc};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
 use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
 use rustc_data_structures::control_flow_graph::ControlFlowGraph;
+use rustc_data_structures::small_vec::SmallVec;
 use rustc_serialize as serialize;
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use mir::visit::MirVisitable;
-use mir::interpret::{Value, PrimVal};
+use mir::interpret::{Value, PrimVal, EvalErrorKind};
 use ty::subst::{Subst, Substs};
 use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -36,12 +36,16 @@ use hir::{self, InlineAsm};
 use std::borrow::{Cow};
 use rustc_data_structures::sync::ReadGuard;
 use std::fmt::{self, Debug, Formatter, Write};
-use std::{iter, mem, u32};
+use std::{iter, mem, option, u32};
 use std::ops::{Index, IndexMut};
 use std::vec::IntoIter;
 use syntax::ast::{self, Name};
 use syntax::symbol::InternedString;
 use syntax_pos::{Span, DUMMY_SP};
+use rustc_apfloat::ieee::{Single, Double};
+use rustc_apfloat::Float;
+
+pub use mir::interpret::AssertMessage;
 
 mod cache;
 pub mod tcx;
@@ -247,6 +251,22 @@ impl<'tcx> Mir<'tcx> {
         })
     }
 
+    /// Returns an iterator over all user-declared mutable arguments and locals.
+    #[inline]
+    pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
+        (1..self.local_decls.len()).filter_map(move |index| {
+            let local = Local::new(index);
+            let decl = &self.local_decls[local];
+            if (decl.is_user_variable || index < self.arg_count + 1)
+               && decl.mutability == Mutability::Mut
+            {
+                Some(local)
+            } else {
+                None
+            }
+        })
+    }
+
     /// Returns an iterator over all function arguments.
     #[inline]
     pub fn args_iter(&self) -> impl Iterator<Item=Local> {
@@ -842,12 +862,17 @@ pub enum TerminatorKind<'tcx> {
     },
 }
 
+pub type Successors<'a> =
+    iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
+pub type SuccessorsMut<'a> =
+    iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
+
 impl<'tcx> Terminator<'tcx> {
-    pub fn successors(&self) -> Cow<[BasicBlock]> {
+    pub fn successors(&self) -> Successors {
         self.kind.successors()
     }
 
-    pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
+    pub fn successors_mut(&mut self) -> SuccessorsMut {
         self.kind.successors_mut()
     }
 
@@ -868,72 +893,71 @@ impl<'tcx> TerminatorKind<'tcx> {
         }
     }
 
-    pub fn successors(&self) -> Cow<[BasicBlock]> {
+    pub fn successors(&self) -> Successors {
         use self::TerminatorKind::*;
         match *self {
-            Goto { target: ref b } => slice::from_ref(b).into_cow(),
-            SwitchInt { targets: ref b, .. } => b[..].into_cow(),
-            Resume | Abort | GeneratorDrop => (&[]).into_cow(),
-            Return => (&[]).into_cow(),
-            Unreachable => (&[]).into_cow(),
-            Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
-            Call { destination: Some((_, ref t)), cleanup: None, .. } =>
-                slice::from_ref(t).into_cow(),
-            Call { destination: None, cleanup: Some(ref c), .. } => slice::from_ref(c).into_cow(),
-            Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
-            Yield { resume: t, drop: Some(c), .. } => vec![t, c].into_cow(),
-            Yield { resume: ref t, drop: None, .. } => slice::from_ref(t).into_cow(),
-            DropAndReplace { target, unwind: Some(unwind), .. } |
-            Drop { target, unwind: Some(unwind), .. } => {
-                vec![target, unwind].into_cow()
+            Resume | Abort | GeneratorDrop | Return | Unreachable |
+            Call { destination: None, cleanup: None, .. } => {
+                None.into_iter().chain(&[])
+            }
+            Goto { target: ref t } |
+            Call { destination: None, cleanup: Some(ref t), .. } |
+            Call { destination: Some((_, ref t)), cleanup: None, .. } |
+            Yield { resume: ref t, drop: None, .. } |
+            DropAndReplace { target: ref t, unwind: None, .. } |
+            Drop { target: ref t, unwind: None, .. } |
+            Assert { target: ref t, cleanup: None, .. } |
+            FalseUnwind { real_target: ref t, unwind: None } => {
+                Some(t).into_iter().chain(&[])
+            }
+            Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } |
+            Yield { resume: ref t, drop: Some(ref u), .. } |
+            DropAndReplace { target: ref t, unwind: Some(ref u), .. } |
+            Drop { target: ref t, unwind: Some(ref u), .. } |
+            Assert { target: ref t, cleanup: Some(ref u), .. } |
+            FalseUnwind { real_target: ref t, unwind: Some(ref u) } => {
+                Some(t).into_iter().chain(slice::from_ref(u))
             }
-            DropAndReplace { ref target, unwind: None, .. } |
-            Drop { ref target, unwind: None, .. } => {
-                slice::from_ref(target).into_cow()
+            SwitchInt { ref targets, .. } => {
+                None.into_iter().chain(&targets[..])
             }
-            Assert { target, cleanup: Some(unwind), .. } => vec![target, unwind].into_cow(),
-            Assert { ref target, .. } => slice::from_ref(target).into_cow(),
             FalseEdges { ref real_target, ref imaginary_targets } => {
-                let mut s = vec![*real_target];
-                s.extend_from_slice(imaginary_targets);
-                s.into_cow()
+                Some(real_target).into_iter().chain(&imaginary_targets[..])
             }
-            FalseUnwind { real_target: t, unwind: Some(u) } => vec![t, u].into_cow(),
-            FalseUnwind { real_target: ref t, unwind: None } => slice::from_ref(t).into_cow(),
         }
     }
 
-    // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and
-    // `Vec<&mut BasicBlock>` would look like in the first place.
-    pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
+    pub fn successors_mut(&mut self) -> SuccessorsMut {
         use self::TerminatorKind::*;
         match *self {
-            Goto { target: ref mut b } => vec![b],
-            SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
-            Resume | Abort | GeneratorDrop => Vec::new(),
-            Return => Vec::new(),
-            Unreachable => Vec::new(),
-            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
-            Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
-            Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
-            Call { destination: None, cleanup: None, .. } => vec![],
-            Yield { resume: ref mut t, drop: Some(ref mut c), .. } => vec![t, c],
-            Yield { resume: ref mut t, drop: None, .. } => vec![t],
-            DropAndReplace { ref mut target, unwind: Some(ref mut unwind), .. } |
-            Drop { ref mut target, unwind: Some(ref mut unwind), .. } => vec![target, unwind],
-            DropAndReplace { ref mut target, unwind: None, .. } |
-            Drop { ref mut target, unwind: None, .. } => {
-                vec![target]
+            Resume | Abort | GeneratorDrop | Return | Unreachable |
+            Call { destination: None, cleanup: None, .. } => {
+                None.into_iter().chain(&mut [])
+            }
+            Goto { target: ref mut t } |
+            Call { destination: None, cleanup: Some(ref mut t), .. } |
+            Call { destination: Some((_, ref mut t)), cleanup: None, .. } |
+            Yield { resume: ref mut t, drop: None, .. } |
+            DropAndReplace { target: ref mut t, unwind: None, .. } |
+            Drop { target: ref mut t, unwind: None, .. } |
+            Assert { target: ref mut t, cleanup: None, .. } |
+            FalseUnwind { real_target: ref mut t, unwind: None } => {
+                Some(t).into_iter().chain(&mut [])
+            }
+            Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } |
+            Yield { resume: ref mut t, drop: Some(ref mut u), .. } |
+            DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } |
+            Drop { target: ref mut t, unwind: Some(ref mut u), .. } |
+            Assert { target: ref mut t, cleanup: Some(ref mut u), .. } |
+            FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => {
+                Some(t).into_iter().chain(slice::from_ref_mut(u))
+            }
+            SwitchInt { ref mut targets, .. } => {
+                None.into_iter().chain(&mut targets[..])
             }
-            Assert { ref mut target, cleanup: Some(ref mut unwind), .. } => vec![target, unwind],
-            Assert { ref mut target, .. } => vec![target],
             FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
-                let mut s = vec![real_target];
-                s.extend(imaginary_targets.iter_mut());
-                s
+                Some(real_target).into_iter().chain(&mut imaginary_targets[..])
             }
-            FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => vec![t, u],
-            FalseUnwind { ref mut real_target, unwind: None } => vec![real_target],
         }
     }
 
@@ -1053,18 +1077,18 @@ impl<'tcx> BasicBlockData<'tcx> {
 impl<'tcx> Debug for TerminatorKind<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
         self.fmt_head(fmt)?;
-        let successors = self.successors();
+        let successor_count = self.successors().count();
         let labels = self.fmt_successor_labels();
-        assert_eq!(successors.len(), labels.len());
+        assert_eq!(successor_count, labels.len());
 
-        match successors.len() {
+        match successor_count {
             0 => Ok(()),
 
-            1 => write!(fmt, " -> {:?}", successors[0]),
+            1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()),
 
             _ => {
                 write!(fmt, " -> [")?;
-                for (i, target) in successors.iter().enumerate() {
+                for (i, target) in self.successors().enumerate() {
                     if i > 0 {
                         write!(fmt, ", ")?;
                     }
@@ -1113,26 +1137,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                 if !expected {
                     write!(fmt, "!")?;
                 }
-                write!(fmt, "{:?}, ", cond)?;
-
-                match *msg {
-                    AssertMessage::BoundsCheck { ref len, ref index } => {
-                        write!(fmt, "{:?}, {:?}, {:?}",
-                               "index out of bounds: the len is {} but the index is {}",
-                               len, index)?;
-                    }
-                    AssertMessage::Math(ref err) => {
-                        write!(fmt, "{:?}", err.description())?;
-                    }
-                    AssertMessage::GeneratorResumedAfterReturn => {
-                        write!(fmt, "{:?}", "generator resumed after completion")?;
-                    }
-                    AssertMessage::GeneratorResumedAfterPanic => {
-                        write!(fmt, "{:?}", "generator resumed after panicking")?;
-                    }
-                }
-
-                write!(fmt, ")")
+                write!(fmt, "{:?}, \"{:?}\")", cond, msg)
             },
             FalseEdges { .. } => write!(fmt, "falseEdges"),
             FalseUnwind { .. } => write!(fmt, "falseUnwind"),
@@ -1187,17 +1192,6 @@ impl<'tcx> TerminatorKind<'tcx> {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub enum AssertMessage<'tcx> {
-    BoundsCheck {
-        len: Operand<'tcx>,
-        index: Operand<'tcx>
-    },
-    Math(ConstMathErr),
-    GeneratorResumedAfterReturn,
-    GeneratorResumedAfterPanic,
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
@@ -1898,12 +1892,13 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
 
 pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
     use ty::TypeVariants::*;
-    use rustc_const_math::ConstFloat;
     match (value, &ty.sty) {
         (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
         (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
-        (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(fty)) =>
-            write!(f, "{}", ConstFloat { bits, ty: fty }),
+        (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) =>
+            write!(f, "{}f32", Single::from_bits(bits)),
+        (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) =>
+            write!(f, "{}f64", Double::from_bits(bits)),
         (Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui),
         (Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i),
         (Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
@@ -1952,7 +1947,7 @@ impl<'tcx> ControlFlowGraph for Mir<'tcx> {
     fn successors<'graph>(&'graph self, node: Self::Node)
                           -> <Self as GraphSuccessors<'graph>>::Iter
     {
-        self.basic_blocks[node].terminator().successors().into_owned().into_iter()
+        self.basic_blocks[node].terminator().successors().cloned()
     }
 }
 
@@ -1963,7 +1958,7 @@ impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> {
 
 impl<'a, 'b>  GraphSuccessors<'b> for Mir<'a> {
     type Item = BasicBlock;
-    type Iter = IntoIter<BasicBlock>;
+    type Iter = iter::Cloned<Successors<'b>>;
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
@@ -1983,6 +1978,11 @@ impl fmt::Debug for Location {
 }
 
 impl Location {
+    pub const START: Location = Location {
+        block: START_BLOCK,
+        statement_index: 0,
+    };
+
     /// Returns the location immediately after this one within the enclosing block.
     ///
     /// Note that if this location represents a terminator, then the
@@ -2029,6 +2029,12 @@ pub struct GeneratorLayout<'tcx> {
     pub fields: Vec<LocalDecl<'tcx>>,
 }
 
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct BorrowCheckResult<'gcx> {
+    pub closure_requirements: Option<ClosureRegionRequirements<'gcx>>,
+    pub used_mut_upvars: SmallVec<[Field; 8]>,
+}
+
 /// After we borrow check a closure, we are left with various
 /// requirements that we have inferred between the free regions that
 /// appear in the closure's signature or on its field types.  These
@@ -2256,8 +2262,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 }
             },
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
-                    AssertMessage::BoundsCheck {
+                let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
+                    EvalErrorKind::BoundsCheck {
                         len: len.fold_with(folder),
                         index: index.fold_with(folder),
                     }
@@ -2306,7 +2312,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             },
             Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
-                    if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
+                    if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
                         len.visit_with(visitor) || index.visit_with(visitor)
                     } else {
                         false
diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs
index 666ca5eabe8..92888ed99e4 100644
--- a/src/librustc/mir/traversal.rs
+++ b/src/librustc/mir/traversal.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::vec;
-
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -67,7 +65,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
             let data = &self.mir[idx];
 
             if let Some(ref term) = data.terminator {
-                for &succ in term.successors().iter() {
+                for &succ in term.successors() {
                     self.worklist.push(succ);
                 }
             }
@@ -110,7 +108,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
 pub struct Postorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     visited: BitVector,
-    visit_stack: Vec<(BasicBlock, vec::IntoIter<BasicBlock>)>
+    visit_stack: Vec<(BasicBlock, Successors<'a>)>
 }
 
 impl<'a, 'tcx> Postorder<'a, 'tcx> {
@@ -126,10 +124,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
 
         if let Some(ref term) = data.terminator {
             po.visited.insert(root.index());
-
-            let succs = term.successors().into_owned().into_iter();
-
-            po.visit_stack.push((root, succs));
+            po.visit_stack.push((root, term.successors()));
             po.traverse_successor();
         }
 
@@ -186,7 +181,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
         // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A]
         loop {
             let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() {
-                if let Some(bb) = iter.next() {
+                if let Some(&bb) = iter.next() {
                     bb
                 } else {
                     break;
@@ -197,8 +192,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
 
             if self.visited.insert(bb.index()) {
                 if let Some(ref term) = self.mir[bb].terminator {
-                    let succs = term.successors().into_owned().into_iter();
-                    self.visit_stack.push((bb, succs));
+                    self.visit_stack.push((bb, term.successors()));
                 }
             }
         }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index a3fdb6f73ab..59b6f369754 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -511,17 +511,13 @@ macro_rules! make_mir_visitor {
             fn super_assert_message(&mut self,
                                     msg: & $($mutability)* AssertMessage<'tcx>,
                                     location: Location) {
-                match *msg {
-                    AssertMessage::BoundsCheck {
+                use mir::interpret::EvalErrorKind::*;
+                if let BoundsCheck {
                         ref $($mutability)* len,
                         ref $($mutability)* index
-                    } => {
-                        self.visit_operand(len, location);
-                        self.visit_operand(index, location);
-                    }
-                    AssertMessage::Math(_) => {},
-                    AssertMessage::GeneratorResumedAfterReturn => {},
-                    AssertMessage::GeneratorResumedAfterPanic => {},
+                    } = *msg {
+                    self.visit_operand(len, location);
+                    self.visit_operand(index, location);
                 }
             }
 
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index ab703d423c6..0beda679e69 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1053,6 +1053,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
          2 = full debug info with variable and type information"),
     opt_level: Option<String> = (None, parse_opt_string, [TRACKED],
         "optimize with possible levels 0-3, s, or z"),
+    force_frame_pointers: Option<bool> = (None, parse_opt_bool, [TRACKED],
+        "force use of the frame pointers"),
     debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "explicitly enable the cfg(debug_assertions) directive"),
     inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
@@ -1248,6 +1250,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "choose which RELRO level to use"),
     nll_subminimal_causes: bool = (false, parse_bool, [UNTRACKED],
         "when tracking region error causes, accept subminimal results for faster execution."),
+    nll_facts: bool = (false, parse_bool, [UNTRACKED],
+                       "dump facts from NLL analysis into side files"),
     disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
         "disable user provided type assertion in NLL"),
     trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -1270,7 +1274,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
         "in dep-info output, omit targets for tracking dependencies of the dep-info files \
          themselves"),
-    approximate_suggestions: bool = (false, parse_bool, [UNTRACKED],
+    suggestion_applicability: bool = (false, parse_bool, [UNTRACKED],
         "include machine-applicability of suggestions in JSON output"),
     unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
         "Present the input source, unstable (and less-pretty) variants;
@@ -1681,7 +1685,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> ast::CrateConfig {
                 early_error(ErrorOutputType::default(), &msg)
             }
 
-            (meta_item.ident.name, meta_item.value_str())
+            (meta_item.name(), meta_item.value_str())
         })
         .collect::<ast::CrateConfig>()
 }
@@ -2966,6 +2970,10 @@ mod tests {
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
         opts = reference.clone();
+        opts.cg.force_frame_pointers = Some(false);
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+        opts = reference.clone();
         opts.cg.debug_assertions = Some(true);
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index a0f11443425..2ab72ba20bf 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics;
 use middle::allocator::AllocatorKind;
 use middle::dependency_format;
 use session::search_paths::PathKind;
-use session::config::{DebugInfoLevel, OutputType};
+use session::config::{OutputType};
 use ty::tls;
 use util::nodemap::{FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
@@ -658,8 +658,11 @@ impl Session {
     }
 
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
-        self.opts.debuginfo != DebugInfoLevel::NoDebugInfo
-            || !self.target.target.options.eliminate_frame_pointer
+        if let Some(x) = self.opts.cg.force_frame_pointers {
+            x
+        } else {
+            !self.target.target.options.eliminate_frame_pointer
+        }
     }
 
     /// Returns the symbol name for the registrar function,
@@ -1002,7 +1005,7 @@ pub fn build_session_with_codemap(
                     Some(registry),
                     codemap.clone(),
                     pretty,
-                    sopts.debugging_opts.approximate_suggestions,
+                    sopts.debugging_opts.suggestion_applicability,
                 ).ui_testing(sopts.debugging_opts.ui_testing),
             ),
             (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new(
@@ -1011,7 +1014,7 @@ pub fn build_session_with_codemap(
                     Some(registry),
                     codemap.clone(),
                     pretty,
-                    sopts.debugging_opts.approximate_suggestions,
+                    sopts.debugging_opts.suggestion_applicability,
                 ).ui_testing(sopts.debugging_opts.ui_testing),
             ),
             (config::ErrorOutputType::Short(color_config), None) => Box::new(
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 31f8af1f968..5a626e7b82c 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -154,7 +154,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
                                            recursion_depth: 0,
                                            predicate: p })
                      .chain(obligations)
-                     .find(|o| !selcx.evaluate_obligation(o));
+                     .find(|o| !selcx.predicate_may_hold_fatal(o));
+    // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
+    // to the canonical trait query form, `infcx.predicate_may_hold`, once
+    // the new system supports intercrate mode (which coherence needs).
 
     if let Some(failing_obligation) = opt_failing_obligation {
         debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 33abc0c7e15..047d4bb8930 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -24,6 +24,7 @@ use super::{
     SelectionContext,
     SelectionError,
     ObjectSafetyViolation,
+    Overflow,
 };
 
 use errors::DiagnosticBuilder;
@@ -659,8 +660,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                 predicate: ty::Predicate::Trait(predicate),
                                 .. obligation.clone()
                             };
-                            let mut selcx = SelectionContext::new(self);
-                            if selcx.evaluate_obligation(&unit_obligation) {
+                            if self.predicate_may_hold(&unit_obligation) {
                                 err.note("the trait is implemented for `()`. \
                                          Possibly this error has been caused by changes to \
                                          Rust's type-inference algorithm \
@@ -830,6 +830,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 }
                 err.struct_error(self.tcx, span, "constant expression")
             }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
         };
         self.note_obligation_cause(&mut err, obligation);
         err.emit();
@@ -872,7 +876,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 .count();
 
             let mut trait_type = trait_ref.self_ty();
-            let mut selcx = SelectionContext::new(self);
 
             for refs_remaining in 0..refs_number {
                 if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) =
@@ -886,7 +889,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                          obligation.param_env,
                                                          new_trait_ref.to_predicate());
 
-                    if selcx.evaluate_obligation(&new_obligation) {
+                    if self.predicate_may_hold(&new_obligation) {
                         let sp = self.tcx.sess.codemap()
                             .span_take_while(span, |c| c.is_whitespace() || *c == '&');
 
@@ -976,6 +979,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                      ArgKind::Arg(format!("{}", field.name), "_".to_string())
                  }).collect::<Vec<_>>())
             }
+            hir::map::NodeStructCtor(ref variant_data) => {
+                (self.tcx.sess.codemap().def_span(self.tcx.hir.span(variant_data.id())),
+                 variant_data.fields()
+                    .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned()))
+                    .collect())
+            }
             _ => panic!("non-FnLike node found: {:?}", node),
         }
     }
@@ -1322,7 +1331,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 cleaned_pred.to_predicate()
             );
 
-            selcx.evaluate_obligation(&obligation)
+            self.predicate_may_hold(&obligation)
         })
     }
 
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 1c091d68a2e..6e201507181 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
                 selcx,
                 register_region_obligations: self.register_region_obligations
             });
-            debug!("select: outcome={:?}", outcome);
+            debug!("select: outcome={:#?}", outcome);
 
             // FIXME: if we kept the original cache key, we could mark projection
             // obligations as complete for the projection cache here.
@@ -333,7 +333,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
             if data.is_global() {
                 // no type variables present, can use evaluation for better caching.
                 // FIXME: consider caching errors too.
-                if selcx.evaluate_obligation_conservatively(&obligation) {
+                if selcx.infcx().predicate_must_hold(&obligation) {
                     debug!("selecting trait `{:?}` at depth {} evaluated to holds",
                            data, obligation.recursion_depth);
                     return Ok(Some(vec![]))
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 728d9f1a027..dd5208e908e 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -41,7 +41,7 @@ pub use self::object_safety::ObjectSafetyViolation;
 pub use self::object_safety::MethodViolationCode;
 pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
-pub use self::select::IntercrateAmbiguityCause;
+pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::{SpecializesCache, find_associated_item};
 pub use self::engine::TraitEngine;
@@ -74,6 +74,19 @@ pub enum IntercrateMode {
     Fixed
 }
 
+// The mode that trait queries run in
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum TraitQueryMode {
+    // Standard/un-canonicalized queries get accurate
+    // spans etc. passed in and hence can do reasonable
+    // error reporting on their own.
+    Standard,
+    // Canonicalized queries get dummy spans and hence
+    // must generally propagate errors to
+    // pre-canonicalization callsites.
+    Canonical,
+}
+
 /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for
 /// which the vtable must be found.  The process of finding a vtable is
 /// called "resolving" the `Obligation`. This process consists of
@@ -349,6 +362,7 @@ pub enum SelectionError<'tcx> {
                                 ty::error::TypeError<'tcx>),
     TraitNotObjectSafe(DefId),
     ConstEvalFailure(ConstEvalErr<'tcx>),
+    Overflow,
 }
 
 pub struct FulfillmentError<'tcx> {
@@ -550,8 +564,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
         predicate: trait_ref.to_predicate(),
     };
 
-    let result = SelectionContext::new(infcx)
-        .evaluate_obligation_conservatively(&obligation);
+    let result = infcx.predicate_must_hold(&obligation);
     debug!("type_known_to_meet_ty={:?} bound={} => {:?}",
            ty, infcx.tcx.item_path_str(def_id), result);
 
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 405dafdff2b..3cf7af30b3d 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -18,10 +18,10 @@ use util::nodemap::FxHashMap;
 use syntax::ast::{MetaItem, NestedMetaItem};
 use syntax::attr;
 use syntax_pos::Span;
-use syntax_pos::symbol::InternedString;
+use syntax_pos::symbol::LocalInternedString;
 
 #[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(InternedString);
+pub struct OnUnimplementedFormatString(LocalInternedString);
 
 #[derive(Debug)]
 pub struct OnUnimplementedDirective {
@@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             if let Some(ref condition) = command.condition {
                 if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
-                    options.contains(&(c.ident.name.as_str().to_string(),
+                    options.contains(&(c.name().as_str().to_string(),
                                       match c.value_str().map(|s| s.as_str().to_string()) {
                                           Some(s) => Some(s),
                                           None => None
@@ -225,7 +225,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
 impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
     pub fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                      trait_def_id: DefId,
-                     from: InternedString,
+                     from: LocalInternedString,
                      err_sp: Span)
                      -> Result<Self, ErrorReported>
     {
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 1c7942139e9..45fa588bbf5 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -188,7 +188,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
     let infcx = selcx.infcx();
     infcx.commit_if_ok(|snapshot| {
         let (skol_predicate, skol_map) =
-            infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot);
+            infcx.skolemize_late_bound_regions(&obligation.predicate);
 
         let skol_obligation = obligation.with(skol_predicate);
         let r = match project_and_unify_type(selcx, &skol_obligation) {
@@ -196,7 +196,10 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
                 let span = obligation.cause.span;
                 match infcx.leak_check(false, span, &skol_map, snapshot) {
                     Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, result)),
-                    Err(e) => Err(MismatchedProjectionTypes { err: e }),
+                    Err(e) => {
+                        debug!("poly_project_and_unify_type: leak check encountered error {:?}", e);
+                        Err(MismatchedProjectionTypes { err: e })
+                    }
                 }
             }
             Err(e) => {
@@ -243,7 +246,10 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>(
             obligations.extend(inferred_obligations);
             Ok(Some(obligations))
         },
-        Err(err) => Err(MismatchedProjectionTypes { err: err }),
+        Err(err) => {
+            debug!("project_and_unify_type: equating types encountered error {:?}", err);
+            Err(MismatchedProjectionTypes { err: err })
+        }
     }
 }
 
@@ -403,7 +409,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
         if let ConstVal::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.selcx.tcx().global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
-                if substs.needs_infer() {
+                if substs.needs_infer() || substs.has_skol() {
                     let identity_substs = Substs::identity_for_item(tcx, def_id);
                     let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
                     if let Some(instance) = instance {
diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs
new file mode 100644
index 00000000000..4e028cac49a
--- /dev/null
+++ b/src/librustc/traits/query/evaluate_obligation.rs
@@ -0,0 +1,70 @@
+// Copyright 2018 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 infer::InferCtxt;
+use infer::canonical::{Canonical, Canonicalize};
+use traits::{EvaluationResult, PredicateObligation, SelectionContext,
+             TraitQueryMode, OverflowError};
+use traits::query::CanonicalPredicateGoal;
+use ty::{ParamEnvAnd, Predicate, TyCtxt};
+
+impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
+    /// Evaluates whether the predicate can be satisfied (by any means)
+    /// in the given `ParamEnv`.
+    pub fn predicate_may_hold(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        self.evaluate_obligation(obligation).may_apply()
+    }
+
+    /// Evaluates whether the predicate can be satisfied in the given
+    /// `ParamEnv`, and returns `false` if not certain. However, this is
+    /// not entirely accurate if inference variables are involved.
+    pub fn predicate_must_hold(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk
+    }
+
+    // Helper function that canonicalizes and runs the query, as well as handles
+    // overflow.
+    fn evaluate_obligation(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> EvaluationResult {
+        let (c_pred, _) =
+            self.canonicalize_query(&obligation.param_env.and(obligation.predicate));
+        // Run canonical query. If overflow occurs, rerun from scratch but this time
+        // in standard trait query mode so that overflow is handled appropriately
+        // within `SelectionContext`.
+        match self.tcx.global_tcx().evaluate_obligation(c_pred) {
+            Ok(result) => result,
+            Err(OverflowError) => {
+                let mut selcx =
+                    SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
+                selcx.evaluate_obligation_recursively(obligation)
+                     .expect("Overflow should be caught earlier in standard query mode")
+            }
+        }
+    }
+}
+
+impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for ParamEnvAnd<'tcx, Predicate<'tcx>> {
+    type Canonicalized = CanonicalPredicateGoal<'gcx>;
+
+    fn intern(
+        _gcx: TyCtxt<'_, 'gcx, 'gcx>,
+        value: Canonical<'gcx, Self::Lifted>,
+    ) -> Self::Canonicalized {
+        value
+    }
+}
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs
index f1f9256f825..096633ddab2 100644
--- a/src/librustc/traits/query/mod.rs
+++ b/src/librustc/traits/query/mod.rs
@@ -19,6 +19,7 @@ use infer::canonical::Canonical;
 use ty::{self, Ty};
 
 pub mod dropck_outlives;
+pub mod evaluate_obligation;
 pub mod normalize;
 pub mod normalize_erasing_regions;
 
@@ -27,6 +28,9 @@ pub type CanonicalProjectionGoal<'tcx> =
 
 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
 
+pub type CanonicalPredicateGoal<'tcx> =
+    Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct NoSolution;
 
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 5e0a4ca3305..f074e061653 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -196,7 +196,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
         if let ConstVal::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.infcx.tcx.global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
-                if substs.needs_infer() {
+                if substs.needs_infer() || substs.has_skol() {
                     let identity_substs = Substs::identity_for_item(tcx, def_id);
                     let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
                     if let Some(instance) = instance {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index f43f5cf3e3f..54b2cf28082 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -17,12 +17,12 @@ use self::EvaluationResult::*;
 
 use super::coherence::{self, Conflict};
 use super::DerivedObligationCause;
-use super::IntercrateMode;
+use super::{IntercrateMode, TraitQueryMode};
 use super::project;
 use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey};
 use super::{PredicateObligation, TraitObligation, ObligationCause};
 use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
-use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
+use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch, Overflow};
 use super::{ObjectCastObligation, Obligation};
 use super::TraitNotObjectSafe;
 use super::Selection;
@@ -87,7 +87,12 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     /// Controls whether or not to filter out negative impls when selecting.
     /// This is used in librustdoc to distinguish between the lack of an impl
     /// and a negative impl
-    allow_negative_impls: bool
+    allow_negative_impls: bool,
+
+    /// The mode that trait queries run in, which informs our error handling
+    /// policy. In essence, canonicalized queries need their errors propagated
+    /// rather than immediately reported because we do not have accurate spans.
+    query_mode: TraitQueryMode,
 }
 
 #[derive(Clone, Debug)]
@@ -319,7 +324,7 @@ enum BuiltinImplConditions<'tcx> {
 ///     all the "potential success" candidates can potentially succeed,
 ///     so they are no-ops when unioned with a definite error, and within
 ///     the categories it's easy to see that the unions are correct.
-enum EvaluationResult {
+pub enum EvaluationResult {
     /// Evaluation successful
     EvaluatedToOk,
     /// Evaluation is known to be ambiguous - it *might* hold for some
@@ -385,7 +390,7 @@ enum EvaluationResult {
 }
 
 impl EvaluationResult {
-    fn may_apply(self) -> bool {
+    pub fn may_apply(self) -> bool {
         match self {
             EvaluatedToOk |
             EvaluatedToAmbig |
@@ -408,6 +413,26 @@ impl EvaluationResult {
     }
 }
 
+impl_stable_hash_for!(enum self::EvaluationResult {
+    EvaluatedToOk,
+    EvaluatedToAmbig,
+    EvaluatedToUnknown,
+    EvaluatedToRecur,
+    EvaluatedToErr
+});
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+/// Indicates that trait evaluation caused overflow.
+pub struct OverflowError;
+
+impl_stable_hash_for!(struct OverflowError { });
+
+impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
+    fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
+        SelectionError::Overflow
+    }
+}
+
 #[derive(Clone)]
 pub struct EvaluationCache<'tcx> {
     hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>
@@ -421,6 +446,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             intercrate: None,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
+            query_mode: TraitQueryMode::Standard,
         }
     }
 
@@ -433,6 +459,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             intercrate: Some(mode),
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
+            query_mode: TraitQueryMode::Standard,
         }
     }
 
@@ -445,6 +472,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             intercrate: None,
             intercrate_ambiguity_causes: None,
             allow_negative_impls,
+            query_mode: TraitQueryMode::Standard,
+        }
+    }
+
+    pub fn with_query_mode(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+                           query_mode: TraitQueryMode) -> SelectionContext<'cx, 'gcx, 'tcx> {
+        debug!("with_query_mode({:?})", query_mode);
+        SelectionContext {
+            infcx,
+            freshener: infcx.freshener(),
+            intercrate: None,
+            intercrate_ambiguity_causes: None,
+            allow_negative_impls: false,
+            query_mode,
         }
     }
 
@@ -528,12 +569,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         assert!(!obligation.predicate.has_escaping_regions());
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
-        let ret = match self.candidate_from_obligation(&stack)? {
-            None => None,
-            Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?)
+
+        let candidate = match self.candidate_from_obligation(&stack) {
+            Err(SelectionError::Overflow) => {
+                // In standard mode, overflow must have been caught and reported
+                // earlier.
+                assert!(self.query_mode == TraitQueryMode::Canonical);
+                return Err(SelectionError::Overflow);
+            },
+            Err(e) => { return Err(e); },
+            Ok(None) => { return Ok(None); },
+            Ok(Some(candidate)) => candidate
         };
 
-        Ok(ret)
+        match self.confirm_candidate(obligation, candidate) {
+            Err(SelectionError::Overflow) => {
+                assert!(self.query_mode == TraitQueryMode::Canonical);
+                return Err(SelectionError::Overflow);
+            },
+            Err(e) => Err(e),
+            Ok(candidate) => Ok(Some(candidate))
+        }
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -547,32 +603,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     // we can be sure it does not.
 
     /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
-    pub fn evaluate_obligation(&mut self,
-                               obligation: &PredicateObligation<'tcx>)
-                               -> bool
+    pub fn predicate_may_hold_fatal(&mut self,
+                                    obligation: &PredicateObligation<'tcx>)
+                                    -> bool
     {
-        debug!("evaluate_obligation({:?})",
+        debug!("predicate_may_hold_fatal({:?})",
                obligation);
 
-        self.probe(|this, _| {
-            this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
-                .may_apply()
-        })
+        // This fatal query is a stopgap that should only be used in standard mode,
+        // where we do not expect overflow to be propagated.
+        assert!(self.query_mode == TraitQueryMode::Standard);
+
+        self.evaluate_obligation_recursively(obligation)
+            .expect("Overflow should be caught earlier in standard query mode")
+            .may_apply()
     }
 
-    /// Evaluates whether the obligation `obligation` can be satisfied,
-    /// and returns `false` if not certain. However, this is not entirely
-    /// accurate if inference variables are involved.
-    pub fn evaluate_obligation_conservatively(&mut self,
-                                              obligation: &PredicateObligation<'tcx>)
-                                              -> bool
+    /// Evaluates whether the obligation `obligation` can be satisfied and returns
+    /// an `EvaluationResult`.
+    pub fn evaluate_obligation_recursively(&mut self,
+                                           obligation: &PredicateObligation<'tcx>)
+                                           -> Result<EvaluationResult, OverflowError>
     {
-        debug!("evaluate_obligation_conservatively({:?})",
-               obligation);
-
         self.probe(|this, _| {
             this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
-                == EvaluatedToOk
         })
     }
 
@@ -582,29 +636,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
                                                 stack: TraitObligationStackList<'o, 'tcx>,
                                                 predicates: I)
-                                                -> EvaluationResult
+                                                -> Result<EvaluationResult, OverflowError>
         where I : IntoIterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
     {
         let mut result = EvaluatedToOk;
         for obligation in predicates {
-            let eval = self.evaluate_predicate_recursively(stack, obligation);
+            let eval = self.evaluate_predicate_recursively(stack, obligation)?;
             debug!("evaluate_predicate_recursively({:?}) = {:?}",
                    obligation, eval);
             if let EvaluatedToErr = eval {
                 // fast-path - EvaluatedToErr is the top of the lattice,
                 // so we don't need to look on the other predicates.
-                return EvaluatedToErr;
+                return Ok(EvaluatedToErr);
             } else {
                 result = cmp::max(result, eval);
             }
         }
-        result
+        Ok(result)
     }
 
     fn evaluate_predicate_recursively<'o>(&mut self,
                                           previous_stack: TraitObligationStackList<'o, 'tcx>,
                                           obligation: &PredicateObligation<'tcx>)
-                                           -> EvaluationResult
+                                           -> Result<EvaluationResult, OverflowError>
     {
         debug!("evaluate_predicate_recursively({:?})",
                obligation);
@@ -620,11 +674,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 // does this code ever run?
                 match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
                     Some(Ok(InferOk { obligations, .. })) => {
-                        self.evaluate_predicates_recursively(previous_stack, &obligations);
-                        EvaluatedToOk
+                        self.evaluate_predicates_recursively(previous_stack, &obligations)
                     },
-                    Some(Err(_)) => EvaluatedToErr,
-                    None => EvaluatedToAmbig,
+                    Some(Err(_)) => Ok(EvaluatedToErr),
+                    None => Ok(EvaluatedToAmbig),
                 }
             }
 
@@ -636,21 +689,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     Some(obligations) =>
                         self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
                     None =>
-                        EvaluatedToAmbig,
+                        Ok(EvaluatedToAmbig),
                 }
             }
 
             ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
                 // we do not consider region relationships when
                 // evaluating trait matches
-                EvaluatedToOk
+                Ok(EvaluatedToOk)
             }
 
             ty::Predicate::ObjectSafe(trait_def_id) => {
                 if self.tcx().is_object_safe(trait_def_id) {
-                    EvaluatedToOk
+                    Ok(EvaluatedToOk)
                 } else {
-                    EvaluatedToErr
+                    Ok(EvaluatedToErr)
                 }
             }
 
@@ -668,10 +721,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         result
                     }
                     Ok(None) => {
-                        EvaluatedToAmbig
+                        Ok(EvaluatedToAmbig)
                     }
                     Err(_) => {
-                        EvaluatedToErr
+                        Ok(EvaluatedToErr)
                     }
                 }
             }
@@ -680,13 +733,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 match self.infcx.closure_kind(closure_def_id, closure_substs) {
                     Some(closure_kind) => {
                         if closure_kind.extends(kind) {
-                            EvaluatedToOk
+                            Ok(EvaluatedToOk)
                         } else {
-                            EvaluatedToErr
+                            Ok(EvaluatedToErr)
                         }
                     }
                     None => {
-                        EvaluatedToAmbig
+                        Ok(EvaluatedToAmbig)
                     }
                 }
             }
@@ -707,16 +760,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                 promoted: None
                             };
                             match self.tcx().const_eval(param_env.and(cid)) {
-                                Ok(_) => EvaluatedToOk,
-                                Err(_) => EvaluatedToErr
+                                Ok(_) => Ok(EvaluatedToOk),
+                                Err(_) => Ok(EvaluatedToErr)
                             }
                         } else {
-                            EvaluatedToErr
+                            Ok(EvaluatedToErr)
                         }
                     }
                     None => {
                         // Inference variables still left in param_env or substs.
-                        EvaluatedToAmbig
+                        Ok(EvaluatedToAmbig)
                     }
                 }
             }
@@ -726,7 +779,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_trait_predicate_recursively<'o>(&mut self,
                                                 previous_stack: TraitObligationStackList<'o, 'tcx>,
                                                 mut obligation: TraitObligation<'tcx>)
-                                                -> EvaluationResult
+                                                -> Result<EvaluationResult, OverflowError>
     {
         debug!("evaluate_trait_predicate_recursively({:?})",
                obligation);
@@ -745,22 +798,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             debug!("CACHE HIT: EVAL({:?})={:?}",
                    fresh_trait_ref,
                    result);
-            return result;
+            return Ok(result);
         }
 
         let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
+        let result = result?;
 
         debug!("CACHE MISS: EVAL({:?})={:?}",
                fresh_trait_ref,
                result);
         self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
 
-        result
+        Ok(result)
     }
 
     fn evaluate_stack<'o>(&mut self,
                           stack: &TraitObligationStack<'o, 'tcx>)
-                          -> EvaluationResult
+                          -> Result<EvaluationResult, OverflowError>
     {
         // In intercrate mode, whenever any of the types are unbound,
         // there can always be an impl. Even if there are no impls in
@@ -815,7 +869,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     }
                 }
             }
-            return EvaluatedToAmbig;
+            return Ok(EvaluatedToAmbig);
         }
         if unbound_input_types &&
               stack.iter().skip(1).any(
@@ -825,7 +879,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         {
             debug!("evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
                    stack.fresh_trait_ref);
-            return EvaluatedToUnknown;
+            return Ok(EvaluatedToUnknown);
         }
 
         // If there is any previous entry on the stack that precisely
@@ -860,18 +914,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             if self.coinductive_match(cycle) {
                 debug!("evaluate_stack({:?}) --> recursive, coinductive",
                        stack.fresh_trait_ref);
-                return EvaluatedToOk;
+                return Ok(EvaluatedToOk);
             } else {
                 debug!("evaluate_stack({:?}) --> recursive, inductive",
                        stack.fresh_trait_ref);
-                return EvaluatedToRecur;
+                return Ok(EvaluatedToRecur);
             }
         }
 
         match self.candidate_from_obligation(stack) {
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
-            Ok(None) => EvaluatedToAmbig,
-            Err(..) => EvaluatedToErr
+            Ok(None) => Ok(EvaluatedToAmbig),
+            Err(Overflow) => Err(OverflowError),
+            Err(..) => Ok(EvaluatedToErr)
         }
     }
 
@@ -909,7 +964,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_candidate<'o>(&mut self,
                               stack: &TraitObligationStack<'o, 'tcx>,
                               candidate: &SelectionCandidate<'tcx>)
-                              -> EvaluationResult
+                              -> Result<EvaluationResult, OverflowError>
     {
         debug!("evaluate_candidate: depth={} candidate={:?}",
                stack.obligation.recursion_depth, candidate);
@@ -921,12 +976,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         stack.list(),
                         selection.nested_obligations().iter())
                 }
-                Err(..) => EvaluatedToErr
+                Err(..) => Ok(EvaluatedToErr)
             }
-        });
+        })?;
         debug!("evaluate_candidate: depth={} result={:?}",
                stack.obligation.recursion_depth, result);
-        result
+        Ok(result)
     }
 
     fn check_evaluation_cache(&self,
@@ -1000,7 +1055,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         // not update) the cache.
         let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
         if stack.obligation.recursion_depth >= recursion_limit {
-            self.infcx().report_overflow_error(&stack.obligation, true);
+            match self.query_mode {
+                TraitQueryMode::Standard => {
+                    self.infcx().report_overflow_error(&stack.obligation, true);
+                },
+                TraitQueryMode::Canonical => {
+                    return Err(Overflow);
+                },
+            }
         }
 
         // Check the cache. Note that we skolemize the trait-ref
@@ -1081,9 +1143,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     debug!("evaluate_stack: intercrate_ambiguity_causes is some");
                     // Heuristics: show the diagnostics when there are no candidates in crate.
                     if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                        if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
-                            !self.evaluate_candidate(stack, &c).may_apply()
-                        }) {
+                        let no_candidates_apply =
+                            candidate_set
+                            .vec
+                            .iter()
+                            .map(|c| self.evaluate_candidate(stack, &c))
+                            .collect::<Result<Vec<_>, OverflowError>>()?
+                            .iter()
+                            .all(|r| !r.may_apply());
+                        if !candidate_set.ambiguous && no_candidates_apply {
                             let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
                             let self_ty = trait_ref.self_ty();
                             let trait_desc = trait_ref.to_string();
@@ -1151,18 +1219,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         }
 
         // Winnow, but record the exact outcome of evaluation, which
-        // is needed for specialization.
-        let mut candidates: Vec<_> = candidates.into_iter().filter_map(|c| {
-            let eval = self.evaluate_candidate(stack, &c);
-            if eval.may_apply() {
-                Some(EvaluatedCandidate {
+        // is needed for specialization. Propagate overflow if it occurs.
+        let candidates: Result<Vec<Option<EvaluatedCandidate>>, _> = candidates
+            .into_iter()
+            .map(|c| match self.evaluate_candidate(stack, &c) {
+                Ok(eval) if eval.may_apply() => Ok(Some(EvaluatedCandidate {
                     candidate: c,
                     evaluation: eval,
-                })
-            } else {
-                None
-            }
-        }).collect();
+                })),
+                Ok(_) => Ok(None),
+                Err(OverflowError) => Err(Overflow),
+            })
+            .collect();
+
+        let mut candidates: Vec<EvaluatedCandidate> =
+            candidates?.into_iter().filter_map(|c| c).collect();
 
         // If there are STILL multiple candidate, we can further
         // reduce the list by dropping duplicates -- including
@@ -1438,7 +1509,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let poly_trait_predicate =
             self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
         let (skol_trait_predicate, skol_map) =
-            self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot);
+            self.infcx().skolemize_late_bound_regions(&poly_trait_predicate);
         debug!("match_projection_obligation_against_definition_bounds: \
                 skol_trait_predicate={:?} skol_map={:?}",
                skol_trait_predicate,
@@ -1537,12 +1608,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let matching_bounds =
             all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
 
-        let matching_bounds =
-            matching_bounds.filter(
-                |bound| self.evaluate_where_clause(stack, bound.clone()).may_apply());
-
-        let param_candidates =
-            matching_bounds.map(|bound| ParamCandidate(bound));
+        // keep only those bounds which may apply, and propagate overflow if it occurs
+        let mut param_candidates = vec![];
+        for bound in matching_bounds {
+            let wc = self.evaluate_where_clause(stack, bound.clone())?;
+            if wc.may_apply() {
+                param_candidates.push(ParamCandidate(bound));
+            }
+        }
 
         candidates.vec.extend(param_candidates);
 
@@ -1552,14 +1625,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn evaluate_where_clause<'o>(&mut self,
                                  stack: &TraitObligationStack<'o, 'tcx>,
                                  where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                                 -> EvaluationResult
+                                 -> Result<EvaluationResult, OverflowError>
     {
         self.probe(move |this, _| {
             match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
                 Ok(obligations) => {
                     this.evaluate_predicates_recursively(stack.list(), obligations.iter())
                 }
-                Err(()) => EvaluatedToErr
+                Err(()) => Ok(EvaluatedToErr)
             }
         })
     }
@@ -2265,7 +2338,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             self.in_snapshot(|this, snapshot| {
                 let (skol_ty, skol_map) =
-                    this.infcx().skolemize_late_bound_regions(&ty, snapshot);
+                    this.infcx().skolemize_late_bound_regions(&ty);
                 let Normalized { value: normalized_ty, mut obligations } =
                     project::normalize_with_depth(this,
                                                   param_env,
@@ -2486,7 +2559,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let trait_obligations = self.in_snapshot(|this, snapshot| {
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
             let (trait_ref, skol_map) =
-                this.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot);
+                this.infcx().skolemize_late_bound_regions(&poly_trait_ref);
             let cause = obligation.derived_cause(ImplDerivedObligation);
             this.impl_or_trait_obligations(cause,
                                            obligation.recursion_depth + 1,
@@ -3069,8 +3142,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         }
 
         let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions(
-            &obligation.predicate,
-            snapshot);
+            &obligation.predicate);
         let skol_obligation_trait_ref = skol_obligation.trait_ref;
 
         let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span,
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 1e3e4160de1..d7e42655bbb 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -177,6 +177,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
             super::ConstEvalFailure(ref err) => {
                 tcx.lift(err).map(super::ConstEvalFailure)
             }
+            super::Overflow => bug!() // FIXME: ape ConstEvalFailure?
         }
     }
 }
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 4f49b159ad3..3d154e43a9a 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -34,7 +34,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
 use mir::{self, Mir, interpret};
 use mir::interpret::{Value, PrimVal};
-use ty::subst::{Kind, Substs};
+use ty::subst::{Kind, Substs, Subst};
 use ty::ReprOptions;
 use ty::Instance;
 use traits;
@@ -1467,6 +1467,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.borrowck_mode().use_mir()
     }
 
+    /// If true, pattern variables for use in guards on match arms
+    /// will be bound as references to the data, and occurrences of
+    /// those variables in the guard expression will implicitly
+    /// dereference those bindings. (See rust-lang/rust#27282.)
+    pub fn all_pat_vars_are_implicit_refs_within_guards(self) -> bool {
+        self.borrowck_mode().use_mir()
+    }
+
     /// If true, we should enable two-phase borrows checks. This is
     /// done with either `-Ztwo-phase-borrows` or with
     /// `#![feature(nll)]`.
@@ -2119,7 +2127,7 @@ macro_rules! intern_method {
                                             $alloc_method:ident,
                                             $alloc_to_key:expr,
                                             $alloc_to_ret:expr,
-                                            $needs_infer:expr) -> $ty:ty) => {
+                                            $keep_in_local_tcx:expr) -> $ty:ty) => {
         impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> {
             pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
                 {
@@ -2137,7 +2145,7 @@ macro_rules! intern_method {
                 // HACK(eddyb) Depend on flags being accurate to
                 // determine that all contents are in the global tcx.
                 // See comments on Lift for why we can't use that.
-                if !($needs_infer)(&v) {
+                if !($keep_in_local_tcx)(&v) {
                     if !self.is_global() {
                         let v = unsafe {
                             mem::transmute(v)
@@ -2165,7 +2173,7 @@ macro_rules! intern_method {
 }
 
 macro_rules! direct_interners {
-    ($lt_tcx:tt, $($name:ident: $method:ident($needs_infer:expr) -> $ty:ty),+) => {
+    ($lt_tcx:tt, $($name:ident: $method:ident($keep_in_local_tcx:expr) -> $ty:ty),+) => {
         $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> {
             fn eq(&self, other: &Self) -> bool {
                 self.0 == other.0
@@ -2180,7 +2188,10 @@ macro_rules! direct_interners {
             }
         }
 
-        intern_method!($lt_tcx, $name: $method($ty, alloc, |x| x, |x| x, $needs_infer) -> $ty);)+
+        intern_method!(
+            $lt_tcx,
+            $name: $method($ty, alloc, |x| x, |x| x, $keep_in_local_tcx) -> $ty
+        );)+
     }
 }
 
@@ -2189,12 +2200,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
 }
 
 direct_interners!('tcx,
-    region: mk_region(|r| {
-        match r {
-            &ty::ReVar(_) | &ty::ReSkolemized(..) => true,
-            _ => false
-        }
-    }) -> RegionKind,
+    region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
     const_: mk_const(|c: &Const| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>
 );
 
@@ -2328,7 +2334,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
         let adt_def = self.adt_def(def_id);
-        let substs = self.mk_substs(iter::once(Kind::from(ty)));
+        let generics = self.generics_of(def_id);
+        let mut substs = vec![Kind::from(ty)];
+        // Add defaults for other generic params if there are some.
+        for def in generics.types.iter().skip(1) {
+            assert!(def.has_default);
+            let ty = self.type_of(def.def_id).subst(self, &substs);
+            substs.push(ty.into());
+        }
+        let substs = self.mk_substs(substs.into_iter());
         self.mk_ty(TyAdt(adt_def, substs))
     }
 
@@ -2471,7 +2485,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(0, keywords::SelfType.name().as_str())
+        self.mk_param(0, keywords::SelfType.name().as_interned_str())
     }
 
     pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index eb06852c65d..1793b5e1edb 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -43,8 +43,8 @@ use middle::const_val::ConstVal;
 use hir::def_id::DefId;
 use ty::{self, Binder, Ty, TyCtxt, TypeFlags};
 
+use rustc_data_structures::lazy_btree_map::LazyBTreeMap;
 use std::fmt;
-use std::collections::BTreeMap;
 use util::nodemap::FxHashSet;
 
 /// The TypeFoldable trait is implemented for every type that can be folded.
@@ -91,6 +91,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn needs_infer(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
     }
+    fn has_skol(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_RE_SKOL)
+    }
     fn needs_subst(&self) -> bool {
         self.has_type_flags(TypeFlags::NEEDS_SUBST)
     }
@@ -111,15 +114,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
         self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
     }
 
-    fn is_normalized_for_trans(&self) -> bool {
-        !self.has_type_flags(TypeFlags::HAS_RE_INFER |
-                             TypeFlags::HAS_FREE_REGIONS |
-                             TypeFlags::HAS_TY_INFER |
-                             TypeFlags::HAS_PARAMS |
-                             TypeFlags::HAS_NORMALIZABLE_PROJECTION |
-                             TypeFlags::HAS_TY_ERR |
-                             TypeFlags::HAS_SELF)
-    }
     /// Indicates whether this value references only 'global'
     /// types/lifetimes that are the same regardless of what fn we are
     /// in. This is used for caching. Errs on the side of returning
@@ -334,7 +328,7 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     current_depth: u32,
     fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
-    map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>
+    map: LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -349,7 +343,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn replace_late_bound_regions<T,F>(self,
         value: &Binder<T>,
         mut f: F)
-        -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+        -> (T, LazyBTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               T : TypeFoldable<'tcx>,
     {
@@ -462,7 +456,7 @@ impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> {
             tcx,
             current_depth: 1,
             fld_r,
-            map: BTreeMap::default()
+            map: LazyBTreeMap::default()
         }
     }
 }
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 2819141c81b..752b7f69a6a 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -14,7 +14,7 @@ use ty::{self, Ty, TyCtxt};
 use middle::cstore::{ExternCrate, ExternCrateSource};
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 
 use std::cell::Cell;
 
@@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         let visible_parent_map = self.visible_parent_map(LOCAL_CRATE);
 
-        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<InternedString>::new());
+        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<LocalInternedString>::new());
         loop {
             // If `cur_def` is a direct or injected extern crate, push the path to the crate
             // followed by the path to the item within the crate and return.
@@ -168,8 +168,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
 
             let data = cur_def_key.disambiguated_data.data;
-            let symbol =
-                data.get_opt_name().unwrap_or_else(|| Symbol::intern("<unnamed>").as_str());
+            let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
+                Symbol::intern("<unnamed>").as_str()
+            });
             cur_path.push(symbol);
 
             match visible_parent_map.get(&cur_def) {
@@ -221,7 +222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::GlobalMetaData(..) => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
-                buffer.push(&data.as_interned_str());
+                buffer.push(&data.as_interned_str().as_symbol().as_str());
             }
             DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index ef2a4246628..a319b341ebb 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -19,7 +19,6 @@ use std::cmp;
 use std::fmt;
 use std::i128;
 use std::mem;
-use std::ops::RangeInclusive;
 
 use ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -149,7 +148,7 @@ pub const FAT_PTR_ADDR: usize = 0;
 /// - For a slice, this is the length.
 pub const FAT_PTR_EXTRA: usize = 1;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
     SizeOverflow(Ty<'tcx>)
@@ -492,7 +491,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             ty::TyFloat(FloatTy::F64) => scalar(F64),
             ty::TyFnPtr(_) => {
                 let mut ptr = scalar_unit(Pointer);
-                ptr.valid_range.start = 1;
+                ptr.valid_range = 1..=*ptr.valid_range.end();
                 tcx.intern_layout(LayoutDetails::scalar(self, ptr))
             }
 
@@ -506,7 +505,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 let mut data_ptr = scalar_unit(Pointer);
                 if !ty.is_unsafe_ptr() {
-                    data_ptr.valid_range.start = 1;
+                    data_ptr.valid_range = 1..=*data_ptr.valid_range.end();
                 }
 
                 let pointee = tcx.normalize_erasing_regions(param_env, pointee);
@@ -524,7 +523,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     }
                     ty::TyDynamic(..) => {
                         let mut vtable = scalar_unit(Pointer);
-                        vtable.valid_range.start = 1;
+                        vtable.valid_range = 1..=*vtable.valid_range.end();
                         vtable
                     }
                     _ => return Err(LayoutError::Unknown(unsized_part))
@@ -751,8 +750,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                         match st.abi {
                             Abi::Scalar(ref mut scalar) |
                             Abi::ScalarPair(ref mut scalar, _) => {
-                                if scalar.valid_range.start == 0 {
-                                    scalar.valid_range.start = 1;
+                                if *scalar.valid_range.start() == 0 {
+                                    scalar.valid_range = 1..=*scalar.valid_range.end();
                                 }
                             }
                             _ => {}
@@ -788,18 +787,15 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                                 }
                             }
                         }
-                        if niche_variants.start > v {
-                            niche_variants.start = v;
-                        }
-                        niche_variants.end = v;
+                        niche_variants = *niche_variants.start().min(&v)..=v;
                     }
 
-                    if niche_variants.start > niche_variants.end {
+                    if niche_variants.start() > niche_variants.end() {
                         dataful_variant = None;
                     }
 
                     if let Some(i) = dataful_variant {
-                        let count = (niche_variants.end - niche_variants.start + 1) as u128;
+                        let count = (niche_variants.end() - niche_variants.start() + 1) as u128;
                         for (field_index, &field) in variants[i].iter().enumerate() {
                             let (offset, niche, niche_start) =
                                 match self.find_niche(field, count)? {
@@ -897,7 +893,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
 
                 // Create the set of structs that represent each variant.
-                let mut variants = variants.into_iter().enumerate().map(|(i, field_layouts)| {
+                let mut layout_variants = variants.iter().enumerate().map(|(i, field_layouts)| {
                     let mut st = univariant_uninterned(&field_layouts,
                         &def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?;
                     st.variants = Variants::Single { index: i };
@@ -944,11 +940,15 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 // We increase the size of the discriminant to avoid LLVM copying
                 // padding when it doesn't need to. This normally causes unaligned
                 // load/stores and excessive memcpy/memset operations. By using a
-                // bigger integer size, LLVM can be sure about it's contents and
+                // bigger integer size, LLVM can be sure about its contents and
                 // won't be so conservative.
 
                 // Use the initial field alignment
-                let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity);
+                let mut ity = if def.repr.c() || def.repr.int.is_some() {
+                    min_ity
+                } else {
+                    Integer::for_abi_align(dl, start_align).unwrap_or(min_ity)
+                };
 
                 // If the alignment is not larger than the chosen discriminant size,
                 // don't use the alignment as the final size.
@@ -958,7 +958,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     // Patch up the variants' first few fields.
                     let old_ity_size = min_ity.size();
                     let new_ity_size = ity.size();
-                    for variant in &mut variants {
+                    for variant in &mut layout_variants {
                         if variant.abi == Abi::Uninhabited {
                             continue;
                         }
@@ -985,15 +985,80 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     value: Int(ity, signed),
                     valid_range: (min as u128 & tag_mask)..=(max as u128 & tag_mask),
                 };
-                let abi = if tag.value.size(dl) == size {
-                    Abi::Scalar(tag.clone())
-                } else {
-                    Abi::Aggregate { sized: true }
-                };
+                let mut abi = Abi::Aggregate { sized: true };
+                if tag.value.size(dl) == size {
+                    abi = Abi::Scalar(tag.clone());
+                } else if !tag.is_bool() {
+                    // HACK(nox): Blindly using ScalarPair for all tagged enums
+                    // where applicable leads to Option<u8> being handled as {i1, i8},
+                    // which later confuses SROA and some loop optimisations,
+                    // ultimately leading to the repeat-trusted-len test
+                    // failing. We make the trade-off of using ScalarPair only
+                    // for types where the tag isn't a boolean.
+                    let mut common_prim = None;
+                    for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) {
+                        let offsets = match layout_variant.fields {
+                            FieldPlacement::Arbitrary { ref offsets, .. } => offsets,
+                            _ => bug!(),
+                        };
+                        let mut fields = field_layouts
+                            .iter()
+                            .zip(offsets)
+                            .filter(|p| !p.0.is_zst());
+                        let (field, offset) = match (fields.next(), fields.next()) {
+                            (None, None) => continue,
+                            (Some(pair), None) => pair,
+                            _ => {
+                                common_prim = None;
+                                break;
+                            }
+                        };
+                        let prim = match field.details.abi {
+                            Abi::Scalar(ref scalar) => scalar.value,
+                            _ => {
+                                common_prim = None;
+                                break;
+                            }
+                        };
+                        if let Some(pair) = common_prim {
+                            // This is pretty conservative. We could go fancier
+                            // by conflating things like i32 and u32, or even
+                            // realising that (u8, u8) could just cohabit with
+                            // u16 or even u32.
+                            if pair != (prim, offset) {
+                                common_prim = None;
+                                break;
+                            }
+                        } else {
+                            common_prim = Some((prim, offset));
+                        }
+                    }
+                    if let Some((prim, offset)) = common_prim {
+                        let pair = scalar_pair(tag.clone(), scalar_unit(prim));
+                        let pair_offsets = match pair.fields {
+                            FieldPlacement::Arbitrary {
+                                ref offsets,
+                                ref memory_index
+                            } => {
+                                assert_eq!(memory_index, &[0, 1]);
+                                offsets
+                            }
+                            _ => bug!()
+                        };
+                        if pair_offsets[0] == Size::from_bytes(0) &&
+                            pair_offsets[1] == *offset &&
+                            align == pair.align &&
+                            size == pair.size {
+                            // We can use `ScalarPair` only when it matches our
+                            // already computed layout (including `#[repr(C)]`).
+                            abi = pair.abi;
+                        }
+                    }
+                }
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Tagged {
                         discr: tag,
-                        variants
+                        variants: layout_variants,
                     },
                     fields: FieldPlacement::Arbitrary {
                         offsets: vec![Size::from_bytes(0)],
@@ -1594,10 +1659,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             let max_value = !0u128 >> (128 - bits);
 
             // Find out how many values are outside the valid range.
-            let niches = if v.start <= v.end {
-                v.start + (max_value - v.end)
+            let niches = if v.start() <= v.end() {
+                v.start() + (max_value - v.end())
             } else {
-                v.start - v.end - 1
+                v.start() - v.end() - 1
             };
 
             // Give up if we can't fit `count` consecutive niches.
@@ -1605,11 +1670,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 return None;
             }
 
-            let niche_start = v.end.wrapping_add(1) & max_value;
-            let niche_end = v.end.wrapping_add(count) & max_value;
+            let niche_start = v.end().wrapping_add(1) & max_value;
+            let niche_end = v.end().wrapping_add(count) & max_value;
             Some((offset, Scalar {
                 value,
-                valid_range: v.start..=niche_end
+                valid_range: *v.start()..=niche_end
             }, niche_start))
         };
 
@@ -1679,14 +1744,14 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
             }
             NicheFilling {
                 dataful_variant,
-                niche_variants: RangeInclusive { start, end },
+                ref niche_variants,
                 ref niche,
                 niche_start,
                 ref variants,
             } => {
                 dataful_variant.hash_stable(hcx, hasher);
-                start.hash_stable(hcx, hasher);
-                end.hash_stable(hcx, hasher);
+                niche_variants.start().hash_stable(hcx, hasher);
+                niche_variants.end().hash_stable(hcx, hasher);
                 niche.hash_stable(hcx, hasher);
                 niche_start.hash_stable(hcx, hasher);
                 variants.hash_stable(hcx, hasher);
@@ -1749,10 +1814,10 @@ impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
-        let Scalar { value, valid_range: RangeInclusive { start, end } } = *self;
+        let Scalar { value, ref valid_range } = *self;
         value.hash_stable(hcx, hasher);
-        start.hash_stable(hcx, hasher);
-        end.hash_stable(hcx, hasher);
+        valid_range.start().hash_stable(hcx, hasher);
+        valid_range.end().hash_stable(hcx, hasher);
     }
 }
 
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index 735fe06560f..57c8c4f34e7 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -9,24 +9,45 @@
 // except according to those terms.
 
 use dep_graph::SerializedDepNodeIndex;
+use dep_graph::DepNode;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use mir::interpret::{GlobalId};
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
 use ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::maps::queries;
+use ty::maps::Query;
+use ty::maps::QueryMap;
 
 use std::hash::Hash;
+use std::fmt::Debug;
 use syntax_pos::symbol::InternedString;
+use rustc_data_structures::sync::Lock;
+use rustc_data_structures::stable_hasher::HashStable;
+use ich::StableHashingContext;
 
 /// Query configuration and description traits.
 
-pub trait QueryConfig {
-    type Key: Eq + Hash + Clone;
-    type Value;
+pub trait QueryConfig<'tcx> {
+    const NAME: &'static str;
+
+    type Key: Eq + Hash + Clone + Debug;
+    type Value: Clone + for<'a> HashStable<StableHashingContext<'a>>;
+
+    fn query(key: Self::Key) -> Query<'tcx>;
+
+    // Don't use this method to access query results, instead use the methods on TyCtxt
+    fn query_map<'a>(tcx: TyCtxt<'a, 'tcx, '_>) -> &'a Lock<QueryMap<'tcx, Self>>;
+
+    fn to_dep_node(tcx: TyCtxt<'_, 'tcx, '_>, key: &Self::Key) -> DepNode;
+
+    // Don't use this method to compute query results, instead use the methods on TyCtxt
+    fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value;
+
+    fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value;
 }
 
-pub(super) trait QueryDescription<'tcx>: QueryConfig {
+pub trait QueryDescription<'tcx>: QueryConfig<'tcx> {
     fn describe(tcx: TyCtxt, key: Self::Key) -> String;
 
     #[inline]
@@ -41,7 +62,7 @@ pub(super) trait QueryDescription<'tcx>: QueryConfig {
     }
 }
 
-impl<'tcx, M: QueryConfig<Key=DefId>> QueryDescription<'tcx> for M {
+impl<'tcx, M: QueryConfig<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
     default fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         if !tcx.sess.verbose() {
             format!("processing `{}`", tcx.item_path_str(def_id))
@@ -73,6 +94,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_region
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
+    fn describe(_tcx: TyCtxt, goal: CanonicalPredicateGoal<'tcx>) -> String {
+        format!("evaluating trait selection obligation `{}`", goal.value.value)
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
     fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
         format!("computing whether `{}` is `Copy`", env.value)
diff --git a/src/librustc/ty/maps/job.rs b/src/librustc/ty/maps/job.rs
index 374406158c1..3b6af018d6b 100644
--- a/src/librustc/ty/maps/job.rs
+++ b/src/librustc/ty/maps/job.rs
@@ -17,13 +17,10 @@ use ty::context::TyCtxt;
 use errors::Diagnostic;
 
 /// Indicates the state of a query for a given key in a query map
-pub(super) enum QueryResult<'tcx, T> {
+pub(super) enum QueryResult<'tcx> {
     /// An already executing query. The query job can be used to await for its completion
     Started(Lrc<QueryJob<'tcx>>),
 
-    /// The query is complete and produced `T`
-    Complete(T),
-
     /// The query panicked. Queries trying to wait on this will raise a fatal error / silently panic
     Poisoned,
 }
diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs
index 72f2cb49abc..da29f23589e 100644
--- a/src/librustc/ty/maps/keys.rs
+++ b/src/librustc/ty/maps/keys.rs
@@ -11,7 +11,7 @@
 //! Defines the set of legal keys that can be used in queries.
 
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
@@ -200,3 +200,13 @@ impl<'tcx> Key for CanonicalTyGoal<'tcx> {
         DUMMY_SP
     }
 }
+
+impl<'tcx> Key for CanonicalPredicateGoal<'tcx> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+
+    fn default_span(&self, _tcx: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index f5cb3643de8..d89846a75ef 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use dep_graph::{DepConstructor, DepNode};
-use errors::DiagnosticBuilder;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use hir::def::{Def, Export};
 use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs};
@@ -32,8 +31,9 @@ use mir;
 use mir::interpret::{GlobalId};
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
-use traits::Vtable;
-use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution};
+use traits::{self, Vtable};
+use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
+                    CanonicalTyGoal, NoSolution};
 use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
@@ -42,7 +42,7 @@ use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use ty::steal::Steal;
 use ty::subst::Substs;
 use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
-use util::common::{profq_msg, ErrorReported, ProfileQueriesMsg};
+use util::common::{ErrorReported};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_target::spec::PanicStrategy;
@@ -67,7 +67,6 @@ pub use self::plumbing::force_from_dep_node;
 
 mod job;
 pub use self::job::{QueryJob, QueryInfo};
-use self::job::QueryResult;
 
 mod keys;
 pub use self::keys::Key;
@@ -212,7 +211,7 @@ define_maps! { <'tcx>
 
     /// Borrow checks the function body. If this is a closure, returns
     /// additional requirements that the closure's creator must verify.
-    [] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements<'tcx>>,
+    [] fn mir_borrowck: MirBorrowCheck(DefId) -> mir::BorrowCheckResult<'tcx>,
 
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
@@ -433,6 +432,12 @@ define_maps! { <'tcx>
         NoSolution,
     >,
 
+    /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
+    /// `infcx.predicate_must_hold()` instead.
+    [] fn evaluate_obligation: EvaluateObligation(
+        CanonicalPredicateGoal<'tcx>
+    ) -> Result<traits::EvaluationResult, traits::OverflowError>,
+
     [] fn substitute_normalize_and_test_predicates:
         substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
 
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
index f88e33c708e..cea2a03fd53 100644
--- a/src/librustc/ty/maps/on_disk_cache.rs
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -30,7 +30,6 @@ use syntax::codemap::{CodeMap, StableFilemapId};
 use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap};
 use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
 use ty;
-use ty::maps::job::QueryResult;
 use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use ty::context::TyCtxt;
 use util::common::time;
@@ -239,14 +238,12 @@ impl<'sess> OnDiskCache<'sess> {
                 encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
 
                 // const eval is special, it only encodes successfully evaluated constants
-                use ty::maps::plumbing::GetCacheInternal;
-                for (key, entry) in const_eval::get_cache_internal(tcx).map.iter() {
+                use ty::maps::QueryConfig;
+                let map = const_eval::query_map(tcx).borrow();
+                assert!(map.active.is_empty());
+                for (key, entry) in map.results.iter() {
                     use ty::maps::config::QueryDescription;
                     if const_eval::cache_on_disk(key.clone()) {
-                        let entry = match *entry {
-                            QueryResult::Complete(ref v) => v,
-                            _ => panic!("incomplete query"),
-                        };
                         if let Ok(ref value) = entry.value {
                             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
@@ -1124,7 +1121,7 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               encoder: &mut CacheEncoder<'enc, 'a, 'tcx, E>,
                                               query_result_index: &mut EncodedQueryResultIndex)
                                               -> Result<(), E::Error>
-    where Q: super::plumbing::GetCacheInternal<'tcx>,
+    where Q: super::config::QueryDescription<'tcx>,
           E: 'enc + TyEncoder,
           Q::Value: Encodable,
 {
@@ -1133,12 +1130,10 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     time(tcx.sess, desc, || {
 
-    for (key, entry) in Q::get_cache_internal(tcx).map.iter() {
+    let map = Q::query_map(tcx).borrow();
+    assert!(map.active.is_empty());
+    for (key, entry) in map.results.iter() {
         if Q::cache_on_disk(key.clone()) {
-            let entry = match *entry {
-                QueryResult::Complete(ref v) => v,
-                _ => panic!("incomplete query"),
-            };
             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
             // Record position of the cache entry
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 61a4eb58531..37950463f74 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -15,21 +15,29 @@
 use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
 use errors::DiagnosticBuilder;
 use errors::Level;
+use errors::Diagnostic;
+use errors::FatalError;
 use ty::tls;
 use ty::{TyCtxt};
 use ty::maps::Query;
+use ty::maps::config::QueryConfig;
 use ty::maps::config::QueryDescription;
-use ty::maps::job::{QueryResult, QueryInfo};
+use ty::maps::job::{QueryJob, QueryResult, QueryInfo};
 use ty::item_path;
 
+use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg};
+
 use rustc_data_structures::fx::{FxHashMap};
-use rustc_data_structures::sync::LockGuard;
-use std::marker::PhantomData;
+use rustc_data_structures::sync::{Lrc, Lock};
+use std::mem;
+use std::ptr;
+use std::collections::hash_map::Entry;
 use syntax_pos::Span;
+use syntax::codemap::DUMMY_SP;
 
-pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> {
-    phantom: PhantomData<(D, &'tcx ())>,
-    pub(super) map: FxHashMap<D::Key, QueryResult<'tcx, QueryValue<D::Value>>>,
+pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> {
+    pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
+    pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
 }
 
 pub(super) struct QueryValue<T> {
@@ -48,18 +56,166 @@ impl<T> QueryValue<T> {
     }
 }
 
-impl<'tcx, M: QueryDescription<'tcx>> QueryMap<'tcx, M> {
+impl<'tcx, M: QueryConfig<'tcx>> QueryMap<'tcx, M> {
     pub(super) fn new() -> QueryMap<'tcx, M> {
         QueryMap {
-            phantom: PhantomData,
-            map: FxHashMap(),
+            results: FxHashMap(),
+            active: FxHashMap(),
+        }
+    }
+}
+
+// If enabled, send a message to the profile-queries thread
+macro_rules! profq_msg {
+    ($tcx:expr, $msg:expr) => {
+        if cfg!(debug_assertions) {
+            if $tcx.sess.profile_queries() {
+                profq_msg($tcx.sess, $msg)
+            }
+        }
+    }
+}
+
+// If enabled, format a key using its debug string, which can be
+// expensive to compute (in terms of time).
+macro_rules! profq_query_msg {
+    ($query:expr, $tcx:expr, $key:expr) => {{
+        let msg = if cfg!(debug_assertions) {
+            if $tcx.sess.profile_queries_and_keys() {
+                Some(format!("{:?}", $key))
+            } else { None }
+        } else { None };
+        QueryMsg {
+            query: $query,
+            msg,
+        }
+    }}
+}
+
+/// A type representing the responsibility to execute the job in the `job` field.
+/// This will poison the relevant query if dropped.
+pub(super) struct JobOwner<'a, 'tcx: 'a, Q: QueryDescription<'tcx> + 'a> {
+    map: &'a Lock<QueryMap<'tcx, Q>>,
+    key: Q::Key,
+    job: Lrc<QueryJob<'tcx>>,
+}
+
+impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
+    /// Either gets a JobOwner corresponding the the query, allowing us to
+    /// start executing the query, or it returns with the result of the query.
+    /// If the query is executing elsewhere, this will wait for it.
+    /// If the query panicked, this will silently panic.
+    pub(super) fn try_get(
+        tcx: TyCtxt<'a, 'tcx, '_>,
+        span: Span,
+        key: &Q::Key,
+    ) -> TryGetJob<'a, 'tcx, Q> {
+        let map = Q::query_map(tcx);
+        loop {
+            let mut lock = map.borrow_mut();
+            if let Some(value) = lock.results.get(key) {
+                profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                let result = Ok((value.value.clone(), value.index));
+                return TryGetJob::JobCompleted(result);
+            }
+            let job = match lock.active.entry((*key).clone()) {
+                Entry::Occupied(entry) => {
+                    match *entry.get() {
+                        QueryResult::Started(ref job) => job.clone(),
+                        QueryResult::Poisoned => FatalError.raise(),
+                    }
+                }
+                Entry::Vacant(entry) => {
+                    // No job entry for this query. Return a new one to be started later
+                    return tls::with_related_context(tcx, |icx| {
+                        let info = QueryInfo {
+                            span,
+                            query: Q::query(key.clone()),
+                        };
+                        let job = Lrc::new(QueryJob::new(info, icx.query.clone()));
+                        let owner = JobOwner {
+                            map,
+                            job: job.clone(),
+                            key: (*key).clone(),
+                        };
+                        entry.insert(QueryResult::Started(job));
+                        TryGetJob::NotYetStarted(owner)
+                    })
+                }
+            };
+            mem::drop(lock);
+
+            if let Err(cycle) = job.await(tcx, span) {
+                return TryGetJob::JobCompleted(Err(cycle));
+            }
+        }
+    }
+
+    /// Completes the query by updating the query map with the `result`,
+    /// signals the waiter and forgets the JobOwner, so it won't poison the query
+    pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) {
+        // We can move out of `self` here because we `mem::forget` it below
+        let key = unsafe { ptr::read(&self.key) };
+        let job = unsafe { ptr::read(&self.job) };
+        let map = self.map;
+
+        // Forget ourself so our destructor won't poison the query
+        mem::forget(self);
+
+        let value = QueryValue::new(result.clone(), dep_node_index);
+        {
+            let mut lock = map.borrow_mut();
+            lock.active.remove(&key);
+            lock.results.insert(key, value);
         }
+
+        job.signal_complete();
+    }
+
+    /// Executes a job by changing the ImplicitCtxt to point to the
+    /// new query job while it executes. It returns the diagnostics
+    /// captured during execution and the actual result.
+    pub(super) fn start<'lcx, F, R>(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, 'lcx>,
+        compute: F)
+    -> (R, Vec<Diagnostic>)
+    where
+        F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R
+    {
+        // The TyCtxt stored in TLS has the same global interner lifetime
+        // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
+        // when accessing the ImplicitCtxt
+        let r = tls::with_related_context(tcx, move |current_icx| {
+            // Update the ImplicitCtxt to point to our new query job
+            let new_icx = tls::ImplicitCtxt {
+                tcx,
+                query: Some(self.job.clone()),
+                layout_depth: current_icx.layout_depth,
+                task: current_icx.task,
+            };
+
+            // Use the ImplicitCtxt while we execute the query
+            tls::enter_context(&new_icx, |_| {
+                compute(tcx)
+            })
+        });
+
+        // Extract the diagnostic from the job
+        let diagnostics = mem::replace(&mut *self.job.diagnostics.lock(), Vec::new());
+
+        (r, diagnostics)
     }
 }
 
-pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
-    fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                              -> LockGuard<'a, QueryMap<'tcx, Self>>;
+impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
+    fn drop(&mut self) {
+        // Poison the query so jobs waiting on it panic
+        self.map.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned);
+        // Also signal the completion of the job, so waiters
+        // will continue execution
+        self.job.signal_complete();
+    }
 }
 
 #[derive(Clone)]
@@ -70,14 +226,14 @@ pub(super) struct CycleError<'tcx> {
 }
 
 /// The result of `try_get_lock`
-pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
+pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> {
     /// The query is not yet started. Contains a guard to the map eventually used to start it.
-    NotYetStarted(LockGuard<'a, QueryMap<'tcx, D>>),
+    NotYetStarted(JobOwner<'a, 'tcx, D>),
 
     /// The query was already completed.
     /// Returns the result of the query and its dep node index
     /// if it succeeded or a cycle error if it failed
-    JobCompleted(Result<(T, DepNodeIndex), CycleError<'tcx>>),
+    JobCompleted(Result<(D::Value, DepNodeIndex), CycleError<'tcx>>),
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -180,28 +336,277 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
         }
     }
-}
 
-// If enabled, send a message to the profile-queries thread
-macro_rules! profq_msg {
-    ($tcx:expr, $msg:expr) => {
-        if cfg!(debug_assertions) {
-            if $tcx.sess.profile_queries() {
-                profq_msg($tcx.sess, $msg)
+    fn try_get_with<Q: QueryDescription<'gcx>>(
+        self,
+        span: Span,
+        key: Q::Key)
+    -> Result<Q::Value, CycleError<'gcx>>
+    {
+        debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
+               Q::NAME,
+               key,
+               span);
+
+        profq_msg!(self,
+            ProfileQueriesMsg::QueryBegin(
+                span.data(),
+                profq_query_msg!(Q::NAME, self, key),
+            )
+        );
+
+        let job = match JobOwner::try_get(self, span, &key) {
+            TryGetJob::NotYetStarted(job) => job,
+            TryGetJob::JobCompleted(result) => {
+                return result.map(|(v, index)| {
+                    self.dep_graph.read_index(index);
+                    v
+                })
             }
+        };
+
+        // Fast path for when incr. comp. is off. `to_dep_node` is
+        // expensive for some DepKinds.
+        if !self.dep_graph.is_fully_enabled() {
+            let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
+            return self.force_query_with_job::<Q>(key, job, null_dep_node).map(|(v, _)| v);
+        }
+
+        let dep_node = Q::to_dep_node(self, &key);
+
+        if dep_node.kind.is_anon() {
+            profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+
+            let res = job.start(self, |tcx| {
+                tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                    Q::compute(tcx.global_tcx(), key)
+                })
+            });
+
+            profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
+            let ((result, dep_node_index), diagnostics) = res;
+
+            self.dep_graph.read_index(dep_node_index);
+
+            self.on_disk_query_result_cache
+                .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
+
+            job.complete(&result, dep_node_index);
+
+            return Ok(result);
+        }
+
+        if !dep_node.kind.is_input() {
+            if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
+                profq_msg!(self, ProfileQueriesMsg::CacheHit);
+                return self.load_from_disk_and_cache_in_memory::<Q>(key,
+                                                                    job,
+                                                                    dep_node_index,
+                                                                    &dep_node)
+            }
+        }
+
+        match self.force_query_with_job::<Q>(key, job, dep_node) {
+            Ok((result, dep_node_index)) => {
+                self.dep_graph.read_index(dep_node_index);
+                Ok(result)
+            }
+            Err(e) => Err(e)
         }
     }
-}
 
-// If enabled, format a key using its debug string, which can be
-// expensive to compute (in terms of time).
-macro_rules! profq_key {
-    ($tcx:expr, $key:expr) => {
-        if cfg!(debug_assertions) {
-            if $tcx.sess.profile_queries_and_keys() {
-                Some(format!("{:?}", $key))
-            } else { None }
-        } else { None }
+    fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
+        self,
+        key: Q::Key,
+        job: JobOwner<'a, 'gcx, Q>,
+        dep_node_index: DepNodeIndex,
+        dep_node: &DepNode
+    ) -> Result<Q::Value, CycleError<'gcx>>
+    {
+        // Note this function can be called concurrently from the same query
+        // We must ensure that this is handled correctly
+
+        debug_assert!(self.dep_graph.is_green(dep_node));
+
+        // First we try to load the result from the on-disk cache
+        let result = if Q::cache_on_disk(key.clone()) &&
+                        self.sess.opts.debugging_opts.incremental_queries {
+            let prev_dep_node_index =
+                self.dep_graph.prev_dep_node_index_of(dep_node);
+            let result = Q::try_load_from_disk(self.global_tcx(),
+                                                    prev_dep_node_index);
+
+            // We always expect to find a cached result for things that
+            // can be forced from DepNode.
+            debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
+                            result.is_some(),
+                            "Missing on-disk cache entry for {:?}",
+                            dep_node);
+            result
+        } else {
+            // Some things are never cached on disk.
+            None
+        };
+
+        let result = if let Some(result) = result {
+            result
+        } else {
+            // We could not load a result from the on-disk cache, so
+            // recompute.
+
+            // The diagnostics for this query have already been
+            // promoted to the current session during
+            // try_mark_green(), so we can ignore them here.
+            let (result, _) = job.start(self, |tcx| {
+                // The dep-graph for this computation is already in
+                // place
+                tcx.dep_graph.with_ignore(|| {
+                    Q::compute(tcx, key)
+                })
+            });
+            result
+        };
+
+        // If -Zincremental-verify-ich is specified, re-hash results from
+        // the cache and make sure that they have the expected fingerprint.
+        if self.sess.opts.debugging_opts.incremental_verify_ich {
+            use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+            use ich::Fingerprint;
+
+            assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
+                    self.dep_graph.prev_fingerprint_of(dep_node),
+                    "Fingerprint for green query instance not loaded \
+                        from cache: {:?}", dep_node);
+
+            debug!("BEGIN verify_ich({:?})", dep_node);
+            let mut hcx = self.create_stable_hashing_context();
+            let mut hasher = StableHasher::new();
+
+            result.hash_stable(&mut hcx, &mut hasher);
+
+            let new_hash: Fingerprint = hasher.finish();
+            debug!("END verify_ich({:?})", dep_node);
+
+            let old_hash = self.dep_graph.fingerprint_of(dep_node_index);
+
+            assert!(new_hash == old_hash, "Found unstable fingerprints \
+                for {:?}", dep_node);
+        }
+
+        if self.sess.opts.debugging_opts.query_dep_graph {
+            self.dep_graph.mark_loaded_from_cache(dep_node_index, true);
+        }
+
+        job.complete(&result, dep_node_index);
+
+        Ok(result)
+    }
+
+    fn force_query_with_job<Q: QueryDescription<'gcx>>(
+        self,
+        key: Q::Key,
+        job: JobOwner<'_, 'gcx, Q>,
+        dep_node: DepNode)
+    -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> {
+        // If the following assertion triggers, it can have two reasons:
+        // 1. Something is wrong with DepNode creation, either here or
+        //    in DepGraph::try_mark_green()
+        // 2. Two distinct query keys get mapped to the same DepNode
+        //    (see for example #48923)
+        assert!(!self.dep_graph.dep_node_exists(&dep_node),
+                "Forcing query with already existing DepNode.\n\
+                    - query-key: {:?}\n\
+                    - dep-node: {:?}",
+                key, dep_node);
+
+        profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+        let res = job.start(self, |tcx| {
+            if dep_node.kind.is_eval_always() {
+                tcx.dep_graph.with_eval_always_task(dep_node,
+                                                    tcx,
+                                                    key,
+                                                    Q::compute)
+            } else {
+                tcx.dep_graph.with_task(dep_node,
+                                        tcx,
+                                        key,
+                                        Q::compute)
+            }
+        });
+        profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
+
+        let ((result, dep_node_index), diagnostics) = res;
+
+        if self.sess.opts.debugging_opts.query_dep_graph {
+            self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
+        }
+
+        if dep_node.kind != ::dep_graph::DepKind::Null {
+            self.on_disk_query_result_cache
+                .store_diagnostics(dep_node_index, diagnostics);
+        }
+
+        job.complete(&result, dep_node_index);
+
+        Ok((result, dep_node_index))
+    }
+
+    /// Ensure that either this query has all green inputs or been executed.
+    /// Executing query::ensure(D) is considered a read of the dep-node D.
+    ///
+    /// This function is particularly useful when executing passes for their
+    /// side-effects -- e.g., in order to report errors for erroneous programs.
+    ///
+    /// Note: The optimization is only available during incr. comp.
+    pub fn ensure_query<Q: QueryDescription<'gcx>>(self, key: Q::Key) -> () {
+        let dep_node = Q::to_dep_node(self, &key);
+
+        // Ensuring an "input" or anonymous query makes no sense
+        assert!(!dep_node.kind.is_anon());
+        assert!(!dep_node.kind.is_input());
+        if self.try_mark_green_and_read(&dep_node).is_none() {
+            // A None return from `try_mark_green_and_read` means that this is either
+            // a new dep node or that the dep node has already been marked red.
+            // Either way, we can't call `dep_graph.read()` as we don't have the
+            // DepNodeIndex. We must invoke the query itself. The performance cost
+            // this introduces should be negligible as we'll immediately hit the
+            // in-memory cache, or another query down the line will.
+            let _ = self.get_query::<Q>(DUMMY_SP, key);
+        }
+    }
+
+    #[allow(dead_code)]
+    fn force_query<Q: QueryDescription<'gcx>>(
+        self,
+        key: Q::Key,
+        span: Span,
+        dep_node: DepNode
+    ) -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> {
+        // We may be concurrently trying both execute and force a query
+        // Ensure that only one of them runs the query
+        let job = match JobOwner::try_get(self, span, &key) {
+            TryGetJob::NotYetStarted(job) => job,
+            TryGetJob::JobCompleted(result) => return result,
+        };
+        self.force_query_with_job::<Q>(key, job, dep_node)
+    }
+
+    pub fn try_get_query<Q: QueryDescription<'gcx>>(
+        self,
+        span: Span,
+        key: Q::Key
+    ) -> Result<Q::Value, DiagnosticBuilder<'a>> {
+        match self.try_get_with::<Q>(span, key) {
+            Ok(e) => Ok(e),
+            Err(e) => Err(self.report_cycle(e)),
+        }
+    }
+
+    pub fn get_query<Q: QueryDescription<'gcx>>(self, span: Span, key: Q::Key) -> Q::Value {
+        self.try_get_query::<Q>(span, key).unwrap_or_else(|mut e| {
+            e.emit();
+            Q::handle_cycle_error(self)
+        })
     }
 }
 
@@ -210,7 +615,7 @@ macro_rules! handle_cycle_error {
         Value::from_cycle_error($this.global_tcx())
     }};
     ([fatal_cycle$(, $modifiers:ident)*][$this:expr]) => {{
-        $this.tcx.sess.abort_if_errors();
+        $this.sess.abort_if_errors();
         unreachable!();
     }};
     ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => {
@@ -223,12 +628,7 @@ macro_rules! define_maps {
      $($(#[$attr:meta])*
        [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
 
-        use dep_graph::DepNodeIndex;
-        use std::mem;
-        use errors::Diagnostic;
-        use errors::FatalError;
-        use rustc_data_structures::sync::{Lock, LockGuard};
-        use rustc_data_structures::OnDrop;
+        use rustc_data_structures::sync::Lock;
 
         define_map_struct! {
             tcx: $tcx,
@@ -251,12 +651,6 @@ macro_rules! define_maps {
             $($(#[$attr])* $name($K)),*
         }
 
-        #[allow(bad_style)]
-        #[derive(Clone, Debug, PartialEq, Eq)]
-        pub enum QueryMsg {
-            $($name(Option<String>)),*
-        }
-
         impl<$tcx> Query<$tcx> {
             pub fn name(&self) -> &'static str {
                 match *self {
@@ -303,162 +697,38 @@ macro_rules! define_maps {
             })*
         }
 
-        $(impl<$tcx> QueryConfig for queries::$name<$tcx> {
+        $(impl<$tcx> QueryConfig<$tcx> for queries::$name<$tcx> {
             type Key = $K;
             type Value = $V;
-        }
 
-        impl<$tcx> GetCacheInternal<$tcx> for queries::$name<$tcx> {
-            fn get_cache_internal<'a>(tcx: TyCtxt<'a, $tcx, $tcx>)
-                                      -> LockGuard<'a, QueryMap<$tcx, Self>> {
-                tcx.maps.$name.borrow()
+            const NAME: &'static str = stringify!($name);
+
+            fn query(key: Self::Key) -> Query<'tcx> {
+                Query::$name(key)
             }
-        }
 
-        impl<'a, $tcx, 'lcx> queries::$name<$tcx> {
+            fn query_map<'a>(tcx: TyCtxt<'a, $tcx, '_>) -> &'a Lock<QueryMap<$tcx, Self>> {
+                &tcx.maps.$name
+            }
 
             #[allow(unused)]
-            fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode {
+            fn to_dep_node(tcx: TyCtxt<'_, $tcx, '_>, key: &Self::Key) -> DepNode {
                 use dep_graph::DepConstructor::*;
 
                 DepNode::new(tcx, $node(*key))
             }
 
-            /// Either get the lock of the query map, allowing us to
-            /// start executing the query, or it returns with the result of the query.
-            /// If the query already executed and panicked, this will fatal error / silently panic
-            fn try_get_lock(
-                tcx: TyCtxt<'a, $tcx, 'lcx>,
-                span: Span,
-                key: &$K
-            ) -> TryGetLock<'a, $tcx, $V, Self>
-            {
-                loop {
-                    let lock = tcx.maps.$name.borrow_mut();
-                    let job = if let Some(value) = lock.map.get(key) {
-                        match *value {
-                            QueryResult::Started(ref job) => Some(job.clone()),
-                            QueryResult::Complete(ref value) => {
-                                profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                                let result = Ok(((&value.value).clone(), value.index));
-                                return TryGetLock::JobCompleted(result);
-                            },
-                            QueryResult::Poisoned => FatalError.raise(),
-                        }
-                    } else {
-                        None
-                    };
-                    let job = if let Some(job) = job {
-                        job
-                    } else {
-                        return TryGetLock::NotYetStarted(lock);
-                    };
-                    mem::drop(lock);
-
-                    if let Err(cycle) = job.await(tcx, span) {
-                        return TryGetLock::JobCompleted(Err(cycle));
-                    }
-                }
+            fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value {
+                let provider = tcx.maps.providers[key.map_crate()].$name;
+                provider(tcx.global_tcx(), key)
             }
 
-            fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                            span: Span,
-                            key: $K)
-                            -> Result<$V, CycleError<$tcx>>
-            {
-                debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
-                       stringify!($name),
-                       key,
-                       span);
-
-                profq_msg!(tcx,
-                    ProfileQueriesMsg::QueryBegin(
-                        span.data(),
-                        QueryMsg::$name(profq_key!(tcx, key))
-                    )
-                );
-
-                /// Get the lock used to start the query or
-                /// return the result of the completed query
-                macro_rules! get_lock_or_return {
-                    () => {{
-                        match Self::try_get_lock(tcx, span, &key) {
-                            TryGetLock::NotYetStarted(lock) => lock,
-                            TryGetLock::JobCompleted(result) => {
-                                return result.map(|(v, index)| {
-                                    tcx.dep_graph.read_index(index);
-                                    v
-                                })
-                            }
-                        }
-                    }}
-                }
-
-                let mut lock = get_lock_or_return!();
-
-                // Fast path for when incr. comp. is off. `to_dep_node` is
-                // expensive for some DepKinds.
-                if !tcx.dep_graph.is_fully_enabled() {
-                    let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
-                    return Self::force_with_lock(tcx, key, span, lock, null_dep_node)
-                                .map(|(v, _)| v);
-                }
-
-                let dep_node = Self::to_dep_node(tcx, &key);
-
-                if dep_node.kind.is_anon() {
-                    profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
-
-                    let res = Self::start_job(tcx, span, key, lock, |tcx| {
-                        tcx.dep_graph.with_anon_task(dep_node.kind, || {
-                            Self::compute_result(tcx.global_tcx(), key)
-                        })
-                    })?;
-
-                    profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
-                    let (((result, dep_node_index), diagnostics), job) = res;
-
-                    tcx.dep_graph.read_index(dep_node_index);
-
-                    tcx.on_disk_query_result_cache
-                       .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
-
-                    let value = QueryValue::new(Clone::clone(&result), dep_node_index);
-
-                    tcx.maps
-                       .$name
-                       .borrow_mut()
-                       .map
-                       .insert(key, QueryResult::Complete(value));
-
-                    job.signal_complete();
-
-                    return Ok(result);
-                }
-
-                if !dep_node.kind.is_input() {
-                    // try_mark_green_and_read may force queries. So we must drop our lock here
-                    mem::drop(lock);
-                    if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) {
-                        profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                        return Self::load_from_disk_and_cache_in_memory(tcx,
-                                                                        key,
-                                                                        span,
-                                                                        dep_node_index,
-                                                                        &dep_node)
-                    }
-                    lock = get_lock_or_return!();
-                }
-
-                match Self::force_with_lock(tcx, key, span, lock, dep_node) {
-                    Ok((result, dep_node_index)) => {
-                        tcx.dep_graph.read_index(dep_node_index);
-                        Ok(result)
-                    }
-                    Err(e) => Err(e)
-                }
+            fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value {
+                handle_cycle_error!([$($modifiers)*][tcx])
             }
+        }
 
+        impl<'a, $tcx, 'lcx> queries::$name<$tcx> {
             /// Ensure that either this query has all green inputs or been executed.
             /// Executing query::ensure(D) is considered a read of the dep-node D.
             ///
@@ -467,282 +737,7 @@ macro_rules! define_maps {
             ///
             /// Note: The optimization is only available during incr. comp.
             pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () {
-                let dep_node = Self::to_dep_node(tcx, &key);
-
-                // Ensuring an "input" or anonymous query makes no sense
-                assert!(!dep_node.kind.is_anon());
-                assert!(!dep_node.kind.is_input());
-                if tcx.try_mark_green_and_read(&dep_node).is_none() {
-                    // A None return from `try_mark_green_and_read` means that this is either
-                    // a new dep node or that the dep node has already been marked red.
-                    // Either way, we can't call `dep_graph.read()` as we don't have the
-                    // DepNodeIndex. We must invoke the query itself. The performance cost
-                    // this introduces should be negligible as we'll immediately hit the
-                    // in-memory cache, or another query down the line will.
-                    let _ = tcx.$name(key);
-                }
-            }
-
-            /// Creates a job for the query and updates the query map indicating that it started.
-            /// Then it changes ImplicitCtxt to point to the new query job while it executes.
-            /// If the query panics, this updates the query map to indicate so.
-            fn start_job<F, R>(tcx: TyCtxt<'_, $tcx, 'lcx>,
-                               span: Span,
-                               key: $K,
-                               mut map: LockGuard<'_, QueryMap<$tcx, Self>>,
-                               compute: F)
-                -> Result<((R, Vec<Diagnostic>), Lrc<QueryJob<$tcx>>), CycleError<$tcx>>
-                where F: for<'b> FnOnce(TyCtxt<'b, $tcx, 'lcx>) -> R
-            {
-                let query = Query::$name(Clone::clone(&key));
-
-                let entry = QueryInfo {
-                    span,
-                    query,
-                };
-
-                // The TyCtxt stored in TLS has the same global interner lifetime
-                // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
-                // when accessing the ImplicitCtxt
-                let (r, job) = ty::tls::with_related_context(tcx, move |icx| {
-                    let job = Lrc::new(QueryJob::new(entry, icx.query.clone()));
-
-                    // Store the job in the query map and drop the lock to allow
-                    // others to wait it
-                    map.map.entry(key).or_insert(QueryResult::Started(job.clone()));
-                    mem::drop(map);
-
-                    let r = {
-                        let on_drop = OnDrop(|| {
-                            // Poison the query so jobs waiting on it panic
-                            tcx.maps
-                            .$name
-                            .borrow_mut()
-                            .map
-                            .insert(key, QueryResult::Poisoned);
-                            // Also signal the completion of the job, so waiters
-                            // will continue execution
-                            job.signal_complete();
-                        });
-
-                        // Update the ImplicitCtxt to point to our new query job
-                        let icx = ty::tls::ImplicitCtxt {
-                            tcx,
-                            query: Some(job.clone()),
-                            layout_depth: icx.layout_depth,
-                            task: icx.task,
-                        };
-
-                        // Use the ImplicitCtxt while we execute the query
-                        let r = ty::tls::enter_context(&icx, |icx| {
-                            compute(icx.tcx)
-                        });
-
-                        mem::forget(on_drop);
-
-                        r
-                    };
-
-                    (r, job)
-                });
-
-                // Extract the diagnostic from the job
-                let diagnostics: Vec<_> = mem::replace(&mut *job.diagnostics.lock(), Vec::new());
-
-                Ok(((r, diagnostics), job))
-            }
-
-            fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
-                let provider = tcx.maps.providers[key.map_crate()].$name;
-                provider(tcx.global_tcx(), key)
-            }
-
-            fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                                                  key: $K,
-                                                  span: Span,
-                                                  dep_node_index: DepNodeIndex,
-                                                  dep_node: &DepNode)
-                                                  -> Result<$V, CycleError<$tcx>>
-            {
-                // Note this function can be called concurrently from the same query
-                // We must ensure that this is handled correctly
-
-                debug_assert!(tcx.dep_graph.is_green(dep_node));
-
-                // First we try to load the result from the on-disk cache
-                let result = if Self::cache_on_disk(key) &&
-                                tcx.sess.opts.debugging_opts.incremental_queries {
-                    let prev_dep_node_index =
-                        tcx.dep_graph.prev_dep_node_index_of(dep_node);
-                    let result = Self::try_load_from_disk(tcx.global_tcx(),
-                                                          prev_dep_node_index);
-
-                    // We always expect to find a cached result for things that
-                    // can be forced from DepNode.
-                    debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
-                                  result.is_some(),
-                                  "Missing on-disk cache entry for {:?}",
-                                  dep_node);
-                    result
-                } else {
-                    // Some things are never cached on disk.
-                    None
-                };
-
-                let (result, job) = if let Some(result) = result {
-                    (result, None)
-                } else {
-                    // We could not load a result from the on-disk cache, so
-                    // recompute.
-
-                    // The diagnostics for this query have already been
-                    // promoted to the current session during
-                    // try_mark_green(), so we can ignore them here.
-                    let ((result, _), job) = Self::start_job(tcx,
-                                                             span,
-                                                             key,
-                                                             tcx.maps.$name.borrow_mut(),
-                                                             |tcx| {
-                        // The dep-graph for this computation is already in
-                        // place
-                        tcx.dep_graph.with_ignore(|| {
-                            Self::compute_result(tcx, key)
-                        })
-                    })?;
-                    (result, Some(job))
-                };
-
-                // If -Zincremental-verify-ich is specified, re-hash results from
-                // the cache and make sure that they have the expected fingerprint.
-                if tcx.sess.opts.debugging_opts.incremental_verify_ich {
-                    use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
-                    use ich::Fingerprint;
-
-                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) ==
-                            tcx.dep_graph.prev_fingerprint_of(dep_node),
-                            "Fingerprint for green query instance not loaded \
-                             from cache: {:?}", dep_node);
-
-                    debug!("BEGIN verify_ich({:?})", dep_node);
-                    let mut hcx = tcx.create_stable_hashing_context();
-                    let mut hasher = StableHasher::new();
-
-                    result.hash_stable(&mut hcx, &mut hasher);
-
-                    let new_hash: Fingerprint = hasher.finish();
-                    debug!("END verify_ich({:?})", dep_node);
-
-                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index);
-
-                    assert!(new_hash == old_hash, "Found unstable fingerprints \
-                        for {:?}", dep_node);
-                }
-
-                if tcx.sess.opts.debugging_opts.query_dep_graph {
-                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
-                }
-
-                let value = QueryValue::new(Clone::clone(&result), dep_node_index);
-
-                tcx.maps
-                   .$name
-                   .borrow_mut()
-                   .map
-                   .insert(key, QueryResult::Complete(value));
-
-                job.map(|j| j.signal_complete());
-
-                Ok(result)
-            }
-
-            #[allow(dead_code)]
-            fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                     key: $K,
-                     span: Span,
-                     dep_node: DepNode)
-                     -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
-                // We may be concurrently trying both execute and force a query
-                // Ensure that only one of them runs the query
-                let lock = match Self::try_get_lock(tcx, span, &key) {
-                    TryGetLock::NotYetStarted(lock) => lock,
-                    TryGetLock::JobCompleted(result) => return result,
-                };
-                Self::force_with_lock(tcx,
-                                      key,
-                                      span,
-                                      lock,
-                                      dep_node)
-            }
-
-            fn force_with_lock(tcx: TyCtxt<'a, $tcx, 'lcx>,
-                               key: $K,
-                               span: Span,
-                               map: LockGuard<'_, QueryMap<$tcx, Self>>,
-                               dep_node: DepNode)
-                               -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
-                // If the following assertion triggers, it can have two reasons:
-                // 1. Something is wrong with DepNode creation, either here or
-                //    in DepGraph::try_mark_green()
-                // 2. Two distinct query keys get mapped to the same DepNode
-                //    (see for example #48923)
-                assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
-                        "Forcing query with already existing DepNode.\n\
-                          - query-key: {:?}\n\
-                          - dep-node: {:?}",
-                        key, dep_node);
-
-                profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
-                let res = Self::start_job(tcx,
-                                          span,
-                                          key,
-                                          map,
-                                          |tcx| {
-                    if dep_node.kind.is_eval_always() {
-                        tcx.dep_graph.with_eval_always_task(dep_node,
-                                                            tcx,
-                                                            key,
-                                                            Self::compute_result)
-                    } else {
-                        tcx.dep_graph.with_task(dep_node,
-                                                tcx,
-                                                key,
-                                                Self::compute_result)
-                    }
-                })?;
-                profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
-
-                let (((result, dep_node_index), diagnostics), job) = res;
-
-                if tcx.sess.opts.debugging_opts.query_dep_graph {
-                    tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false);
-                }
-
-                if dep_node.kind != ::dep_graph::DepKind::Null {
-                    tcx.on_disk_query_result_cache
-                       .store_diagnostics(dep_node_index, diagnostics);
-                }
-
-                let value = QueryValue::new(Clone::clone(&result), dep_node_index);
-
-                tcx.maps
-                   .$name
-                   .borrow_mut()
-                   .map
-                   .insert(key, QueryResult::Complete(value));
-
-                let job: Lrc<QueryJob> = job;
-
-                job.signal_complete();
-
-                Ok((result, dep_node_index))
-            }
-
-            pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-                           -> Result<$V, DiagnosticBuilder<'a>> {
-                match Self::try_get_with(tcx, span, key) {
-                    Ok(e) => Ok(e),
-                    Err(e) => Err(tcx.report_cycle(e)),
-                }
+                tcx.ensure_query::<queries::$name>(key);
             }
         })*
 
@@ -778,10 +773,7 @@ macro_rules! define_maps {
         impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
             $($(#[$attr])*
             pub fn $name(self, key: $K) -> $V {
-                queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
-                    e.emit();
-                    handle_cycle_error!([$($modifiers)*][self])
-                })
+                self.tcx.get_query::<queries::$name>(self.span, key)
             })*
         }
 
@@ -872,7 +864,6 @@ macro_rules! define_provider_struct {
 pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
                                            dep_node: &DepNode)
                                            -> bool {
-    use ty::maps::keys::Key;
     use hir::def_id::LOCAL_CRATE;
 
     // We must avoid ever having to call force_from_dep_node() for a
@@ -915,23 +906,14 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
             {
                 use $crate::util::common::{ProfileQueriesMsg, profq_msg};
 
-                // FIXME(eddyb) Get more valid Span's on queries.
-                // def_span guard is necessary to prevent a recursive loop,
-                // default_span calls def_span query internally.
-                let span = if stringify!($query) != "def_span" {
-                    $key.default_span(tcx)
-                } else {
-                    ::syntax_pos::DUMMY_SP
-                };
-
                 profq_msg!(tcx,
                     ProfileQueriesMsg::QueryBegin(
-                        span.data(),
-                        ::ty::maps::QueryMsg::$query(profq_key!(tcx, $key))
+                        DUMMY_SP.data(),
+                        profq_query_msg!(::ty::maps::queries::$query::NAME, tcx, $key),
                     )
                 );
 
-                match ::ty::maps::queries::$query::force(tcx, $key, span, *dep_node) {
+                match tcx.force_query::<::ty::maps::queries::$query>($key, DUMMY_SP, *dep_node) {
                     Ok(_) => {},
                     Err(e) => {
                         tcx.report_cycle(e).emit();
@@ -977,6 +959,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::NormalizeProjectionTy |
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::DropckOutlives |
+        DepKind::EvaluateObligation |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::InstanceDefSizeEstimate |
         DepKind::ProgramClausesForEnv |
diff --git a/src/librustc/ty/maps/values.rs b/src/librustc/ty/maps/values.rs
index 8d38d7dbbbb..d3d06248792 100644
--- a/src/librustc/ty/maps/values.rs
+++ b/src/librustc/ty/maps/values.rs
@@ -37,7 +37,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> {
 
 impl<'tcx> Value<'tcx> for ty::SymbolName {
     fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
-        ty::SymbolName { name: Symbol::intern("<error>").as_str() }
+        ty::SymbolName { name: Symbol::intern("<error>").as_interned_str() }
     }
 }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index de043668410..c4fe112a9e9 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -51,7 +51,7 @@ use std::mem;
 use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::{Symbol, LocalInternedString, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
 use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
@@ -69,7 +69,7 @@ pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
 pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
 pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
 pub use self::sty::RegionKind;
-pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
+pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid};
 pub use self::sty::BoundRegion::*;
 pub use self::sty::InferTy::*;
 pub use self::sty::RegionKind::*;
@@ -1370,15 +1370,13 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
 /// type name in a non-zero universe is a skolemized type -- an
 /// idealized representative of "types in general" that we use for
 /// checking generic functions.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct UniverseIndex(u32);
 
 impl UniverseIndex {
     /// The root universe, where things that the user defined are
     /// visible.
-    pub fn root() -> UniverseIndex {
-        UniverseIndex(0)
-    }
+    pub const ROOT: Self = UniverseIndex(0);
 
     /// A "subuniverse" corresponds to being inside a `forall` quantifier.
     /// So, for example, suppose we have this type in universe `U`:
@@ -1392,7 +1390,21 @@ impl UniverseIndex {
     /// region `'a`, but that region was not nameable from `U` because
     /// it was not in scope there.
     pub fn subuniverse(self) -> UniverseIndex {
-        UniverseIndex(self.0 + 1)
+        UniverseIndex(self.0.checked_add(1).unwrap())
+    }
+
+    pub fn as_u32(&self) -> u32 {
+        self.0
+    }
+
+    pub fn as_usize(&self) -> usize {
+        self.0 as usize
+    }
+}
+
+impl From<u32> for UniverseIndex {
+    fn from(index: u32) -> Self {
+        UniverseIndex(index)
     }
 }
 
@@ -1476,7 +1488,11 @@ impl<'tcx> ParamEnv<'tcx> {
             }
 
             Reveal::All => {
-                if value.needs_infer() || value.has_param_types() || value.has_self_ty() {
+                if value.has_skol()
+                    || value.needs_infer()
+                    || value.has_param_types()
+                    || value.has_self_ty()
+                {
                     ParamEnvAnd {
                         param_env: self,
                         value,
@@ -2031,7 +2047,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
-        match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
+        match tcx.try_get_query::<queries::adt_sized_constraint>(DUMMY_SP, self.did) {
             Ok(tys) => tys,
             Err(mut bug) => {
                 debug!("adt_sized_constraint: {:?} is recursive", self);
@@ -2463,7 +2479,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn item_name(self, id: DefId) -> InternedString {
         if id.index == CRATE_DEF_INDEX {
-            self.original_crate_name(id.krate).as_str()
+            self.original_crate_name(id.krate).as_interned_str()
         } else {
             let def_key = self.def_key(id);
             // The name of a StructCtor is that of its struct parent.
@@ -2820,15 +2836,13 @@ impl_stable_hash_for!(struct self::SymbolName {
 impl SymbolName {
     pub fn new(name: &str) -> SymbolName {
         SymbolName {
-            name: Symbol::intern(name).as_str()
+            name: Symbol::intern(name).as_interned_str()
         }
     }
-}
 
-impl Deref for SymbolName {
-    type Target = str;
-
-    fn deref(&self) -> &str { &self.name }
+    pub fn as_str(&self) -> LocalInternedString {
+        self.name.as_str()
+    }
 }
 
 impl fmt::Display for SymbolName {
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 9b20fce6673..d4ed6c60e0e 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -474,8 +474,18 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
 impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
     type Lifted = interpret::EvalError<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        Some(interpret::EvalError {
+            kind: tcx.lift(&self.kind)?,
+            backtrace: self.backtrace.clone(),
+        })
+    }
+}
+
+impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
+    type Lifted = interpret::EvalErrorKind<'tcx, <O as Lift<'tcx>>::Lifted>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         use ::mir::interpret::EvalErrorKind::*;
-        let kind = match self.kind {
+        Some(match *self {
             MachineError(ref err) => MachineError(err.clone()),
             FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
                 tcx.lift(&a)?,
@@ -504,10 +514,11 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
             Unimplemented(ref s) => Unimplemented(s.clone()),
             DerefFunctionPointer => DerefFunctionPointer,
             ExecuteMemory => ExecuteMemory,
-            ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b),
-            Math(sp, ref err) => Math(sp, err.clone()),
+            BoundsCheck { ref len, ref index } => BoundsCheck {
+                len: tcx.lift(len)?,
+                index: tcx.lift(index)?,
+            },
             Intrinsic(ref s) => Intrinsic(s.clone()),
-            OverflowingMath => OverflowingMath,
             InvalidChar(c) => InvalidChar(c),
             StackFrameLimitReached => StackFrameLimitReached,
             OutOfTls => OutOfTls,
@@ -568,10 +579,12 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
             UnimplementedTraitSelection => UnimplementedTraitSelection,
             TypeckError => TypeckError,
             ReferencedConstant => ReferencedConstant,
-        };
-        Some(interpret::EvalError {
-            kind: kind,
-            backtrace: self.backtrace.clone(),
+            OverflowNeg => OverflowNeg,
+            Overflow(op) => Overflow(op),
+            DivisionByZero => DivisionByZero,
+            RemainderByZero => RemainderByZero,
+            GeneratorResumedAfterReturn => GeneratorResumedAfterReturn,
+            GeneratorResumedAfterPanic => GeneratorResumedAfterPanic,
         })
     }
 }
@@ -585,7 +598,6 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
             NonConstPath => NonConstPath,
             UnimplementedConstVal(s) => UnimplementedConstVal(s),
             IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index },
-            Math(ref e) => Math(e.clone()),
 
             LayoutError(ref e) => {
                 return tcx.lift(e).map(LayoutError)
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 0dfae13cc75..382db571b52 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -864,7 +864,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, keywords::SelfType.name().as_str())
+        ParamTy::new(0, keywords::SelfType.name().as_interned_str())
     }
 
     pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
@@ -876,8 +876,10 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn is_self(&self) -> bool {
-        if self.name == keywords::SelfType.name().as_str() {
-            assert_eq!(self.idx, 0);
+        // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere,
+        // but this should only be possible when using `-Z continue-parse-after-error` like
+        // `compile-fail/issue-36638.rs`.
+        if self.name == keywords::SelfType.name().as_str() && self.idx == 0 {
             true
         } else {
             false
@@ -1019,7 +1021,7 @@ pub enum RegionKind {
 
     /// A skolemized region - basically the higher-ranked version of ReFree.
     /// Should not exist after typeck.
-    ReSkolemized(SkolemizedRegionVid, BoundRegion),
+    ReSkolemized(ty::UniverseIndex, BoundRegion),
 
     /// Empty lifetime is for data that is never accessed.
     /// Bottom in the region lattice. We treat ReEmpty somewhat
@@ -1073,11 +1075,6 @@ newtype_index!(RegionVid
         DEBUG_FORMAT = custom,
     });
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
-pub struct SkolemizedRegionVid {
-    pub index: u32,
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum InferTy {
     TyVar(TyVid),
@@ -1169,13 +1166,6 @@ impl RegionKind {
         }
     }
 
-    pub fn needs_infer(&self) -> bool {
-        match *self {
-            ty::ReVar(..) | ty::ReSkolemized(..) => true,
-            _ => false
-        }
-    }
-
     pub fn escapes_depth(&self, depth: u32) -> bool {
         match *self {
             ty::ReLateBound(debruijn, _) => debruijn.depth > depth,
@@ -1193,20 +1183,29 @@ impl RegionKind {
         }
     }
 
+    pub fn keep_in_local_tcx(&self) -> bool {
+        if let ty::ReVar(..) = self {
+            true
+        } else {
+            false
+        }
+    }
+
     pub fn type_flags(&self) -> TypeFlags {
         let mut flags = TypeFlags::empty();
 
+        if self.keep_in_local_tcx() {
+            flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
+        }
+
         match *self {
             ty::ReVar(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
-                flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
             }
             ty::ReSkolemized(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_RE_INFER;
                 flags = flags | TypeFlags::HAS_RE_SKOL;
-                flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
             }
             ty::ReLateBound(..) => { }
             ty::ReEarlyBound(..) => {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index a10ca132472..4aa70e1f7e0 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -1024,7 +1024,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let (param_env, ty) = query.into_parts();
 
     let needs_drop = |ty: Ty<'tcx>| -> bool {
-        match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
+        match tcx.try_get_query::<ty::queries::needs_drop_raw>(DUMMY_SP, param_env.and(ty)) {
             Ok(v) => v,
             Err(mut bug) => {
                 // Cycles should be reported as an error by `check_representable`.
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index bb6aa654c29..85533caffce 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -25,7 +25,6 @@ use std::time::{Duration, Instant};
 
 use std::sync::mpsc::{Sender};
 use syntax_pos::{SpanData};
-use ty::maps::{QueryMsg};
 use ty::TyCtxt;
 use dep_graph::{DepNode};
 use proc_macro;
@@ -59,6 +58,17 @@ fn panic_hook(info: &panic::PanicInfo) {
         if backtrace {
             TyCtxt::try_print_query_stack();
         }
+
+        #[cfg(windows)]
+        unsafe {
+            if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
+                extern "system" {
+                    fn DebugBreak();
+                }
+                // Trigger a debugger if we crashed during bootstrap
+                DebugBreak();
+            }
+        }
     }
 }
 
@@ -77,6 +87,13 @@ pub struct ProfQDumpParams {
     pub dump_profq_msg_log:bool,
 }
 
+#[allow(bad_style)]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct QueryMsg {
+    pub query: &'static str,
+    pub msg: Option<String>,
+}
+
 /// A sequence of these messages induce a trace of query-based incremental compilation.
 /// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
 #[derive(Clone,Debug)]
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 905776373bd..894a18b79cc 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -462,7 +462,7 @@ impl PrintContext {
                 0 => Symbol::intern("'r"),
                 1 => Symbol::intern("'s"),
                 i => Symbol::intern(&format!("'t{}", i-2)),
-            }.as_str()
+            }.as_interned_str()
         }
 
         // Replace any anonymous late-bound regions with named
@@ -808,8 +808,8 @@ define_print! {
                     write!(f, "'?{}", c.index())
                 }
 
-                ty::ReSkolemized(id, ref bound_region) => {
-                    write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
+                ty::ReSkolemized(universe, ref bound_region) => {
+                    write!(f, "ReSkolemized({:?}, {:?})", universe, bound_region)
                 }
 
                 ty::ReEmpty => write!(f, "ReEmpty"),
diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs
index dec88eb62cc..e662088e82f 100644
--- a/src/librustc_apfloat/ppc.rs
+++ b/src/librustc_apfloat/ppc.rs
@@ -20,7 +20,7 @@ use std::ops::Neg;
 pub struct DoubleFloat<F>(F, F);
 pub type DoubleDouble = DoubleFloat<ieee::Double>;
 
-// These are legacy semantics for the Fallback, inaccrurate implementation of
+// These are legacy semantics for the Fallback, inaccurate implementation of
 // IBM double-double, if the accurate DoubleDouble doesn't handle the
 // operation. It's equivalent to having an IEEE number with consecutive 106
 // bits of mantissa and 11 bits of exponent.
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index a01b3cbf47b..79baf0ec151 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -99,7 +99,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
     fn consume(&mut self,
                consume_id: ast::NodeId,
                consume_span: Span,
-               cmt: mc::cmt<'tcx>,
+               cmt: &mc::cmt_<'tcx>,
                mode: euv::ConsumeMode) {
         debug!("consume(consume_id={}, cmt={:?}, mode={:?})",
                consume_id, cmt, mode);
@@ -110,12 +110,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
 
     fn matched_pat(&mut self,
                    _matched_pat: &hir::Pat,
-                   _cmt: mc::cmt,
+                   _cmt: &mc::cmt_,
                    _mode: euv::MatchMode) { }
 
     fn consume_pat(&mut self,
                    consume_pat: &hir::Pat,
-                   cmt: mc::cmt<'tcx>,
+                   cmt: &mc::cmt_<'tcx>,
                    mode: euv::ConsumeMode) {
         debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
                consume_pat,
@@ -128,7 +128,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
     fn borrow(&mut self,
               borrow_id: ast::NodeId,
               borrow_span: Span,
-              cmt: mc::cmt<'tcx>,
+              cmt: &mc::cmt_<'tcx>,
               loan_region: ty::Region<'tcx>,
               bk: ty::BorrowKind,
               loan_cause: euv::LoanCause)
@@ -139,7 +139,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
                bk, loan_cause);
 
         let hir_id = self.tcx().hir.node_to_hir_id(borrow_id);
-        if let Some(lp) = opt_loan_path(&cmt) {
+        if let Some(lp) = opt_loan_path(cmt) {
             let moved_value_use_kind = match loan_cause {
                 euv::ClosureCapture(_) => MovedInCapture,
                 _ => MovedInUse,
@@ -155,13 +155,13 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
     fn mutate(&mut self,
               assignment_id: ast::NodeId,
               assignment_span: Span,
-              assignee_cmt: mc::cmt<'tcx>,
+              assignee_cmt: &mc::cmt_<'tcx>,
               mode: euv::MutateMode)
     {
         debug!("mutate(assignment_id={}, assignee_cmt={:?})",
                assignment_id, assignee_cmt);
 
-        if let Some(lp) = opt_loan_path(&assignee_cmt) {
+        if let Some(lp) = opt_loan_path(assignee_cmt) {
             match mode {
                 MutateMode::Init | MutateMode::JustWrite => {
                     // In a case like `path = 1`, then path does not
@@ -363,10 +363,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
     }
 
     pub fn check_for_loans_across_yields(&self,
-                                         cmt: mc::cmt<'tcx>,
+                                         cmt: &mc::cmt_<'tcx>,
                                          loan_region: ty::Region<'tcx>,
                                          borrow_span: Span) {
-        pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt<'tcx>) -> bool {
+        pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
             match cmt.cat {
                 // Borrows of static items is allowed
                 Categorization::StaticItem => false,
@@ -401,7 +401,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             return;
         }
 
-        if !borrow_of_local_data(&cmt) {
+        if !borrow_of_local_data(cmt) {
             return;
         }
 
@@ -649,9 +649,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
     fn consume_common(&self,
                       id: hir::ItemLocalId,
                       span: Span,
-                      cmt: mc::cmt<'tcx>,
+                      cmt: &mc::cmt_<'tcx>,
                       mode: euv::ConsumeMode) {
-        if let Some(lp) = opt_loan_path(&cmt) {
+        if let Some(lp) = opt_loan_path(cmt) {
             let moved_value_use_kind = match mode {
                 euv::Copy => {
                     self.check_for_copy_of_frozen_path(id, span, &lp);
@@ -876,11 +876,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
     fn check_assignment(&self,
                         assignment_id: hir::ItemLocalId,
                         assignment_span: Span,
-                        assignee_cmt: mc::cmt<'tcx>) {
+                        assignee_cmt: &mc::cmt_<'tcx>) {
         debug!("check_assignment(assignee_cmt={:?})", assignee_cmt);
 
         // Check that we don't invalidate any outstanding loans
-        if let Some(loan_path) = opt_loan_path(&assignee_cmt) {
+        if let Some(loan_path) = opt_loan_path(assignee_cmt) {
             let scope = region::Scope::Node(assignment_id);
             self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
                 self.report_illegal_mutation(assignment_span, &loan_path, loan);
@@ -892,7 +892,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         // needs to be done here instead of in check_loans because we
         // depend on move data.
         if let Categorization::Local(local_id) = assignee_cmt.cat {
-            let lp = opt_loan_path(&assignee_cmt).unwrap();
+            let lp = opt_loan_path(assignee_cmt).unwrap();
             self.move_data.each_assignment_of(assignment_id, &lp, |assign| {
                 if assignee_cmt.mutbl.is_mutable() {
                     let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id);
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 465457f5ab3..ac905d6de5d 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -26,10 +26,10 @@ use syntax_pos::Span;
 use rustc::hir::*;
 use rustc::hir::map::Node::*;
 
-struct GatherMoveInfo<'tcx> {
+struct GatherMoveInfo<'c, 'tcx: 'c> {
     id: hir::ItemLocalId,
     kind: MoveKind,
-    cmt: mc::cmt<'tcx>,
+    cmt: &'c mc::cmt_<'tcx>,
     span_path_opt: Option<MovePlace<'tcx>>
 }
 
@@ -87,7 +87,7 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                        move_data: &MoveData<'tcx>,
                                        move_error_collector: &mut MoveErrorCollector<'tcx>,
                                        move_expr_id: hir::ItemLocalId,
-                                       cmt: mc::cmt<'tcx>,
+                                       cmt: &mc::cmt_<'tcx>,
                                        move_reason: euv::MoveReason) {
     let kind = match move_reason {
         euv::DirectRefMove | euv::PatBindingMove => MoveExpr,
@@ -102,11 +102,11 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     gather_move(bccx, move_data, move_error_collector, move_info);
 }
 
-pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-                                      move_data: &MoveData<'tcx>,
-                                      move_error_collector: &mut MoveErrorCollector<'tcx>,
-                                      move_pat: &hir::Pat,
-                                      cmt: mc::cmt<'tcx>) {
+pub fn gather_move_from_pat<'a, 'c, 'tcx: 'c>(bccx: &BorrowckCtxt<'a, 'tcx>,
+                                              move_data: &MoveData<'tcx>,
+                                              move_error_collector: &mut MoveErrorCollector<'tcx>,
+                                              move_pat: &hir::Pat,
+                                              cmt: &'c mc::cmt_<'tcx>) {
     let source = get_pattern_source(bccx.tcx,move_pat);
     let pat_span_path_opt = match move_pat.node {
         PatKind::Binding(_, _, ref path1, _) => {
@@ -132,18 +132,17 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     gather_move(bccx, move_data, move_error_collector, move_info);
 }
 
-fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
+fn gather_move<'a, 'c, 'tcx: 'c>(bccx: &BorrowckCtxt<'a, 'tcx>,
                          move_data: &MoveData<'tcx>,
                          move_error_collector: &mut MoveErrorCollector<'tcx>,
-                         move_info: GatherMoveInfo<'tcx>) {
+                         move_info: GatherMoveInfo<'c, 'tcx>) {
     debug!("gather_move(move_id={:?}, cmt={:?})",
            move_info.id, move_info.cmt);
 
-    let potentially_illegal_move =
-                check_and_get_illegal_move_origin(bccx, &move_info.cmt);
+    let potentially_illegal_move = check_and_get_illegal_move_origin(bccx, move_info.cmt);
     if let Some(illegal_move_origin) = potentially_illegal_move {
         debug!("illegal_move_origin={:?}", illegal_move_origin);
-        let error = MoveError::with_move_info(illegal_move_origin,
+        let error = MoveError::with_move_info(Rc::new(illegal_move_origin),
                                               move_info.span_path_opt);
         move_error_collector.add_error(error);
         return;
@@ -177,8 +176,8 @@ pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 
 // (keep in sync with move_error::report_cannot_move_out_of )
 fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-                                               cmt: &mc::cmt<'tcx>)
-                                               -> Option<mc::cmt<'tcx>> {
+                                               cmt: &mc::cmt_<'tcx>)
+                                               -> Option<mc::cmt_<'tcx>> {
     match cmt.cat {
         Categorization::Deref(_, mc::BorrowedPtr(..)) |
         Categorization::Deref(_, mc::Implicit(..)) |
diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
index 97fa94b5e5c..6d73500d318 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
@@ -27,7 +27,7 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                     item_scope: region::Scope,
                                     span: Span,
                                     cause: euv::LoanCause,
-                                    cmt: mc::cmt<'tcx>,
+                                    cmt: &'a mc::cmt_<'tcx>,
                                     loan_region: ty::Region<'tcx>,
                                     _: ty::BorrowKind)
                                     -> Result<(),()> {
@@ -41,8 +41,8 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                          span,
                                          cause,
                                          loan_region,
-                                         cmt_original: cmt.clone()};
-    ctxt.check(&cmt, None)
+                                         cmt_original: cmt};
+    ctxt.check(cmt, None)
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -57,12 +57,11 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
     span: Span,
     cause: euv::LoanCause,
     loan_region: ty::Region<'tcx>,
-    cmt_original: mc::cmt<'tcx>
+    cmt_original: &'a mc::cmt_<'tcx>
 }
 
 impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
-
-    fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
+    fn check(&self, cmt: &mc::cmt_<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
         //! Main routine. Walks down `cmt` until we find the
         //! "guarantor".  Reports an error if `self.loan_region` is
         //! larger than scope of `cmt`.
@@ -102,7 +101,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn scope(&self, cmt: &mc::cmt<'tcx>) -> ty::Region<'tcx> {
+    fn scope(&self, cmt: &mc::cmt_<'tcx>) -> ty::Region<'tcx> {
         //! Returns the maximal region scope for the which the
         //! place `cmt` is guaranteed to be valid without any
         //! rooting etc, and presuming `cmt` is not mutated.
@@ -136,7 +135,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
     }
 
     fn report_error(&self, code: bckerr_code<'tcx>) {
-        self.bccx.report(BckError { cmt: self.cmt_original.clone(),
+        self.bccx.report(BckError { cmt: self.cmt_original,
                                     span: self.span,
                                     cause: BorrowViolation(self.cause),
                                     code: code });
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index 49234f4ed7f..a74eba39955 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -76,7 +76,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
     fn consume(&mut self,
                consume_id: ast::NodeId,
                _consume_span: Span,
-               cmt: mc::cmt<'tcx>,
+               cmt: &mc::cmt_<'tcx>,
                mode: euv::ConsumeMode) {
         debug!("consume(consume_id={}, cmt={:?}, mode={:?})",
                consume_id, cmt, mode);
@@ -93,7 +93,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
 
     fn matched_pat(&mut self,
                    matched_pat: &hir::Pat,
-                   cmt: mc::cmt<'tcx>,
+                   cmt: &mc::cmt_<'tcx>,
                    mode: euv::MatchMode) {
         debug!("matched_pat(matched_pat={:?}, cmt={:?}, mode={:?})",
                matched_pat,
@@ -103,7 +103,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
 
     fn consume_pat(&mut self,
                    consume_pat: &hir::Pat,
-                   cmt: mc::cmt<'tcx>,
+                   cmt: &mc::cmt_<'tcx>,
                    mode: euv::ConsumeMode) {
         debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
                consume_pat,
@@ -123,7 +123,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
     fn borrow(&mut self,
               borrow_id: ast::NodeId,
               borrow_span: Span,
-              cmt: mc::cmt<'tcx>,
+              cmt: &mc::cmt_<'tcx>,
               loan_region: ty::Region<'tcx>,
               bk: ty::BorrowKind,
               loan_cause: euv::LoanCause)
@@ -144,7 +144,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
     fn mutate(&mut self,
               assignment_id: ast::NodeId,
               assignment_span: Span,
-              assignee_cmt: mc::cmt<'tcx>,
+              assignee_cmt: &mc::cmt_<'tcx>,
               mode: euv::MutateMode)
     {
         self.guarantee_assignment_valid(assignment_id,
@@ -165,7 +165,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
 fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                 borrow_span: Span,
                                 loan_cause: AliasableViolationKind,
-                                cmt: mc::cmt<'tcx>,
+                                cmt: &mc::cmt_<'tcx>,
                                 req_kind: ty::BorrowKind)
                                 -> Result<(),()> {
 
@@ -206,7 +206,7 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                               borrow_span: Span,
                               cause: AliasableViolationKind,
-                              cmt: mc::cmt<'tcx>,
+                              cmt: &mc::cmt_<'tcx>,
                               req_kind: ty::BorrowKind)
                               -> Result<(),()> {
     debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}",
@@ -246,10 +246,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
     fn guarantee_assignment_valid(&mut self,
                                   assignment_id: ast::NodeId,
                                   assignment_span: Span,
-                                  cmt: mc::cmt<'tcx>,
+                                  cmt: &mc::cmt_<'tcx>,
                                   mode: euv::MutateMode) {
 
-        let opt_lp = opt_loan_path(&cmt);
+        let opt_lp = opt_loan_path(cmt);
         debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}",
                assignment_id, cmt, opt_lp);
 
@@ -259,14 +259,14 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
         } else {
             // Check that we don't allow assignments to non-mutable data.
             if check_mutability(self.bccx, assignment_span, MutabilityViolation,
-                                cmt.clone(), ty::MutBorrow).is_err() {
+                                cmt, ty::MutBorrow).is_err() {
                 return; // reported an error, no sense in reporting more.
             }
         }
 
         // Check that we don't allow assignments to aliasable data
         if check_aliasability(self.bccx, assignment_span, MutabilityViolation,
-                              cmt.clone(), ty::MutBorrow).is_err() {
+                              cmt, ty::MutBorrow).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
@@ -300,7 +300,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
     fn guarantee_valid(&mut self,
                        borrow_id: hir::ItemLocalId,
                        borrow_span: Span,
-                       cmt: mc::cmt<'tcx>,
+                       cmt: &mc::cmt_<'tcx>,
                        req_kind: ty::BorrowKind,
                        loan_region: ty::Region<'tcx>,
                        cause: euv::LoanCause) {
@@ -320,28 +320,26 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
         // Check that the lifetime of the borrow does not exceed
         // the lifetime of the data being borrowed.
         if lifetime::guarantee_lifetime(self.bccx, self.item_ub,
-                                        borrow_span, cause, cmt.clone(), loan_region,
-                                        req_kind).is_err() {
+                                        borrow_span, cause, cmt, loan_region, req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of non-mutable data.
         if check_mutability(self.bccx, borrow_span, BorrowViolation(cause),
-                            cmt.clone(), req_kind).is_err() {
+                            cmt, req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of aliasable data.
         if check_aliasability(self.bccx, borrow_span, BorrowViolation(cause),
-                              cmt.clone(), req_kind).is_err() {
+                              cmt, req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Compute the restrictions that are required to enforce the
         // loan is safe.
         let restr = restrictions::compute_restrictions(
-            self.bccx, borrow_span, cause,
-            cmt.clone(), loan_region);
+            self.bccx, borrow_span, cause, &cmt, loan_region);
 
         debug!("guarantee_valid(): restrictions={:?}", restr);
 
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index e3adb51433b..0b90127cc7e 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -30,7 +30,7 @@ pub enum RestrictionResult<'tcx> {
 pub fn compute_restrictions<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       span: Span,
                                       cause: euv::LoanCause,
-                                      cmt: mc::cmt<'tcx>,
+                                      cmt: &mc::cmt_<'tcx>,
                                       loan_region: ty::Region<'tcx>)
                                       -> RestrictionResult<'tcx> {
     let ctxt = RestrictionsContext {
@@ -55,7 +55,7 @@ struct RestrictionsContext<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
     fn restrict(&self,
-                cmt: mc::cmt<'tcx>) -> RestrictionResult<'tcx> {
+                cmt: &mc::cmt_<'tcx>) -> RestrictionResult<'tcx> {
         debug!("restrict(cmt={:?})", cmt);
 
         let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
@@ -86,7 +86,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 // When we borrow the interior of an enum, we have to
                 // ensure the enum itself is not mutated, because that
                 // could cause the type of the memory to change.
-                self.restrict(cmt_base)
+                self.restrict(&cmt_base)
             }
 
             Categorization::Interior(cmt_base, interior) => {
@@ -101,7 +101,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 };
                 let interior = interior.cleaned();
                 let base_ty = cmt_base.ty;
-                let result = self.restrict(cmt_base);
+                let result = self.restrict(&cmt_base);
                 // Borrowing one union field automatically borrows all its fields.
                 match base_ty.sty {
                     ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
@@ -145,7 +145,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                         //
                         // Eventually we should make these non-special and
                         // just rely on Deref<T> implementation.
-                        let result = self.restrict(cmt_base);
+                        let result = self.restrict(&cmt_base);
                         self.extend(result, &cmt, LpDeref(pk))
                     }
                     mc::Implicit(bk, lt) | mc::BorrowedPtr(bk, lt) => {
@@ -155,7 +155,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                                 BckError {
                                     span: self.span,
                                     cause: BorrowViolation(self.cause),
-                                    cmt: cmt_base,
+                                    cmt: &cmt_base,
                                     code: err_borrowed_pointer_too_short(
                                         self.loan_region, lt)});
                             return RestrictionResult::Safe;
@@ -169,7 +169,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                                 // The referent can be aliased after the
                                 // references lifetime ends (by a newly-unfrozen
                                 // borrow).
-                                let result = self.restrict(cmt_base);
+                                let result = self.restrict(&cmt_base);
                                 self.extend(result, &cmt, LpDeref(pk))
                             }
                         }
@@ -183,7 +183,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
 
     fn extend(&self,
               result: RestrictionResult<'tcx>,
-              cmt: &mc::cmt<'tcx>,
+              cmt: &mc::cmt_<'tcx>,
               elem: LoanPathElem<'tcx>) -> RestrictionResult<'tcx> {
         match result {
             RestrictionResult::Safe => RestrictionResult::Safe,
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 6d832d4060a..9d0d8c2f909 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -144,7 +144,10 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
     {
         check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
     }
-    unused::check(&mut bccx, body);
+
+    if !tcx.use_mir_borrowck() {
+        unused::check(&mut bccx, body);
+    }
 
     Lrc::new(BorrowCheckResult {
         used_mut_nodes: bccx.used_mut_nodes.into_inner(),
@@ -497,7 +500,7 @@ impl<'a, 'tcx> LoanPath<'tcx> {
 
 // Avoid "cannot borrow immutable field `self.x` as mutable" as that implies that a field *can* be
 // mutable independently of the struct it belongs to. (#35937)
-pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option<Rc<LoanPath<'tcx>>>, bool) {
+pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt_<'tcx>) -> (Option<Rc<LoanPath<'tcx>>>, bool) {
     let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
 
     match cmt.cat {
@@ -545,7 +548,7 @@ pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option<Rc<LoanPath<
 /// the method `compute()` found in `gather_loans::restrictions`,
 /// which allows it to share common loan path pieces as it
 /// traverses the CMT.
-pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
+pub fn opt_loan_path<'tcx>(cmt: &mc::cmt_<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
     opt_loan_path_is_field(cmt).0
 }
 
@@ -564,10 +567,10 @@ pub enum bckerr_code<'tcx> {
 // Combination of an error code and the categorization of the expression
 // that caused it
 #[derive(Debug, PartialEq)]
-pub struct BckError<'tcx> {
+pub struct BckError<'c, 'tcx: 'c> {
     span: Span,
     cause: AliasableViolationKind,
-    cmt: mc::cmt<'tcx>,
+    cmt: &'c mc::cmt_<'tcx>,
     code: bckerr_code<'tcx>
 }
 
@@ -599,7 +602,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         region_rels.is_subregion_of(r_sub, r_sup)
     }
 
-    pub fn report(&self, err: BckError<'tcx>) {
+    pub fn report(&self, err: BckError<'a, 'tcx>) {
         // Catch and handle some particular cases.
         match (&err.code, &err.cause) {
             (&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _),
@@ -800,7 +803,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         self.tcx.sess.span_err_with_code(s, msg, code);
     }
 
-    fn report_bckerr(&self, err: &BckError<'tcx>) {
+    fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
         let error_span = err.span.clone();
 
         match err.code {
@@ -1011,7 +1014,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 db.emit();
             }
             err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
-                let descr = self.cmt_to_path_or_string(&err.cmt);
+                let descr = self.cmt_to_path_or_string(err.cmt);
                 let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast);
                 let descr = match opt_loan_path(&err.cmt) {
                     Some(lp) => {
@@ -1042,7 +1045,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                          span: Span,
                                          kind: AliasableViolationKind,
                                          cause: mc::AliasableReason,
-                                         cmt: mc::cmt<'tcx>) {
+                                         cmt: &mc::cmt_<'tcx>) {
         let mut is_closure = false;
         let prefix = match kind {
             MutabilityViolation => {
@@ -1240,7 +1243,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
     }
 
     fn report_out_of_scope_escaping_closure_capture(&self,
-                                                    err: &BckError<'tcx>,
+                                                    err: &BckError<'a, 'tcx>,
                                                     capture_span: Span)
     {
         let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt);
@@ -1274,18 +1277,18 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         }
     }
 
-    fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'tcx>,
+    fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'a, 'tcx>,
                                     error_span: &Span) {
         match err.cmt.note {
             mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
                 // If this is an `Fn` closure, it simply can't mutate upvars.
                 // If it's an `FnMut` closure, the original variable was declared immutable.
                 // We need to determine which is the case here.
-                let kind = match err.cmt.upvar().unwrap().cat {
+                let kind = match err.cmt.upvar_cat().unwrap() {
                     Categorization::Upvar(mc::Upvar { kind, .. }) => kind,
                     _ => bug!()
                 };
-                if kind == ty::ClosureKind::Fn {
+                if *kind == ty::ClosureKind::Fn {
                     let closure_node_id =
                         self.tcx.hir.local_def_id_to_node_id(upvar_id.closure_expr_id);
                     db.span_help(self.tcx.hir.span(closure_node_id),
@@ -1389,7 +1392,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         cmt.descriptive_string(self.tcx)
     }
 
-    pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt<'tcx>) -> String {
+    pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt_<'tcx>) -> String {
         match opt_loan_path(cmt) {
             Some(lp) => format!("`{}`", self.loan_path_to_string(&lp)),
             None => self.cmt_to_string(cmt),
diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml
deleted file mode 100644
index 41310ede3e0..00000000000
--- a/src/librustc_const_math/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "rustc_const_math"
-version = "0.0.0"
-
-[lib]
-name = "rustc_const_math"
-path = "lib.rs"
-crate-type = ["dylib"]
-
-[dependencies]
-rustc_apfloat = { path = "../librustc_apfloat" }
-serialize = { path = "../libserialize" }
-syntax = { path = "../libsyntax" }
diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs
deleted file mode 100644
index bd0a332436e..00000000000
--- a/src/librustc_const_math/err.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use syntax::ast;
-
-#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)]
-pub enum ConstMathErr {
-    NotInRange,
-    CmpBetweenUnequalTypes,
-    UnequalTypes(Op),
-    Overflow(Op),
-    ShiftNegative,
-    DivisionByZero,
-    RemainderByZero,
-    UnsignedNegation,
-    ULitOutOfRange(ast::UintTy),
-    LitOutOfRange(ast::IntTy),
-}
-pub use self::ConstMathErr::*;
-
-#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)]
-pub enum Op {
-    Add,
-    Sub,
-    Mul,
-    Div,
-    Rem,
-    Shr,
-    Shl,
-    Neg,
-    BitAnd,
-    BitOr,
-    BitXor,
-}
-
-impl ConstMathErr {
-    pub fn description(&self) -> &'static str {
-        use self::Op::*;
-        match *self {
-            NotInRange => "inferred value out of range",
-            CmpBetweenUnequalTypes => "compared two values of different types",
-            UnequalTypes(Add) => "tried to add two values of different types",
-            UnequalTypes(Sub) => "tried to subtract two values of different types",
-            UnequalTypes(Mul) => "tried to multiply two values of different types",
-            UnequalTypes(Div) => "tried to divide two values of different types",
-            UnequalTypes(Rem) => {
-                "tried to calculate the remainder of two values of different types"
-            },
-            UnequalTypes(BitAnd) => "tried to bitand two values of different types",
-            UnequalTypes(BitOr) => "tried to bitor two values of different types",
-            UnequalTypes(BitXor) => "tried to xor two values of different types",
-            UnequalTypes(_) => unreachable!(),
-            Overflow(Add) => "attempt to add with overflow",
-            Overflow(Sub) => "attempt to subtract with overflow",
-            Overflow(Mul) => "attempt to multiply with overflow",
-            Overflow(Div) => "attempt to divide with overflow",
-            Overflow(Rem) => "attempt to calculate the remainder with overflow",
-            Overflow(Neg) => "attempt to negate with overflow",
-            Overflow(Shr) => "attempt to shift right with overflow",
-            Overflow(Shl) => "attempt to shift left with overflow",
-            Overflow(_) => unreachable!(),
-            ShiftNegative => "attempt to shift by a negative amount",
-            DivisionByZero => "attempt to divide by zero",
-            RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
-            UnsignedNegation => "unary negation of unsigned integer",
-            ULitOutOfRange(ast::UintTy::U8) => "literal out of range for u8",
-            ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16",
-            ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32",
-            ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64",
-            ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128",
-            ULitOutOfRange(ast::UintTy::Usize) => "literal out of range for usize",
-            LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8",
-            LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16",
-            LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32",
-            LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64",
-            LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128",
-            LitOutOfRange(ast::IntTy::Isize) => "literal out of range for isize",
-        }
-    }
-}
diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs
deleted file mode 100644
index 9d820ea8cbe..00000000000
--- a/src/librustc_const_math/float.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::cmp::Ordering;
-use std::num::ParseFloatError;
-
-use syntax::ast;
-
-use rustc_apfloat::{Float, FloatConvert, Status};
-use rustc_apfloat::ieee::{Single, Double};
-
-use super::err::*;
-
-// Note that equality for `ConstFloat` means that the it is the same
-// constant, not that the rust values are equal. In particular, `NaN
-// == NaN` (at least if it's the same NaN; distinct encodings for NaN
-// are considering unequal).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
-pub struct ConstFloat {
-    pub ty: ast::FloatTy,
-
-    // This is a bit inefficient but it makes conversions below more
-    // ergonomic, and all of this will go away once `miri` is merged.
-    pub bits: u128,
-}
-
-impl ConstFloat {
-    /// Description of the type, not the value
-    pub fn description(&self) -> &'static str {
-        self.ty.ty_to_string()
-    }
-
-    /// Compares the values if they are of the same type
-    pub fn try_cmp(self, rhs: Self) -> Result<Ordering, ConstMathErr> {
-        match (self.ty, rhs.ty) {
-            (ast::FloatTy::F64, ast::FloatTy::F64)  => {
-                let a = Double::from_bits(self.bits);
-                let b = Double::from_bits(rhs.bits);
-                // This is pretty bad but it is the existing behavior.
-                Ok(a.partial_cmp(&b).unwrap_or(Ordering::Greater))
-            }
-
-            (ast::FloatTy::F32, ast::FloatTy::F32) => {
-                let a = Single::from_bits(self.bits);
-                let b = Single::from_bits(rhs.bits);
-                Ok(a.partial_cmp(&b).unwrap_or(Ordering::Greater))
-            }
-
-            _ => Err(CmpBetweenUnequalTypes),
-        }
-    }
-
-    pub fn from_i128(input: i128, ty: ast::FloatTy) -> Self {
-        let bits = match ty {
-            ast::FloatTy::F32 => Single::from_i128(input).value.to_bits(),
-            ast::FloatTy::F64 => Double::from_i128(input).value.to_bits()
-        };
-        ConstFloat { bits, ty }
-    }
-
-    pub fn from_u128(input: u128, ty: ast::FloatTy) -> Self {
-        let bits = match ty {
-            ast::FloatTy::F32 => Single::from_u128(input).value.to_bits(),
-            ast::FloatTy::F64 => Double::from_u128(input).value.to_bits()
-        };
-        ConstFloat { bits, ty }
-    }
-
-    pub fn from_str(num: &str, ty: ast::FloatTy) -> Result<Self, ParseFloatError> {
-        let bits = match ty {
-            ast::FloatTy::F32 => {
-                let rust_bits = num.parse::<f32>()?.to_bits() as u128;
-                let apfloat = num.parse::<Single>().unwrap_or_else(|e| {
-                    panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e);
-                });
-                let apfloat_bits = apfloat.to_bits();
-                assert!(rust_bits == apfloat_bits,
-                    "apfloat::ieee::Single gave different result for `{}`: \
-                     {}({:#x}) vs Rust's {}({:#x})",
-                    num, apfloat, apfloat_bits,
-                    Single::from_bits(rust_bits), rust_bits);
-                apfloat_bits
-            }
-            ast::FloatTy::F64 => {
-                let rust_bits = num.parse::<f64>()?.to_bits() as u128;
-                let apfloat = num.parse::<Double>().unwrap_or_else(|e| {
-                    panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e);
-                });
-                let apfloat_bits = apfloat.to_bits();
-                assert!(rust_bits == apfloat_bits,
-                    "apfloat::ieee::Double gave different result for `{}`: \
-                     {}({:#x}) vs Rust's {}({:#x})",
-                    num, apfloat, apfloat_bits,
-                    Double::from_bits(rust_bits), rust_bits);
-                apfloat_bits
-            }
-        };
-        Ok(ConstFloat { bits, ty })
-    }
-
-    pub fn to_i128(self, width: usize) -> Option<i128> {
-        assert!(width <= 128);
-        let r = match self.ty {
-            ast::FloatTy::F32 => Single::from_bits(self.bits).to_i128(width),
-            ast::FloatTy::F64 => Double::from_bits(self.bits).to_i128(width)
-        };
-        if r.status.intersects(Status::INVALID_OP) {
-            None
-        } else {
-            Some(r.value)
-        }
-    }
-
-    pub fn to_u128(self, width: usize) -> Option<u128> {
-        assert!(width <= 128);
-        let r = match self.ty {
-            ast::FloatTy::F32 => Single::from_bits(self.bits).to_u128(width),
-            ast::FloatTy::F64 => Double::from_bits(self.bits).to_u128(width)
-        };
-        if r.status.intersects(Status::INVALID_OP) {
-            None
-        } else {
-            Some(r.value)
-        }
-    }
-
-    pub fn convert(self, to: ast::FloatTy) -> Self {
-        let bits = match (self.ty, to) {
-            (ast::FloatTy::F32, ast::FloatTy::F32) |
-            (ast::FloatTy::F64, ast::FloatTy::F64) => return self,
-
-            (ast::FloatTy::F32, ast::FloatTy::F64) => {
-                Double::to_bits(Single::from_bits(self.bits).convert(&mut false).value)
-            }
-            (ast::FloatTy::F64, ast::FloatTy::F32) => {
-                Single::to_bits(Double::from_bits(self.bits).convert(&mut false).value)
-            }
-        };
-        ConstFloat { bits, ty: to }
-    }
-}
-
-impl ::std::fmt::Display for ConstFloat {
-    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
-        match self.ty {
-            ast::FloatTy::F32 => write!(fmt, "{:#}", Single::from_bits(self.bits))?,
-            ast::FloatTy::F64 => write!(fmt, "{:#}", Double::from_bits(self.bits))?,
-        }
-        write!(fmt, "{}", self.ty)
-    }
-}
-
-impl ::std::fmt::Debug for ConstFloat {
-    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
-        ::std::fmt::Display::fmt(self, fmt)
-    }
-}
-
-macro_rules! derive_binop {
-    ($op:ident, $func:ident) => {
-        impl ::std::ops::$op for ConstFloat {
-            type Output = Result<Self, ConstMathErr>;
-            fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
-                let bits = match (self.ty, rhs.ty) {
-                    (ast::FloatTy::F32, ast::FloatTy::F32) =>{
-                        let a = Single::from_bits(self.bits);
-                        let b = Single::from_bits(rhs.bits);
-                        a.$func(b).value.to_bits()
-                    }
-                    (ast::FloatTy::F64, ast::FloatTy::F64) => {
-                        let a = Double::from_bits(self.bits);
-                        let b = Double::from_bits(rhs.bits);
-                        a.$func(b).value.to_bits()
-                    }
-                    _ => return Err(UnequalTypes(Op::$op)),
-                };
-                Ok(ConstFloat { bits, ty: self.ty })
-            }
-        }
-    }
-}
-
-derive_binop!(Add, add);
-derive_binop!(Sub, sub);
-derive_binop!(Mul, mul);
-derive_binop!(Div, div);
-derive_binop!(Rem, rem);
-
-impl ::std::ops::Neg for ConstFloat {
-    type Output = Self;
-    fn neg(self) -> Self {
-        let bits = match self.ty {
-            ast::FloatTy::F32 => (-Single::from_bits(self.bits)).to_bits(),
-            ast::FloatTy::F64 => (-Double::from_bits(self.bits)).to_bits(),
-        };
-        ConstFloat { bits, ty: self.ty }
-    }
-}
-
-/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this
-/// are rounded to infinity when converted to `f32`.
-///
-/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP)
-/// shifted by the maximum exponent (accounting for normalization).
-pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
-                                        << (Single::MAX_EXP - Single::PRECISION as i16);
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
deleted file mode 100644
index 499c330be1d..00000000000
--- a/src/librustc_const_math/lib.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2012-2013 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.
-
-//! Rusty Mathematics
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
-
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
-
-extern crate rustc_apfloat;
-
-extern crate syntax;
-
-extern crate serialize as rustc_serialize; // used by deriving
-
-mod float;
-mod err;
-
-pub use float::*;
-pub use err::{ConstMathErr, Op};
diff --git a/src/librustc_data_structures/lazy_btree_map.rs b/src/librustc_data_structures/lazy_btree_map.rs
new file mode 100644
index 00000000000..74f91af10fe
--- /dev/null
+++ b/src/librustc_data_structures/lazy_btree_map.rs
@@ -0,0 +1,108 @@
+// Copyright 2018 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::collections::btree_map;
+use std::collections::BTreeMap;
+
+/// A thin wrapper around BTreeMap that avoids allocating upon creation.
+///
+/// Vec, HashSet and HashMap all have the nice feature that they don't do any
+/// heap allocation when creating a new structure of the default size. In
+/// contrast, BTreeMap *does* allocate in that situation. The compiler uses
+/// B-Tree maps in some places such that many maps are created but few are
+/// inserted into, so having a BTreeMap alternative that avoids allocating on
+/// creation is a performance win.
+///
+/// Only a fraction of BTreeMap's functionality is currently supported.
+/// Additional functionality should be added on demand.
+#[derive(Debug)]
+pub struct LazyBTreeMap<K, V>(Option<BTreeMap<K, V>>);
+
+impl<K, V> LazyBTreeMap<K, V> {
+    pub fn new() -> LazyBTreeMap<K, V> {
+        LazyBTreeMap(None)
+    }
+
+    pub fn iter(&self) -> Iter<K, V> {
+        Iter(self.0.as_ref().map(|btm| btm.iter()))
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.as_ref().map_or(true, |btm| btm.is_empty())
+    }
+}
+
+impl<K: Ord, V> LazyBTreeMap<K, V> {
+    fn instantiate(&mut self) -> &mut BTreeMap<K, V> {
+        if let Some(ref mut btm) = self.0 {
+            btm
+        } else {
+            let btm = BTreeMap::new();
+            self.0 = Some(btm);
+            self.0.as_mut().unwrap()
+        }
+    }
+
+    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
+        self.instantiate().insert(key, value)
+    }
+
+    pub fn entry(&mut self, key: K) -> btree_map::Entry<K, V> {
+        self.instantiate().entry(key)
+    }
+
+    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+        Values(self.0.as_ref().map(|btm| btm.values()))
+    }
+}
+
+impl<K: Ord, V> Default for LazyBTreeMap<K, V> {
+    fn default() -> LazyBTreeMap<K, V> {
+        LazyBTreeMap::new()
+    }
+}
+
+impl<'a, K: 'a, V: 'a> IntoIterator for &'a LazyBTreeMap<K, V> {
+    type Item = (&'a K, &'a V);
+    type IntoIter = Iter<'a, K, V>;
+
+    fn into_iter(self) -> Iter<'a, K, V> {
+        self.iter()
+    }
+}
+
+pub struct Iter<'a, K: 'a, V: 'a>(Option<btree_map::Iter<'a, K, V>>);
+
+impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
+    type Item = (&'a K, &'a V);
+
+    fn next(&mut self) -> Option<(&'a K, &'a V)> {
+        self.0.as_mut().and_then(|iter| iter.next())
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.as_ref().map_or_else(|| (0, Some(0)), |iter| iter.size_hint())
+    }
+}
+
+pub struct Values<'a, K: 'a, V: 'a>(Option<btree_map::Values<'a, K, V>>);
+
+impl<'a, K, V> Iterator for Values<'a, K, V> {
+    type Item = &'a V;
+
+    fn next(&mut self) -> Option<&'a V> {
+        self.0.as_mut().and_then(|values| values.next())
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.as_ref().map_or_else(|| (0, Some(0)), |values| values.size_hint())
+    }
+}
+
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 1320fe75bc5..597d1627ada 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -60,6 +60,7 @@ pub mod bitvec;
 pub mod graph;
 pub mod indexed_set;
 pub mod indexed_vec;
+pub mod lazy_btree_map;
 pub mod obligation_forest;
 pub mod sip128;
 pub mod snapshot_map;
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index b203f387e46..a1052ca6c3c 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1060,7 +1060,7 @@ impl RustcDefaultCalls {
                     let mut cfgs = Vec::new();
                     for &(name, ref value) in sess.parse_sess.config.iter() {
                         let gated_cfg = GatedCfg::gate(&ast::MetaItem {
-                            ident: ast::Ident::with_empty_ctxt(name),
+                            ident: ast::Path::from_ident(name.to_ident()),
                             node: ast::MetaItemKind::Word,
                             span: DUMMY_SP,
                         });
@@ -1526,7 +1526,8 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
         let thread = cfg.spawn(f);
         thread.unwrap().join()
     } else {
-        Ok(f())
+        let f = panic::AssertUnwindSafe(f);
+        panic::catch_unwind(f)
     }
 }
 
diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs
index 280f3c8c796..6426286ccbc 100644
--- a/src/librustc_driver/profile/trace.rs
+++ b/src/librustc_driver/profile/trace.rs
@@ -10,7 +10,7 @@
 
 use super::*;
 use syntax_pos::SpanData;
-use rustc::ty::maps::QueryMsg;
+use rustc::util::common::QueryMsg;
 use std::fs::File;
 use std::time::{Duration, Instant};
 use std::collections::hash_map::HashMap;
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 47c49fbe9ef..d2ee3d8743c 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -303,11 +303,11 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_str())
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_interned_str())
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
-        let name = Symbol::intern(name).as_str();
+        let name = Symbol::intern(name).as_interned_str();
         self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID),
             index,
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 40e4efb397d..75401f21862 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -11,6 +11,7 @@
 use CodeSuggestion;
 use SubstitutionPart;
 use Substitution;
+use Applicability;
 use Level;
 use std::fmt;
 use syntax_pos::{MultiSpan, Span};
@@ -222,7 +223,7 @@ impl Diagnostic {
             }],
             msg: msg.to_owned(),
             show_code_when_inline: false,
-            approximate: false,
+            applicability: Applicability::Unspecified,
         });
         self
     }
@@ -253,7 +254,7 @@ impl Diagnostic {
             }],
             msg: msg.to_owned(),
             show_code_when_inline: true,
-            approximate: false,
+            applicability: Applicability::Unspecified,
         });
         self
     }
@@ -269,15 +270,16 @@ impl Diagnostic {
             }).collect(),
             msg: msg.to_owned(),
             show_code_when_inline: true,
-            approximate: false,
+            applicability: Applicability::Unspecified,
         });
         self
     }
 
     /// This is a suggestion that may contain mistakes or fillers and should
     /// be read and understood by a human.
-    pub fn span_approximate_suggestion(&mut self, sp: Span, msg: &str,
-                                       suggestion: String) -> &mut Self {
+    pub fn span_suggestion_with_applicability(&mut self, sp: Span, msg: &str,
+                                       suggestion: String,
+                                       applicability: Applicability) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitutions: vec![Substitution {
                 parts: vec![SubstitutionPart {
@@ -287,13 +289,14 @@ impl Diagnostic {
             }],
             msg: msg.to_owned(),
             show_code_when_inline: true,
-            approximate: true,
+            applicability,
         });
         self
     }
 
-    pub fn span_approximate_suggestions(&mut self, sp: Span, msg: &str,
-                                        suggestions: Vec<String>) -> &mut Self {
+    pub fn span_suggestions_with_applicability(&mut self, sp: Span, msg: &str,
+                                        suggestions: Vec<String>,
+                                        applicability: Applicability) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitutions: suggestions.into_iter().map(|snippet| Substitution {
                 parts: vec![SubstitutionPart {
@@ -303,7 +306,7 @@ impl Diagnostic {
             }).collect(),
             msg: msg.to_owned(),
             show_code_when_inline: true,
-            approximate: true,
+            applicability,
         });
         self
     }
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 945ecce7ab3..7e9ca8633a5 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -11,6 +11,7 @@
 use Diagnostic;
 use DiagnosticId;
 use DiagnosticStyledString;
+use Applicability;
 
 use Level;
 use Handler;
@@ -187,15 +188,17 @@ impl<'a> DiagnosticBuilder<'a> {
                                      msg: &str,
                                      suggestions: Vec<String>)
                                      -> &mut Self);
-    forward!(pub fn span_approximate_suggestion(&mut self,
+    forward!(pub fn span_suggestion_with_applicability(&mut self,
                                                 sp: Span,
                                                 msg: &str,
-                                                suggestion: String)
+                                                suggestion: String,
+                                                applicability: Applicability)
                                                 -> &mut Self);
-    forward!(pub fn span_approximate_suggestions(&mut self,
+    forward!(pub fn span_suggestions_with_applicability(&mut self,
                                                  sp: Span,
                                                  msg: &str,
-                                                 suggestions: Vec<String>)
+                                                 suggestions: Vec<String>,
+                                                 applicability: Applicability)
                                                  -> &mut Self);
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
     forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index ce3efef08cc..c2b442e9497 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -56,6 +56,14 @@ mod lock;
 
 use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION};
 
+#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum Applicability {
+    MachineApplicable,
+    HasPlaceholders,
+    MaybeIncorrect,
+    Unspecified
+}
+
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct CodeSuggestion {
     /// Each substitute can have multiple variants due to multiple
@@ -87,7 +95,7 @@ pub struct CodeSuggestion {
     /// Sometimes we may show suggestions with placeholders,
     /// which are useful for users but not useful for
     /// tools like rustfix
-    pub approximate: bool,
+    pub applicability: Applicability,
 }
 
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 57311a7b588..38e891008f7 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -110,7 +110,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
         for list_item in attr.meta_item_list().unwrap_or_default() {
             match list_item.word() {
                 Some(word) if value.is_none() =>
-                    value = Some(word.ident.name),
+                    value = Some(word.name()),
                 _ =>
                     // FIXME better-encapsulate meta_item (don't directly access `node`)
                     span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node),
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index 46ba94f2061..6906dacfc5e 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -74,7 +74,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
 
         let mname = self.field(attr, MODULE);
         let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
-        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
+        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str();
 
         let dep_node = DepNode::new(self.tcx,
                                     DepConstructor::CompileCodegenUnit(mangled_cgu_name));
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 91ce6f3854a..f06062fa4ac 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -675,9 +675,8 @@ impl LintPass for DeprecatedAttr {
 
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
-        let name = unwrap_or!(attr.name(), return);
         for &&(n, _, ref g) in &self.depr_attrs {
-            if name == n {
+            if attr.name() == n {
                 if let &AttributeGate::Gated(Stability::Deprecated(link),
                                              ref name,
                                              ref reason,
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 65b340d6568..4f6d23dce6d 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -30,7 +30,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 
-#[macro_use]
 extern crate syntax;
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index bf86f6a6952..8df40b62ddd 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::ty;
 use rustc::ty::adjustment;
@@ -72,40 +73,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
 
         let mut fn_warned = false;
         let mut op_warned = false;
-        if cx.tcx.features().fn_must_use {
-            let maybe_def = match expr.node {
-                hir::ExprCall(ref callee, _) => {
-                    match callee.node {
-                        hir::ExprPath(ref qpath) => {
-                            Some(cx.tables.qpath_def(qpath, callee.hir_id))
-                        },
-                        _ => None
-                    }
-                },
-                hir::ExprMethodCall(..) => {
-                    cx.tables.type_dependent_defs().get(expr.hir_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 let hir::ExprBinary(bin_op, ..) = expr.node {
+        let maybe_def = match expr.node {
+            hir::ExprCall(ref callee, _) => {
+                match callee.node {
+                    hir::ExprPath(ref qpath) => {
+                        let def = cx.tables.qpath_def(qpath, callee.hir_id);
+                        if let Def::Fn(_) = def {
+                            Some(def)
+                        } else {  // `Def::Local` if it was a closure, for which we
+                            None  // do not currently support must-use linting
+                        }
+                    },
+                    _ => None
+                }
+            },
+            hir::ExprMethodCall(..) => {
+                cx.tables.type_dependent_defs().get(expr.hir_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 ");
+        }
+        let must_use_op = match expr.node {
+            // Hardcoding operators here seemed more expedient than the
+            // refactoring that would be needed to look up the `#[must_use]`
+            // attribute which does exist on the comparison trait methods
+            hir::ExprBinary(bin_op, ..)  => {
                 match bin_op.node {
-                    // Hardcoding the comparison operators here seemed more
-                    // expedient than the refactoring that would be needed to
-                    // look up the `#[must_use]` attribute which does exist on
-                    // the comparison trait methods
                     hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
-                        let msg = "unused comparison which must be used";
-                        cx.span_lint(UNUSED_MUST_USE, expr.span, msg);
-                        op_warned = true;
+                        Some("comparison")
+                    },
+                    hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => {
+                        Some("arithmetic operation")
+                    },
+                    hir::BiAnd | hir::BiOr => {
+                        Some("logical operation")
+                    },
+                    hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => {
+                        Some("bitwise operation")
                     },
-                    _ => {},
                 }
-            }
+            },
+            hir::ExprUnary(..) => Some("unary operation"),
+            _ => None
+        };
+
+        if let Some(must_use_op) = must_use_op {
+            cx.span_lint(UNUSED_MUST_USE, expr.span,
+                         &format!("unused {} which must be used", must_use_op));
+            op_warned = true;
         }
 
         if !(ty_warned || fn_warned || op_warned) {
@@ -174,8 +192,6 @@ impl LintPass for UnusedAttributes {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
     fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
         debug!("checking attribute: {:?}", attr);
-        let name = unwrap_or!(attr.name(), return);
-
         // Note that check_name() marks the attribute as used if it matches.
         for &(ref name, ty, _) in BUILTIN_ATTRIBUTES {
             match ty {
@@ -195,6 +211,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
             }
         }
 
+        let name = attr.name();
         if !attr::is_used(attr) {
             debug!("Emitting warning for: {:?}", attr);
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index a11b95cb5b6..fdfe2a98bf9 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -51,7 +51,7 @@ macro_rules! provide {
         pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) {
             $(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T)
                                     -> <ty::queries::$name<$lt> as
-                                        QueryConfig>::Value
+                                        QueryConfig<$lt>>::Value
                 where T: IntoArgs,
             {
                 #[allow(unused_variables)]
@@ -535,7 +535,7 @@ impl CrateStore for cstore::CStore {
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::from_str(&name),
+            ident: ast::Ident::from_str(&name.as_str()),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 0147e8dc607..57f92707ccf 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -40,7 +40,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
-use syntax::symbol::{InternedString, Symbol};
+use syntax::symbol::InternedString;
 use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
 
@@ -537,12 +537,12 @@ impl<'a, 'tcx> CrateMetadata {
 
         ty::VariantDef {
             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-            name: Symbol::intern(&self.item_name(index)),
+            name: self.item_name(index).as_symbol(),
             fields: item.children.decode(self).map(|index| {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    name: Symbol::intern(&self.item_name(index)),
+                    name: self.item_name(index).as_symbol(),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -730,7 +730,7 @@ impl<'a, 'tcx> CrateMetadata {
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
                                     def,
-                                    ident: Ident::from_str(&self.item_name(child_index)),
+                                    ident: Ident::from_interned_str(self.item_name(child_index)),
                                     vis: self.get_visibility(child_index),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                     is_import: false,
@@ -748,7 +748,7 @@ impl<'a, 'tcx> CrateMetadata {
                 let span = child.span.decode((self, sess));
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::from_str(&name);
+                    let ident = Ident::from_interned_str(name);
                     let vis = self.get_visibility(child_index);
                     let is_import = false;
                     callback(def::Export { def, ident, vis, span, is_import });
@@ -847,7 +847,7 @@ impl<'a, 'tcx> CrateMetadata {
         };
 
         ty::AssociatedItem {
-            name: Symbol::intern(&name),
+            name: name.as_symbol(),
             kind,
             vis: item.visibility.decode(self),
             defaultness: container.defaultness(),
@@ -914,7 +914,7 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(id)
             .children
             .decode(self)
-            .map(|index| Symbol::intern(&self.item_name(index)))
+            .map(|index| self.item_name(index).as_symbol())
             .collect()
     }
 
@@ -977,7 +977,13 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
-        self.def_key(id).parent.and_then(|parent_index| {
+        let def_key = self.def_key(id);
+        match def_key.disambiguated_data.data {
+            DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
+            // Not an associated item
+            _ => return None,
+        }
+        def_key.parent.and_then(|parent_index| {
             match self.entry(parent_index).kind {
                 EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
                 _ => None,
@@ -1106,7 +1112,7 @@ impl<'a, 'tcx> CrateMetadata {
             DefKey {
                 parent: Some(CRATE_DEF_INDEX),
                 disambiguated_data: DisambiguatedDefPathData {
-                    data: DefPathData::MacroDef(name.as_str()),
+                    data: DefPathData::MacroDef(name.as_interned_str()),
                     disambiguator: 0,
                 }
             }
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index a1b348774b1..62964745b6f 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -16,7 +16,6 @@ log = "0.4"
 log_settings = "0.1.1"
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 3dc5a7a8490..db2e078586e 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -471,7 +471,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             | (RegionKind::ReClosureBound(_), _)
             | (RegionKind::ReCanonical(_), _)
             | (RegionKind::ReErased, _) => {
-                span_bug!(drop_span, "region does not make sense in this context");
+                span_bug!(drop_span, "region {:?} does not make sense in this context",
+                          borrow.region);
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs
new file mode 100644
index 00000000000..28da1b2d733
--- /dev/null
+++ b/src/librustc_mir/borrow_check/location.rs
@@ -0,0 +1,123 @@
+// 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 rustc::mir::{BasicBlock, Location, Mir};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+
+/// Maps between a MIR Location, which identifies the a particular
+/// statement within a basic block, to a "rich location", which
+/// identifies at a finer granularity. In particular, we distinguish
+/// the *start* of a statement and the *mid-point*. The mid-point is
+/// the point *just* before the statement takes effect; in particular,
+/// for an assignment `A = B`, it is the point where B is about to be
+/// written into A. This mid-point is a kind of hack to work around
+/// our inability to track the position information at sufficient
+/// granularity through outlives relations; however, the rich location
+/// table serves another purpose: it compresses locations from
+/// multiple words into a single u32.
+crate struct LocationTable {
+    num_points: usize,
+    statements_before_block: IndexVec<BasicBlock, usize>,
+}
+
+newtype_index!(LocationIndex { DEBUG_FORMAT = "LocationIndex({})" });
+
+#[derive(Copy, Clone, Debug)]
+crate enum RichLocation {
+    Start(Location),
+    Mid(Location),
+}
+
+impl LocationTable {
+    crate fn new(mir: &Mir<'_>) -> Self {
+        let mut num_points = 0;
+        let statements_before_block = mir.basic_blocks()
+            .iter()
+            .map(|block_data| {
+                let v = num_points;
+                num_points += (block_data.statements.len() + 1) * 2;
+                v
+            })
+            .collect();
+
+        debug!(
+            "LocationTable(statements_before_block={:#?})",
+            statements_before_block
+        );
+        debug!("LocationTable: num_points={:#?}", num_points);
+
+        Self {
+            num_points,
+            statements_before_block,
+        }
+    }
+
+    crate fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
+        (0..self.num_points).map(LocationIndex::new)
+    }
+
+    crate fn start_index(&self, location: Location) -> LocationIndex {
+        let Location {
+            block,
+            statement_index,
+        } = location;
+        let start_index = self.statements_before_block[block];
+        LocationIndex::new(start_index + statement_index * 2)
+    }
+
+    crate fn mid_index(&self, location: Location) -> LocationIndex {
+        let Location {
+            block,
+            statement_index,
+        } = location;
+        let start_index = self.statements_before_block[block];
+        LocationIndex::new(start_index + statement_index * 2 + 1)
+    }
+
+    crate fn to_location(&self, index: LocationIndex) -> RichLocation {
+        let point_index = index.index();
+
+        // Find the basic block. We have a vector with the
+        // starting index of the statement in each block. Imagine
+        // we have statement #22, and we have a vector like:
+        //
+        // [0, 10, 20]
+        //
+        // In that case, this represents point_index 2 of
+        // basic block BB2. We know this because BB0 accounts for
+        // 0..10, BB1 accounts for 11..20, and BB2 accounts for
+        // 20...
+        //
+        // To compute this, we could do a binary search, but
+        // because I am lazy we instead iterate through to find
+        // the last point where the "first index" (0, 10, or 20)
+        // was less than the statement index (22). In our case, this will
+        // be (BB2, 20).
+        let (block, &first_index) = self.statements_before_block
+            .iter_enumerated()
+            .filter(|(_, first_index)| **first_index <= point_index)
+            .last()
+            .unwrap();
+
+        let statement_index = (point_index - first_index) / 2;
+        if index.is_start() {
+            RichLocation::Start(Location { block, statement_index })
+        } else {
+            RichLocation::Mid(Location { block, statement_index })
+        }
+    }
+}
+
+impl LocationIndex {
+    fn is_start(&self) -> bool {
+        // even indices are start points; odd indices are mid points
+        (self.index() % 2) == 0
+    }
+}
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4dd8d245d3b..3e3f510e308 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -17,15 +17,17 @@ use rustc::hir::map::definitions::DefPathData;
 use rustc::infer::InferCtxt;
 use rustc::ty::{self, ParamEnv, TyCtxt};
 use rustc::ty::maps::Providers;
-use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place};
-use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
-use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
-use rustc::mir::ClosureRegionRequirements;
+use rustc::lint::builtin::UNUSED_MUT;
+use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
+use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand};
+use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind};
+use rustc::mir::{Terminator, TerminatorKind};
 
 use rustc_data_structures::control_flow_graph::dominators::Dominators;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::small_vec::SmallVec;
 
 use std::rc::Rc;
 
@@ -48,12 +50,14 @@ use std::iter;
 
 use self::borrow_set::{BorrowSet, BorrowData};
 use self::flows::Flows;
+use self::location::LocationTable;
 use self::prefixes::PrefixSet;
 use self::MutateMode::{JustWrite, WriteAndRead};
 
 crate mod borrow_set;
 mod error_reporting;
 mod flows;
+mod location;
 crate mod place_ext;
 mod prefixes;
 
@@ -69,12 +73,15 @@ pub fn provide(providers: &mut Providers) {
 fn mir_borrowck<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
-) -> Option<ClosureRegionRequirements<'tcx>> {
+) -> BorrowCheckResult<'tcx> {
     let input_mir = tcx.mir_validated(def_id);
     debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
 
     if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() {
-        return None;
+        return BorrowCheckResult {
+            closure_requirements: None,
+            used_mut_upvars: SmallVec::new(),
+        };
     }
 
     let opt_closure_req = tcx.infer_ctxt().enter(|infcx| {
@@ -90,7 +97,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     input_mir: &Mir<'gcx>,
     def_id: DefId,
-) -> Option<ClosureRegionRequirements<'gcx>> {
+) -> BorrowCheckResult<'gcx> {
     let tcx = infcx.tcx;
     let attributes = tcx.get_attrs(def_id);
     let param_env = tcx.param_env(def_id);
@@ -105,6 +112,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let mut mir: Mir<'tcx> = input_mir.clone();
     let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir);
     let mir = &mir; // no further changes
+    let location_table = &LocationTable::new(mir);
 
     let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) {
         Ok(move_data) => move_data,
@@ -194,6 +202,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         def_id,
         free_regions,
         mir,
+        location_table,
         param_env,
         &mut flow_inits,
         &mdpe.move_data,
@@ -237,6 +246,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         reservation_error_reported: FxHashSet(),
         moved_error_reported: FxHashSet(),
         nonlexical_regioncx: regioncx,
+        used_mut: FxHashSet(),
+        used_mut_upvars: SmallVec::new(),
         nonlexical_cause_info: None,
         borrow_set,
         dominators,
@@ -252,7 +263,66 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
 
     mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
 
-    opt_closure_req
+    // For each non-user used mutable variable, check if it's been assigned from
+    // a user-declared local. If so, then put that local into the used_mut set.
+    // Note that this set is expected to be small - only upvars from closures
+    // would have a chance of erroneously adding non-user-defined mutable vars
+    // to the set.
+    let temporary_used_locals: FxHashSet<Local> =
+        mbcx.used_mut.iter()
+            .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable)
+            .cloned()
+            .collect();
+
+    for local in temporary_used_locals {
+        for location in mbcx.mir.find_assignments(local) {
+            for moi in &mbcx.move_data.loc_map[location] {
+                let mpi = &mbcx.move_data.moves[*moi].path;
+                let path = &mbcx.move_data.move_paths[*mpi];
+                debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set",
+                       path.place, local, path.place);
+                if let Place::Local(user_local) = path.place {
+                    mbcx.used_mut.insert(user_local);
+                }
+            }
+        }
+    }
+
+    debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
+
+    for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) {
+        if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.visibility_scope_info {
+            let local_decl = &mbcx.mir.local_decls[local];
+
+            // Skip implicit `self` argument for closures
+            if local.index() == 1 && tcx.is_closure(mbcx.mir_def_id) {
+                continue;
+            }
+
+            // Skip over locals that begin with an underscore or have no name
+            match local_decl.name {
+                Some(name) => if name.as_str().starts_with("_") { continue; },
+                None => continue,
+            }
+
+            let source_info = local_decl.source_info;
+            let mut_span = tcx.sess.codemap().span_until_non_whitespace(source_info.span);
+
+            tcx.struct_span_lint_node(
+                UNUSED_MUT,
+                vsi[local_decl.syntactic_scope].lint_root,
+                source_info.span,
+                "variable does not need to be mutable"
+            )
+            .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
+            .emit();
+        }
+    }
+
+    BorrowCheckResult {
+        closure_requirements: opt_closure_req,
+        used_mut_upvars: mbcx.used_mut_upvars,
+    }
 }
 
 #[allow(dead_code)]
@@ -287,6 +357,12 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// This field keeps track of errors reported in the checking of moved variables,
     /// so that we don't report report seemingly duplicate errors.
     moved_error_reported: FxHashSet<Place<'tcx>>,
+    /// This field keeps track of all the local variables that are declared mut and are mutated.
+    /// Used for the warning issued by an unused mutable local variable.
+    used_mut: FxHashSet<Local>,
+    /// If the function we're checking is a closure, then we'll need to report back the list of
+    /// mutable upvars that have been used. This field keeps track of them.
+    used_mut_upvars: SmallVec<[Field; 8]>,
     /// Non-lexical region inference context, if NLL is enabled.  This
     /// contains the results from region inference and lets us e.g.
     /// find out which CFG points are contained in each borrow region.
@@ -514,18 +590,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 cleanup: _,
             } => {
                 self.consume_operand(ContextKind::Assert.new(loc), (cond, span), flow_state);
-                match *msg {
-                    AssertMessage::BoundsCheck { ref len, ref index } => {
-                        self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
-                        self.consume_operand(
-                            ContextKind::Assert.new(loc),
-                            (index, span),
-                            flow_state,
-                        );
-                    }
-                    AssertMessage::Math(_ /*const_math_err*/) => {}
-                    AssertMessage::GeneratorResumedAfterReturn => {}
-                    AssertMessage::GeneratorResumedAfterPanic => {}
+                use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+                if let BoundsCheck { ref len, ref index } = *msg {
+                    self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
+                    self.consume_operand(
+                        ContextKind::Assert.new(loc),
+                        (index, span),
+                        flow_state,
+                    );
                 }
             }
 
@@ -684,6 +756,11 @@ enum InitializationRequiringAction {
     Assignment,
 }
 
+struct RootPlace<'d, 'tcx: 'd> {
+    place: &'d Place<'tcx>,
+    is_local_mutation_allowed: LocalMutationIsAllowed,
+}
+
 impl InitializationRequiringAction {
     fn as_noun(self) -> &'static str {
         match self {
@@ -729,6 +806,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         erased_drop_place_ty: ty::Ty<'gcx>,
         span: Span,
     ) {
+        let gcx = self.tcx.global_tcx();
+        let drop_field = |
+            mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+            (index, field): (usize, ty::Ty<'gcx>),
+        | {
+            let field_ty = gcx.normalize_erasing_regions(mir.param_env, field);
+            let place = drop_place.clone().field(Field::new(index), field_ty);
+
+            mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
+        };
+
         match erased_drop_place_ty.sty {
             // When a struct is being dropped, we need to check
             // whether it has a destructor, if it does, then we can
@@ -737,14 +825,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             // destructor but `bar` does not, we will only check for
             // borrows of `x.foo` and not `x.bar`. See #47703.
             ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => {
-                for (index, field) in def.all_fields().enumerate() {
-                    let gcx = self.tcx.global_tcx();
-                    let field_ty = field.ty(gcx, substs);
-                    let field_ty = gcx.normalize_erasing_regions(self.param_env, field_ty);
-                    let place = drop_place.clone().field(Field::new(index), field_ty);
-
-                    self.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
-                }
+                def.all_fields()
+                    .map(|field| field.ty(gcx, substs))
+                    .enumerate()
+                    .for_each(|field| drop_field(self, field));
+            }
+            // Same as above, but for tuples.
+            ty::TyTuple(tys) => {
+                tys.iter().cloned().enumerate()
+                    .for_each(|field| drop_field(self, field));
+            }
+            // Closures and generators also have disjoint fields, but they are only
+            // directly accessed in the body of the closure/generator.
+            ty::TyClosure(def, substs)
+            | ty::TyGenerator(def, substs, ..)
+                if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
+            => {
+                substs.upvar_tys(def, self.tcx).enumerate()
+                    .for_each(|field| drop_field(self, field));
             }
             _ => {
                 // We have now refined the type of the value being
@@ -752,7 +850,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // subfield; so check whether that field's type still
                 // "needs drop". If so, we assume that the destructor
                 // may access any data it likes (i.e., a Deep Write).
-                let gcx = self.tcx.global_tcx();
                 if erased_drop_place_ty.needs_drop(gcx, self.param_env) {
                     self.access_place(
                         ContextKind::Drop.new(loc),
@@ -810,7 +907,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         }
 
         let mutability_error =
-            self.check_access_permissions(place_span, rw, is_local_mutation_allowed);
+            self.check_access_permissions(place_span, rw, is_local_mutation_allowed, flow_state);
         let conflict_error =
             self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
 
@@ -1077,9 +1174,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // `NullOp::Box`?
             }
 
-            Rvalue::Aggregate(ref _aggregate_kind, ref operands) => for operand in operands {
-                self.consume_operand(context, (operand, span), flow_state);
-            },
+            Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
+                // We need to report back the list of mutable upvars that were
+                // moved into the closure and subsequently used by the closure,
+                // in order to populate our used_mut set.
+                if let AggregateKind::Closure(def_id, _) = &**aggregate_kind {
+                    let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id);
+                    debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
+                    for field in used_mut_upvars {
+                        match operands[field.index()] {
+                            Operand::Move(Place::Local(local)) => {
+                                self.used_mut.insert(local);
+                            }
+                            Operand::Move(ref place @ Place::Projection(_)) => {
+                                if let Some(field) = self.is_upvar_field_projection(place) {
+                                    self.used_mut_upvars.push(field);
+                                }
+                            }
+                            Operand::Move(Place::Static(..)) |
+                            Operand::Copy(..) |
+                            Operand::Constant(..) => {}
+                        }
+                    }
+                }
+
+                for operand in operands {
+                    self.consume_operand(context, (operand, span), flow_state);
+                }
+            }
         }
     }
 
@@ -1280,7 +1402,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ) {
         debug!("check_if_reassignment_to_immutable_state({:?})", place);
         // determine if this path has a non-mut owner (and thus needs checking).
-        if let Ok(()) = self.is_mutable(place, LocalMutationIsAllowed::No) {
+        if let Ok(..) = self.is_mutable(place, LocalMutationIsAllowed::No) {
             return;
         }
         debug!(
@@ -1574,10 +1696,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ///
     /// Returns true if an error is reported, false otherwise.
     fn check_access_permissions(
-        &self,
+        &mut self,
         (place, span): (&Place<'tcx>, Span),
         kind: ReadOrWrite,
         is_local_mutation_allowed: LocalMutationIsAllowed,
+        flow_state: &Flows<'cx, 'gcx, 'tcx>,
     ) -> bool {
         debug!(
             "check_access_permissions({:?}, {:?}, {:?})",
@@ -1592,90 +1715,93 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
             }
             Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. }))
-            | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) =
-                self.is_mutable(place, is_local_mutation_allowed)
-            {
-                error_reported = true;
-                let item_msg = self.get_default_err_msg(place);
-                let mut err = self.tcx
-                    .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
-                err.span_label(span, "cannot borrow as mutable");
-
-                if place != place_err {
-                    if let Some(name) = self.describe_place(place_err) {
-                        err.note(&format!("the value which is causing this path not to be mutable \
-                                           is...: `{}`", name));
-                    }
-                }
-
-                err.emit();
-            },
-            Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
-
-                if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) {
-                    error_reported = true;
-                    let mut err_info = None;
-                    match *place_err {
-
-                        Place::Projection(box Projection {
-                        ref base, elem:ProjectionElem::Deref}) => {
-                            match *base {
-                                Place::Local(local) => {
-                                    let locations = self.mir.find_assignments(local);
-                                        if locations.len() > 0 {
-                                            let item_msg = if error_reported {
-                                                self.get_secondary_err_msg(base)
-                                            } else {
-                                                self.get_default_err_msg(place)
-                                            };
-                                            let sp = self.mir.source_info(locations[0]).span;
-                                            let mut to_suggest_span = String::new();
-                                            if let Ok(src) =
-                                                self.tcx.sess.codemap().span_to_snippet(sp) {
-                                                    to_suggest_span = src[1..].to_string();
-                                            };
-                                            err_info = Some((
-                                                    sp,
-                                                    "consider changing this to be a \
-                                                    mutable reference",
-                                                    to_suggest_span,
-                                                    item_msg,
-                                                    self.get_primary_err_msg(base)));
-                                        }
-                                },
-                            _ => {},
-                            }
-                        },
-                        _ => {},
-                    }
+            | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => {
+                match self.is_mutable(place, is_local_mutation_allowed) {
+                    Ok(root_place) => self.add_used_mut(root_place, flow_state),
+                    Err(place_err) => {
+                        error_reported = true;
+                        let item_msg = self.get_default_err_msg(place);
+                        let mut err = self.tcx
+                            .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
+                        err.span_label(span, "cannot borrow as mutable");
 
-                    if let Some((err_help_span,
-                                 err_help_stmt,
-                                 to_suggest_span,
-                                 item_msg,
-                                 sec_span)) = err_info {
-                        let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
-                        err.span_suggestion(err_help_span,
-                                            err_help_stmt,
-                                            format!("&mut {}", to_suggest_span));
-                        if place != place_err {
-                            err.span_label(span, sec_span);
-                        }
-                        err.emit()
-                    } else {
-                        let item_msg_ = self.get_default_err_msg(place);
-                        let mut err = self.tcx.cannot_assign(span, &item_msg_, Origin::Mir);
-                        err.span_label(span, "cannot mutate");
                         if place != place_err {
                             if let Some(name) = self.describe_place(place_err) {
                                 err.note(&format!("the value which is causing this path not to be \
-                                                   mutable is...: `{}`", name));
+                                    mutable is...: `{}`", name));
                             }
                         }
+
                         err.emit();
                     }
                 }
             }
+            Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
+                match self.is_mutable(place, is_local_mutation_allowed) {
+                    Ok(root_place) => self.add_used_mut(root_place, flow_state),
+                    Err(place_err) => {
+                        error_reported = true;
+
+                        let err_info = if let Place::Projection(
+                            box Projection {
+                                base: Place::Local(local),
+                                elem: ProjectionElem::Deref
+                            }
+                        ) = *place_err {
+                            let locations = self.mir.find_assignments(local);
+                            if locations.len() > 0 {
+                                let item_msg = if error_reported {
+                                    self.get_secondary_err_msg(&Place::Local(local))
+                                } else {
+                                    self.get_default_err_msg(place)
+                                };
+                                let sp = self.mir.source_info(locations[0]).span;
+                                let mut to_suggest_span = String::new();
+                                if let Ok(src) =
+                                    self.tcx.sess.codemap().span_to_snippet(sp) {
+                                        to_suggest_span = src[1..].to_string();
+                                };
+                                Some((sp,
+                                      "consider changing this to be a \
+                                      mutable reference",
+                                      to_suggest_span,
+                                      item_msg,
+                                      self.get_primary_err_msg(&Place::Local(local))))
+                            } else {
+                                None
+                            }
+                        } else {
+                            None
+                        };
+
+                        if let Some((err_help_span,
+                                     err_help_stmt,
+                                     to_suggest_span,
+                                     item_msg,
+                                     sec_span)) = err_info {
+                            let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+                            err.span_suggestion(err_help_span,
+                                                err_help_stmt,
+                                                format!("&mut {}", to_suggest_span));
+                            if place != place_err {
+                                err.span_label(span, sec_span);
+                            }
+                            err.emit()
+                        } else {
+                            let item_msg = self.get_default_err_msg(place);
+                            let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+                            err.span_label(span, "cannot mutate");
+                            if place != place_err {
+                                if let Some(name) = self.describe_place(place_err) {
+                                    err.note(&format!("the value which is causing this path not \
+                                                       to be mutable is...: `{}`", name));
+                                }
+                            }
+                            err.emit();
+                        }
+                    }
+                }
+            }
             Reservation(WriteKind::Move)
             | Reservation(WriteKind::StorageDeadOrDrop)
             | Reservation(WriteKind::MutableBorrow(BorrowKind::Shared))
@@ -1702,30 +1828,76 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         error_reported
     }
 
-    /// Can this value be written or borrowed mutably
+    /// Adds the place into the used mutable variables set
+    fn add_used_mut<'d>(
+        &mut self,
+        root_place: RootPlace<'d, 'tcx>,
+        flow_state: &Flows<'cx, 'gcx, 'tcx>
+    ) {
+        match root_place {
+            RootPlace {
+                place: Place::Local(local),
+                is_local_mutation_allowed,
+            } => {
+                if is_local_mutation_allowed != LocalMutationIsAllowed::Yes {
+                    // If the local may be initialized, and it is now currently being
+                    // mutated, then it is justified to be annotated with the `mut`
+                    // keyword, since the mutation may be a possible reassignment.
+                    let mpi = self.move_data.rev_lookup.find_local(*local);
+                    if flow_state.inits.contains(&mpi) {
+                        self.used_mut.insert(*local);
+                    }
+                }
+            }
+            RootPlace {
+                place: place @ Place::Projection(_),
+                is_local_mutation_allowed: _,
+            } => {
+                if let Some(field) = self.is_upvar_field_projection(&place) {
+                    self.used_mut_upvars.push(field);
+                }
+            }
+            RootPlace {
+                place: Place::Static(..),
+                is_local_mutation_allowed: _,
+            } => {}
+        }
+    }
+
+    /// Whether this value be written or borrowed mutably.
+    /// Returns the root place if the place passed in is a projection.
     fn is_mutable<'d>(
         &self,
         place: &'d Place<'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-    ) -> Result<(), &'d Place<'tcx>> {
+    ) -> Result<RootPlace<'d, 'tcx>, &'d Place<'tcx>> {
         match *place {
             Place::Local(local) => {
                 let local = &self.mir.local_decls[local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
-                        LocalMutationIsAllowed::Yes | LocalMutationIsAllowed::ExceptUpvars => {
-                            Ok(())
+                        LocalMutationIsAllowed::Yes => {
+                            Ok(RootPlace {
+                                place,
+                                is_local_mutation_allowed: LocalMutationIsAllowed::Yes
+                            })
+                        }
+                        LocalMutationIsAllowed::ExceptUpvars => {
+                            Ok(RootPlace {
+                                place,
+                                is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars
+                            })
                         }
                         LocalMutationIsAllowed::No => Err(place),
                     },
-                    Mutability::Mut => Ok(()),
+                    Mutability::Mut => Ok(RootPlace { place, is_local_mutation_allowed }),
                 }
             }
             Place::Static(ref static_) =>
                 if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
                     Err(place)
                 } else {
-                    Ok(())
+                    Ok(RootPlace { place, is_local_mutation_allowed })
                 },
             Place::Projection(ref proj) => {
                 match proj.elem {
@@ -1761,9 +1933,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                 match tnm.mutbl {
                                     // `*const` raw pointers are not mutable
                                     hir::MutImmutable => return Err(place),
-                                    // `*mut` raw pointers are always mutable, regardless of context
-                                    // The users have to check by themselve.
-                                    hir::MutMutable => return Ok(()),
+                                    // `*mut` raw pointers are always mutable, regardless of
+                                    // context. The users have to check by themselves.
+                                    hir::MutMutable => {
+                                        return Ok(RootPlace { place, is_local_mutation_allowed });
+                                    }
                                 }
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable
@@ -1794,7 +1968,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                 }
                                 (Mutability::Not, LocalMutationIsAllowed::Yes)
                                 | (Mutability::Mut, _) => {
-                                    self.is_mutable(&proj.base, is_local_mutation_allowed)
+                                    // Subtle: this is an upvar
+                                    // reference, so it looks like
+                                    // `self.foo` -- we want to double
+                                    // check that the context `*self`
+                                    // is mutable (i.e., this is not a
+                                    // `Fn` closure).  But if that
+                                    // check succeeds, we want to
+                                    // *blame* the mutability on
+                                    // `place` (that is,
+                                    // `self.foo`). This is used to
+                                    // propagate the info about
+                                    // whether mutability declarations
+                                    // are used outwards, so that we register
+                                    // the outer variable as mutable. Otherwise a
+                                    // test like this fails to record the `mut`
+                                    // as needed:
+                                    //
+                                    // ```
+                                    // fn foo<F: FnOnce()>(_f: F) { }
+                                    // fn main() {
+                                    //     let var = Vec::new();
+                                    //     foo(move || {
+                                    //         var.push(1);
+                                    //     });
+                                    // }
+                                    // ```
+                                    let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?;
+                                    Ok(RootPlace { place, is_local_mutation_allowed })
                                 }
                             }
                         } else {
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index afaedecdf0a..d34e9434fbf 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -8,28 +8,37 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use borrow_check::borrow_set::BorrowSet;
+use borrow_check::location::LocationTable;
+use borrow_check::nll::facts::AllFacts;
 use rustc::hir;
-use rustc::mir::{BasicBlock, BasicBlockData, Location, Place, Mir, Rvalue};
+use rustc::infer::InferCtxt;
+use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
 use rustc::mir::Place::Projection;
-use rustc::mir::{Local, PlaceProjection, ProjectionElem};
-use rustc::mir::visit::TyContext;
-use rustc::infer::InferCtxt;
-use rustc::ty::{self, CanonicalTy, ClosureSubsts};
-use rustc::ty::subst::Substs;
+use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
+use rustc::mir::{Local, PlaceProjection, ProjectionElem, Statement, Terminator};
 use rustc::ty::fold::TypeFoldable;
+use rustc::ty::subst::Substs;
+use rustc::ty::{self, CanonicalTy, ClosureSubsts};
 
+use super::region_infer::{Cause, RegionInferenceContext};
 use super::ToRegionVid;
-use super::region_infer::{RegionInferenceContext, Cause};
 
 pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
     regioncx: &mut RegionInferenceContext<'tcx>,
+    all_facts: &mut Option<AllFacts>,
+    location_table: &LocationTable,
     mir: &Mir<'tcx>,
+    borrow_set: &BorrowSet<'tcx>,
 ) {
     let mut cg = ConstraintGeneration {
+        borrow_set,
         infcx,
         regioncx,
+        location_table,
+        all_facts,
         mir,
     };
 
@@ -41,8 +50,11 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
 /// 'cg = the duration of the constraint generation process itself.
 struct ConstraintGeneration<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> {
     infcx: &'cg InferCtxt<'cx, 'gcx, 'tcx>,
+    all_facts: &'cg mut Option<AllFacts>,
+    location_table: &'cg LocationTable,
     regioncx: &'cg mut RegionInferenceContext<'tcx>,
     mir: &'cg Mir<'tcx>,
+    borrow_set: &'cg BorrowSet<'tcx>,
 }
 
 impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx, 'tcx> {
@@ -68,12 +80,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
     /// call. Make them live at the location where they appear.
     fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
         match ty_context {
-            TyContext::ReturnTy(source_info) |
-            TyContext::YieldTy(source_info) |
-            TyContext::LocalDecl { source_info, .. } => {
-                span_bug!(source_info.span,
-                          "should not be visiting outside of the CFG: {:?}",
-                          ty_context);
+            TyContext::ReturnTy(source_info)
+            | TyContext::YieldTy(source_info)
+            | TyContext::LocalDecl { source_info, .. } => {
+                span_bug!(
+                    source_info.span,
+                    "should not be visiting outside of the CFG: {:?}",
+                    ty_context
+                );
             }
             TyContext::Location(location) => {
                 self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location));
@@ -90,25 +104,117 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         self.super_closure_substs(substs);
     }
 
+    fn visit_statement(
+        &mut self,
+        block: BasicBlock,
+        statement: &Statement<'tcx>,
+        location: Location,
+    ) {
+        if let Some(all_facts) = self.all_facts {
+            all_facts.cfg_edge.push((
+                self.location_table.start_index(location),
+                self.location_table.mid_index(location),
+            ));
+
+            all_facts.cfg_edge.push((
+                self.location_table.mid_index(location),
+                self.location_table
+                    .start_index(location.successor_within_block()),
+            ));
+        }
+
+        self.super_statement(block, statement, location);
+    }
+
+    fn visit_assign(
+        &mut self,
+        block: BasicBlock,
+        place: &Place<'tcx>,
+        rvalue: &Rvalue<'tcx>,
+        location: Location,
+    ) {
+        // When we see `X = ...`, then kill borrows of
+        // `(*X).foo` and so forth.
+        if let Some(all_facts) = self.all_facts {
+            if let Place::Local(temp) = place {
+                if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
+                    for &borrow_index in borrow_indices {
+                        let location_index = self.location_table.mid_index(location);
+                        all_facts.killed.push((borrow_index, location_index));
+                    }
+                }
+            }
+        }
+
+        self.super_assign(block, place, rvalue, location);
+    }
+
+    fn visit_terminator(
+        &mut self,
+        block: BasicBlock,
+        terminator: &Terminator<'tcx>,
+        location: Location,
+    ) {
+        if let Some(all_facts) = self.all_facts {
+            all_facts.cfg_edge.push((
+                self.location_table.start_index(location),
+                self.location_table.mid_index(location),
+            ));
+
+            for successor_block in terminator.successors() {
+                all_facts.cfg_edge.push((
+                    self.location_table.mid_index(location),
+                    self.location_table
+                        .start_index(successor_block.start_location()),
+                ));
+            }
+        }
+
+        self.super_terminator(block, terminator, location);
+    }
+
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         debug!("visit_rvalue(rvalue={:?}, location={:?})", rvalue, location);
 
-        // Look for an rvalue like:
-        //
-        //     & L
-        //
-        // where L is the path that is borrowed. In that case, we have
-        // to add the reborrow constraints (which don't fall out
-        // naturally from the type-checker).
-        if let Rvalue::Ref(region, _bk, ref borrowed_lv) = *rvalue {
-            self.add_reborrow_constraint(location, region, borrowed_lv);
+        match rvalue {
+            Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
+                // In some cases, e.g. when borrowing from an unsafe
+                // place, we don't bother to create a loan, since
+                // there are no conditions to validate.
+                if let Some(all_facts) = self.all_facts {
+                    if let Some(borrow_index) = self.borrow_set.location_map.get(&location) {
+                        let region_vid = region.to_region_vid();
+                        all_facts.borrow_region.push((
+                            region_vid,
+                            *borrow_index,
+                            self.location_table.mid_index(location),
+                        ));
+                    }
+                }
+
+                // Look for an rvalue like:
+                //
+                //     & L
+                //
+                // where L is the path that is borrowed. In that case, we have
+                // to add the reborrow constraints (which don't fall out
+                // naturally from the type-checker).
+                self.add_reborrow_constraint(location, region, borrowed_place);
+            }
+
+            _ => { }
         }
 
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_user_assert_ty(&mut self, _c_ty: &CanonicalTy<'tcx>,
-                            _local: &Local, _location: Location) { }
+    fn visit_user_assert_ty(
+        &mut self,
+        _c_ty: &CanonicalTy<'tcx>,
+        _local: &Local,
+        _location: Location,
+    ) {
+    }
 }
 
 impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
@@ -122,8 +228,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
     {
         debug!(
             "add_regular_live_constraint(live_ty={:?}, location={:?})",
-            live_ty,
-            location
+            live_ty, location
         );
 
         self.infcx
@@ -144,8 +249,10 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
     ) {
         let mut borrowed_place = borrowed_place;
 
-        debug!("add_reborrow_constraint({:?}, {:?}, {:?})",
-               location, borrow_region, borrowed_place);
+        debug!(
+            "add_reborrow_constraint({:?}, {:?}, {:?})",
+            location, borrow_region, borrowed_place
+        );
         while let Projection(box PlaceProjection { base, elem }) = borrowed_place {
             debug!("add_reborrow_constraint - iteration {:?}", borrowed_place);
 
@@ -165,12 +272,20 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
                                 location.successor_within_block(),
                             );
 
+                            if let Some(all_facts) = self.all_facts {
+                                all_facts.outlives.push((
+                                    ref_region.to_region_vid(),
+                                    borrow_region.to_region_vid(),
+                                    self.location_table.mid_index(location),
+                                ));
+                            }
+
                             match mutbl {
                                 hir::Mutability::MutImmutable => {
                                     // Immutable reference. We don't need the base
                                     // to be valid for the entire lifetime of
                                     // the borrow.
-                                    break
+                                    break;
                                 }
                                 hir::Mutability::MutMutable => {
                                     // Mutable reference. We *do* need the base
@@ -199,19 +314,19 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
                         }
                         ty::TyRawPtr(..) => {
                             // deref of raw pointer, guaranteed to be valid
-                            break
+                            break;
                         }
                         ty::TyAdt(def, _) if def.is_box() => {
                             // deref of `Box`, need the base to be valid - propagate
                         }
-                        _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place)
+                        _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
                     }
                 }
-                ProjectionElem::Field(..) |
-                ProjectionElem::Downcast(..) |
-                ProjectionElem::Index(..) |
-                ProjectionElem::ConstantIndex { .. } |
-                ProjectionElem::Subslice { .. } => {
+                ProjectionElem::Field(..)
+                | ProjectionElem::Downcast(..)
+                | ProjectionElem::Index(..)
+                | ProjectionElem::ConstantIndex { .. }
+                | ProjectionElem::Subslice { .. } => {
                     // other field access
                 }
             }
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index d5e11a312ec..56e388a5b60 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -193,7 +193,6 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
                         block_data
                             .terminator()
                             .successors()
-                            .iter()
                             .map(|&basic_block| Location {
                                 statement_index: 0,
                                 block: basic_block,
diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs
new file mode 100644
index 00000000000..2802aa0dff4
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/facts.rs
@@ -0,0 +1,194 @@
+// 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 borrow_check::location::{LocationIndex, LocationTable};
+use dataflow::indexes::BorrowIndex;
+use rustc::ty::RegionVid;
+use std::error::Error;
+use std::fmt::Debug;
+use std::fs::{self, File};
+use std::io::Write;
+use std::path::Path;
+
+/// The "facts" which are the basis of the NLL borrow analysis.
+#[derive(Default)]
+crate struct AllFacts {
+    // `borrow_region(R, B, P)` -- the region R may refer to data from borrow B
+    // starting at the point P (this is usually the point *after* a borrow rvalue)
+    crate borrow_region: Vec<(RegionVid, BorrowIndex, LocationIndex)>,
+
+    // universal_region(R) -- this is a "free region" within fn body
+    crate universal_region: Vec<RegionVid>,
+
+    // `cfg_edge(P,Q)` for each edge P -> Q in the control flow
+    crate cfg_edge: Vec<(LocationIndex, LocationIndex)>,
+
+    // `killed(B,P)` when some prefix of the path borrowed at B is assigned at point P
+    crate killed: Vec<(BorrowIndex, LocationIndex)>,
+
+    // `outlives(R1, R2, P)` when we require `R1@P: R2@P`
+    crate outlives: Vec<(RegionVid, RegionVid, LocationIndex)>,
+
+    // `region_live_at(R, P)` when the region R appears in a live variable at P
+    crate region_live_at: Vec<(RegionVid, LocationIndex)>,
+}
+
+impl AllFacts {
+    crate fn write_to_dir(
+        &self,
+        dir: impl AsRef<Path>,
+        location_table: &LocationTable,
+    ) -> Result<(), Box<dyn Error>> {
+        let dir: &Path = dir.as_ref();
+        fs::create_dir_all(dir)?;
+        let wr = FactWriter { location_table, dir };
+        macro_rules! write_facts_to_path {
+            ($wr:ident . write_facts_to_path($this:ident . [
+                $($field:ident,)*
+            ])) => {
+                $(
+                    $wr.write_facts_to_path(
+                        &$this.$field,
+                        &format!("{}.facts", stringify!($field))
+                    )?;
+                )*
+            }
+        }
+        write_facts_to_path! {
+            wr.write_facts_to_path(self.[
+                borrow_region,
+                universal_region,
+                cfg_edge,
+                killed,
+                outlives,
+                region_live_at,
+            ])
+        }
+        Ok(())
+    }
+}
+
+struct FactWriter<'w> {
+    location_table: &'w LocationTable,
+    dir: &'w Path,
+}
+
+impl<'w> FactWriter<'w> {
+    fn write_facts_to_path<T>(
+        &self,
+        rows: &Vec<T>,
+        file_name: &str,
+    ) -> Result<(), Box<dyn Error>>
+    where
+        T: FactRow,
+    {
+        let file = &self.dir.join(file_name);
+        let mut file = File::create(file)?;
+        for row in rows {
+            row.write(&mut file, self.location_table)?;
+        }
+        Ok(())
+    }
+}
+
+trait FactRow {
+    fn write(
+        &self,
+        out: &mut File,
+        location_table: &LocationTable,
+    ) -> Result<(), Box<dyn Error>>;
+}
+
+impl FactRow for RegionVid {
+    fn write(
+        &self,
+        out: &mut File,
+        location_table: &LocationTable,
+    ) -> Result<(), Box<dyn Error>> {
+        write_row(out, location_table, &[self])
+    }
+}
+
+impl<A, B> FactRow for (A, B)
+where
+    A: FactCell,
+    B: FactCell,
+{
+    fn write(
+        &self,
+        out: &mut File,
+        location_table: &LocationTable,
+    ) -> Result<(), Box<dyn Error>> {
+        write_row(out, location_table, &[&self.0, &self.1])
+    }
+}
+
+impl<A, B, C> FactRow for (A, B, C)
+where
+    A: FactCell,
+    B: FactCell,
+    C: FactCell,
+{
+    fn write(
+        &self,
+        out: &mut File,
+        location_table: &LocationTable,
+    ) -> Result<(), Box<dyn Error>> {
+        write_row(out, location_table, &[&self.0, &self.1, &self.2])
+    }
+}
+
+impl<A, B, C, D> FactRow for (A, B, C, D)
+where
+    A: FactCell,
+    B: FactCell,
+    C: FactCell,
+    D: FactCell,
+{
+    fn write(
+        &self,
+        out: &mut File,
+        location_table: &LocationTable,
+    ) -> Result<(), Box<dyn Error>> {
+        write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3])
+    }
+}
+
+fn write_row(
+    out: &mut dyn Write,
+    location_table: &LocationTable,
+    columns: &[&dyn FactCell],
+) -> Result<(), Box<dyn Error>> {
+    for (index, c) in columns.iter().enumerate() {
+        let tail = if index == columns.len() - 1 {
+            "\n"
+        } else {
+            "\t"
+        };
+        write!(out, "{:?}{}", c.to_string(location_table), tail)?;
+    }
+    Ok(())
+}
+
+trait FactCell {
+    fn to_string(&self, location_table: &LocationTable) -> String;
+}
+
+impl<A: Debug> FactCell for A {
+    default fn to_string(&self, _location_table: &LocationTable) -> String {
+        format!("{:?}", self)
+    }
+}
+
+impl FactCell for LocationIndex {
+    fn to_string(&self, location_table: &LocationTable) -> String {
+        format!("{:?}", location_table.to_location(*self))
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 3ca1bd23e86..0b1729294d8 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -9,36 +9,39 @@
 // except according to those terms.
 
 use borrow_check::borrow_set::BorrowSet;
+use borrow_check::location::LocationTable;
+use dataflow::move_paths::MoveData;
+use dataflow::FlowAtLocation;
+use dataflow::MaybeInitializedPlaces;
 use rustc::hir::def_id::DefId;
-use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir};
 use rustc::infer::InferCtxt;
+use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc::util::nodemap::FxHashMap;
 use std::collections::BTreeSet;
 use std::fmt::Debug;
 use std::io;
+use std::path::PathBuf;
 use transform::MirSource;
 use util::liveness::{LivenessResults, LocalSet};
-use dataflow::FlowAtLocation;
-use dataflow::MaybeInitializedPlaces;
-use dataflow::move_paths::MoveData;
 
+use self::mir_util::PassWhere;
 use util as mir_util;
 use util::pretty::{self, ALIGN};
-use self::mir_util::PassWhere;
 
 mod constraint_generation;
 pub mod explain_borrow;
-pub(crate) mod region_infer;
+mod facts;
+crate mod region_infer;
 mod renumber;
 mod subtype_constraint_generation;
-pub(crate) mod type_check;
+crate mod type_check;
 mod universal_regions;
 
+use self::facts::AllFacts;
 use self::region_infer::RegionInferenceContext;
 use self::universal_regions::UniversalRegions;
 
-
 /// Rewrites the regions in the MIR to use NLL variables, also
 /// scraping out the set of universal regions (e.g., region parameters)
 /// declared on the function. That set will need to be given to
@@ -71,10 +74,11 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     def_id: DefId,
     universal_regions: UniversalRegions<'tcx>,
     mir: &Mir<'tcx>,
+    location_table: &LocationTable,
     param_env: ty::ParamEnv<'gcx>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
-    _borrow_set: &BorrowSet<'tcx>,
+    borrow_set: &BorrowSet<'tcx>,
 ) -> (
     RegionInferenceContext<'tcx>,
     Option<ClosureRegionRequirements<'gcx>>,
@@ -92,15 +96,47 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         move_data,
     );
 
+    let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts {
+        Some(AllFacts::default())
+    } else {
+        None
+    };
+
+    if let Some(all_facts) = &mut all_facts {
+        all_facts
+            .universal_region
+            .extend(universal_regions.universal_regions());
+    }
+
     // Create the region inference context, taking ownership of the region inference
     // data that was contained in `infcx`.
     let var_origins = infcx.take_region_var_origins();
-    let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir);
-    subtype_constraint_generation::generate(&mut regioncx, mir, constraint_sets);
-
+    let mut regioncx =
+        RegionInferenceContext::new(var_origins, universal_regions, mir);
+
+    // Generate various constraints.
+    subtype_constraint_generation::generate(
+        &mut regioncx,
+        &mut all_facts,
+        location_table,
+        mir,
+        constraint_sets,
+    );
+    constraint_generation::generate_constraints(
+        infcx,
+        &mut regioncx,
+        &mut all_facts,
+        location_table,
+        &mir,
+        borrow_set,
+    );
 
-    // Generate non-subtyping constraints.
-    constraint_generation::generate_constraints(infcx, &mut regioncx, &mir);
+    // Dump facts if requested.
+    if let Some(all_facts) = all_facts {
+        let def_path = infcx.tcx.hir.def_path(def_id);
+        let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate());
+        all_facts.write_to_dir(dir_path, location_table).unwrap();
+    }
 
     // Solve the region constraints.
     let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs b/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs
index 4fcd3118f91..f68394d6149 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs
@@ -95,7 +95,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     block_data
                         .terminator()
                         .successors()
-                        .iter()
                         .map(|&basic_block| Location {
                             statement_index: 0,
                             block: basic_block,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 08391401cc6..4d1f3e2b430 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -16,7 +16,7 @@ use rustc::infer::RegionObligation;
 use rustc::infer::RegionVariableOrigin;
 use rustc::infer::SubregionOrigin;
 use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
-use rustc::infer::region_constraints::{GenericKind, VarOrigins};
+use rustc::infer::region_constraints::{GenericKind, VarInfos};
 use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
                  Local, Location, Mir};
 use rustc::traits::ObligationCause;
@@ -256,19 +256,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// of those will be constant regions representing the free
     /// regions defined in `universal_regions`.
     pub(crate) fn new(
-        var_origins: VarOrigins,
+        var_infos: VarInfos,
         universal_regions: UniversalRegions<'tcx>,
         mir: &Mir<'tcx>,
     ) -> Self {
-        let num_region_variables = var_origins.len();
+        let num_region_variables = var_infos.len();
         let num_universal_regions = universal_regions.len();
 
         let elements = &Rc::new(RegionValueElements::new(mir, num_universal_regions));
 
         // Create a RegionDefinition for each inference variable.
-        let definitions = var_origins
+        let definitions = var_infos
             .into_iter()
-            .map(|origin| RegionDefinition::new(origin))
+            .map(|info| RegionDefinition::new(info.origin))
             .collect();
 
         let mut result = Self {
diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
index 32728145b29..9db19085a39 100644
--- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::mir::Mir;
+use borrow_check::location::LocationTable;
+use borrow_check::nll::facts::AllFacts;
 use rustc::infer::region_constraints::Constraint;
 use rustc::infer::region_constraints::RegionConstraintData;
 use rustc::infer::region_constraints::{Verify, VerifyBound};
+use rustc::mir::{Location, Mir};
 use rustc::ty;
+use std::iter;
 use syntax::codemap::Span;
 
-use super::region_infer::{TypeTest, RegionInferenceContext, RegionTest};
+use super::region_infer::{RegionInferenceContext, RegionTest, TypeTest};
 use super::type_check::Locations;
 use super::type_check::MirTypeckRegionConstraints;
 use super::type_check::OutlivesSet;
@@ -27,19 +30,30 @@ use super::type_check::OutlivesSet;
 /// them into the NLL `RegionInferenceContext`.
 pub(super) fn generate<'tcx>(
     regioncx: &mut RegionInferenceContext<'tcx>,
+    all_facts: &mut Option<AllFacts>,
+    location_table: &LocationTable,
     mir: &Mir<'tcx>,
     constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
-    SubtypeConstraintGenerator { regioncx, mir }.generate(constraints);
+    SubtypeConstraintGenerator {
+        regioncx,
+        location_table,
+        mir,
+    }.generate(constraints, all_facts);
 }
 
 struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> {
     regioncx: &'cx mut RegionInferenceContext<'tcx>,
+    location_table: &'cx LocationTable,
     mir: &'cx Mir<'tcx>,
 }
 
 impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
-    fn generate(&mut self, constraints: &MirTypeckRegionConstraints<'tcx>) {
+    fn generate(
+        &mut self,
+        constraints: &MirTypeckRegionConstraints<'tcx>,
+        all_facts: &mut Option<AllFacts>,
+    ) {
         let MirTypeckRegionConstraints {
             liveness_set,
             outlives_sets,
@@ -57,6 +71,17 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
             self.regioncx.add_live_point(region_vid, *location, &cause);
         }
 
+        if let Some(all_facts) = all_facts {
+            all_facts
+                .region_live_at
+                .extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
+                    let r = self.to_region_vid(region);
+                    let p1 = self.location_table.start_index(*location);
+                    let p2 = self.location_table.mid_index(*location);
+                    iter::once((r, p1)).chain(iter::once((r, p2)))
+                }));
+        }
+
         for OutlivesSet { locations, data } in outlives_sets {
             debug!("generate: constraints at: {:#?}", locations);
             let RegionConstraintData {
@@ -65,7 +90,11 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
                 givens,
             } = data;
 
-            let span = self.mir.source_info(locations.from_location).span;
+            let span = self.mir
+                .source_info(locations.from_location().unwrap_or(Location::START))
+                .span;
+
+            let at_location = locations.at_location().unwrap_or(Location::START);
 
             for constraint in constraints.keys() {
                 debug!("generate: constraint: {:?}", constraint);
@@ -83,8 +112,24 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
                 // reverse direction, because `regioncx` talks about
                 // "outlives" (`>=`) whereas the region constraints
                 // talk about `<=`.
-                self.regioncx
-                    .add_outlives(span, b_vid, a_vid, locations.at_location);
+                self.regioncx.add_outlives(span, b_vid, a_vid, at_location);
+
+                // In the new analysis, all outlives relations etc
+                // "take effect" at the mid point of the statement
+                // that requires them, so ignore the `at_location`.
+                if let Some(all_facts) = all_facts {
+                    if let Some(from_location) = locations.from_location() {
+                        all_facts.outlives.push((
+                            b_vid,
+                            a_vid,
+                            self.location_table.mid_index(from_location),
+                        ));
+                    } else {
+                        for location in self.location_table.all_points() {
+                            all_facts.outlives.push((b_vid, a_vid, location));
+                        }
+                    }
+                }
             }
 
             for verify in verifys {
@@ -109,7 +154,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
 
         let lower_bound = self.to_region_vid(verify.region);
 
-        let point = locations.at_location;
+        let point = locations.at_location().unwrap_or(Location::START);
 
         let test = self.verify_bound_to_region_test(&verify.bound);
 
@@ -149,14 +194,6 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
     }
 
     fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
-        // Every region that we see in the constraints came from the
-        // MIR or from the parameter environment. If the former, it
-        // will be a region variable.  If the latter, it will be in
-        // the set of universal regions *somewhere*.
-        if let ty::ReVar(vid) = r {
-            *vid
-        } else {
-            self.regioncx.to_region_vid(r)
-        }
+        self.regioncx.to_region_vid(r)
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index b1aeae0b76b..2b1878c33e9 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -29,7 +29,7 @@ use rustc::traits::PredicateObligations;
 
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::{AtLocation, TypeChecker};
+use super::{Locations, TypeChecker};
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     pub(super) fn equate_inputs_and_outputs(
@@ -47,26 +47,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         } = universal_regions;
         let infcx = self.infcx;
 
-        let start_position = Location {
-            block: START_BLOCK,
-            statement_index: 0,
-        };
-
         // Equate expected input tys with those in the MIR.
         let argument_locals = (1..).map(Local::new);
         for (&unnormalized_input_ty, local) in unnormalized_input_tys.iter().zip(argument_locals) {
-            let input_ty = self.normalize(&unnormalized_input_ty, start_position);
+            let input_ty = self.normalize(&unnormalized_input_ty, Locations::All);
             let mir_input_ty = mir.local_decls[local].ty;
-            self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
+            self.equate_normalized_input_or_output(input_ty, mir_input_ty);
         }
 
         assert!(
             mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
             mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
-            );
+        );
         if let Some(mir_yield_ty) = mir.yield_ty {
             let ur_yield_ty = universal_regions.yield_ty.unwrap();
-            self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty);
+            self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty);
         }
 
         // Return types are a bit more complex. They may contain existential `impl Trait`
@@ -75,13 +70,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             "equate_inputs_and_outputs: unnormalized_output_ty={:?}",
             unnormalized_output_ty
         );
-        let output_ty = self.normalize(&unnormalized_output_ty, start_position);
+        let output_ty = self.normalize(&unnormalized_output_ty, Locations::All);
         debug!(
             "equate_inputs_and_outputs: normalized output_ty={:?}",
             output_ty
         );
         let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
-        let anon_type_map = self.fully_perform_op(start_position.at_self(), |cx| {
+        let anon_type_map = self.fully_perform_op(Locations::All, |cx| {
             let mut obligations = ObligationAccumulator::default();
 
             let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types(
@@ -112,7 +107,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs);
                 let anon_defn_ty = renumber::renumber_regions(
                     cx.infcx,
-                    TyContext::Location(start_position),
+                    TyContext::Location(Location::START),
                     &anon_defn_ty,
                 );
                 debug!(
@@ -134,7 +129,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }).unwrap_or_else(|terr| {
                 span_mirbug!(
                     self,
-                    start_position,
+                    Location::START,
                     "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
                     output_ty,
                     mir_output_ty,
@@ -148,7 +143,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         // prove that `T: Iterator` where `T` is the type we
         // instantiated it with).
         if let Some(anon_type_map) = anon_type_map {
-            self.fully_perform_op(start_position.at_self(), |_cx| {
+            self.fully_perform_op(Locations::All, |_cx| {
                 infcx.constrain_anon_types(&anon_type_map, universal_regions);
                 Ok(InferOk {
                     value: (),
@@ -158,13 +153,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn equate_normalized_input_or_output(&mut self, location: Location, a: Ty<'tcx>, b: Ty<'tcx>) {
+    fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
         debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
 
-        if let Err(terr) = self.eq_types(a, b, location.at_self()) {
+        if let Err(terr) = self.eq_types(a, b, Locations::All) {
             span_mirbug!(
                 self,
-                location,
+                Location::START,
                 "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
                 a,
                 b,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index ec7ee466008..42a1745addf 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -22,6 +22,7 @@ use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
 use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::*;
 use rustc::traits::query::NoSolution;
 use rustc::traits::{self, Normalized, TraitEngine};
@@ -617,17 +618,72 @@ pub struct OutlivesSet<'tcx> {
     pub data: RegionConstraintData<'tcx>,
 }
 
+/// The `Locations` type summarizes *where* region constraints are
+/// required to hold. Normally, this is at a particular point which
+/// created the obligation, but for constraints that the user gave, we
+/// want the constraint to hold at all points.
 #[derive(Copy, Clone, Debug)]
-pub struct Locations {
-    /// The location in the MIR that generated these constraints.
-    /// This is intended for error reporting and diagnosis; the
-    /// constraints may *take effect* at a distinct spot.
-    pub from_location: Location,
-
-    /// The constraints must be met at this location. In terms of the
-    /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field
-    /// is the `P` value.
-    pub at_location: Location,
+pub enum Locations {
+    /// Indicates that a type constraint should always be true. This
+    /// is particularly important in the new borrowck analysis for
+    /// things like the type of the return slot. Consider this
+    /// example:
+    ///
+    /// ```
+    /// fn foo<'a>(x: &'a u32) -> &'a u32 {
+    ///     let y = 22;
+    ///     return &y; // error
+    /// }
+    /// ```
+    ///
+    /// Here, we wind up with the signature from the return type being
+    /// something like `&'1 u32` where `'1` is a universal region. But
+    /// the type of the return slot `_0` is something like `&'2 u32`
+    /// where `'2` is an existential region variable. The type checker
+    /// requires that `&'2 u32 = &'1 u32` -- but at what point? In the
+    /// older NLL analysis, we required this only at the entry point
+    /// to the function. By the nature of the constraints, this wound
+    /// up propagating to all points reachable from start (because
+    /// `'1` -- as a universal region -- is live everywhere).  In the
+    /// newer analysis, though, this doesn't work: `_0` is considered
+    /// dead at the start (it has no usable value) and hence this type
+    /// equality is basically a no-op. Then, later on, when we do `_0
+    /// = &'3 y`, that region `'3` never winds up related to the
+    /// universal region `'1` and hence no error occurs. Therefore, we
+    /// use Locations::All instead, which ensures that the `'1` and
+    /// `'2` are equal everything. We also use this for other
+    /// user-given type annotations; e.g., if the user wrote `let mut
+    /// x: &'static u32 = ...`, we would ensure that all values
+    /// assigned to `x` are of `'static` lifetime.
+    All,
+
+    Pair {
+        /// The location in the MIR that generated these constraints.
+        /// This is intended for error reporting and diagnosis; the
+        /// constraints may *take effect* at a distinct spot.
+        from_location: Location,
+
+        /// The constraints must be met at this location. In terms of the
+        /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field
+        /// is the `P` value.
+        at_location: Location,
+    }
+}
+
+impl Locations {
+    pub fn from_location(&self) -> Option<Location> {
+        match self {
+            Locations::All => None,
+            Locations::Pair { from_location, .. } => Some(*from_location),
+        }
+    }
+
+    pub fn at_location(&self) -> Option<Location> {
+        match self {
+            Locations::All => None,
+            Locations::Pair { at_location, .. } => Some(*at_location),
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
@@ -769,7 +825,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     "check_stmt: user_assert_ty ty={:?} local_ty={:?}",
                     ty, local_ty
                 );
-                if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) {
+                if let Err(terr) = self.eq_types(ty, local_ty, Locations::All) {
                     span_mirbug!(
                         self,
                         stmt,
@@ -819,7 +875,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let place_ty = location.ty(mir, tcx).to_ty(tcx);
                 let rv_ty = value.ty(mir, tcx);
 
-                let locations = Locations {
+                let locations = Locations::Pair {
                     from_location: term_location,
                     at_location: target.start_location(),
                 };
@@ -838,7 +894,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 // *both* blocks, so we need to ensure that it holds
                 // at both locations.
                 if let Some(unwind) = unwind {
-                    let locations = Locations {
+                    let locations = Locations::Pair {
                         from_location: term_location,
                         at_location: unwind.start_location(),
                     };
@@ -918,11 +974,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     ));
                 }
 
-                if self.is_box_free(func) {
-                    self.check_box_free_inputs(mir, term, &sig, args, term_location);
-                } else {
-                    self.check_call_inputs(mir, term, &sig, args, term_location);
-                }
+                self.check_call_inputs(mir, term, &sig, args, term_location);
             }
             TerminatorKind::Assert {
                 ref cond, ref msg, ..
@@ -932,7 +984,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
+                if let BoundsCheck { ref len, ref index } = *msg {
                     if len.ty(mir, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
@@ -974,7 +1026,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         match *destination {
             Some((ref dest, target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
-                let locations = Locations {
+                let locations = Locations::Pair {
                     from_location: term_location,
                     at_location: target_block.start_location(),
                 };
@@ -1026,70 +1078,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
-        match *operand {
-            Operand::Constant(ref c) => match c.ty.sty {
-                ty::TyFnDef(ty_def_id, _) => {
-                    Some(ty_def_id) == self.tcx().lang_items().box_free_fn()
-                }
-                _ => false,
-            },
-            _ => false,
-        }
-    }
-
-    fn check_box_free_inputs(
-        &mut self,
-        mir: &Mir<'tcx>,
-        term: &Terminator<'tcx>,
-        sig: &ty::FnSig<'tcx>,
-        args: &[Operand<'tcx>],
-        term_location: Location,
-    ) {
-        debug!("check_box_free_inputs");
-
-        // box_free takes a Box as a pointer. Allow for that.
-
-        if sig.inputs().len() != 1 {
-            span_mirbug!(self, term, "box_free should take 1 argument");
-            return;
-        }
-
-        let pointee_ty = match sig.inputs()[0].sty {
-            ty::TyRawPtr(mt) => mt.ty,
-            _ => {
-                span_mirbug!(self, term, "box_free should take a raw ptr");
-                return;
-            }
-        };
-
-        if args.len() != 1 {
-            span_mirbug!(self, term, "box_free called with wrong # of args");
-            return;
-        }
-
-        let ty = args[0].ty(mir, self.tcx());
-        let arg_ty = match ty.sty {
-            ty::TyRawPtr(mt) => mt.ty,
-            ty::TyAdt(def, _) if def.is_box() => ty.boxed_ty(),
-            _ => {
-                span_mirbug!(self, term, "box_free called with bad arg ty");
-                return;
-            }
-        };
-
-        if let Err(terr) = self.sub_types(arg_ty, pointee_ty, term_location.at_self()) {
-            span_mirbug!(
-                self,
-                term,
-                "bad box_free arg ({:?} <- {:?}): {:?}",
-                pointee_ty,
-                arg_ty,
-                terr
-            );
-        }
-    }
-
     fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) {
         let is_cleanup = block_data.is_cleanup;
         self.last_span = block_data.terminator().source_info.span;
@@ -1442,7 +1430,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             };
             let operand_ty = operand.ty(mir, tcx);
             if let Err(terr) =
-                self.sub_types(operand_ty, field_ty, location.at_successor_within_block())
+                self.sub_types(operand_ty, field_ty, location.at_self())
             {
                 span_mirbug!(
                     self,
@@ -1494,7 +1482,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             // these extra requirements are basically like where
             // clauses on the struct.
             AggregateKind::Closure(def_id, substs) => {
-                if let Some(closure_region_requirements) = tcx.mir_borrowck(*def_id) {
+                if let Some(closure_region_requirements) =
+                    tcx.mir_borrowck(*def_id).closure_requirements
+                {
                     closure_region_requirements.apply_requirements(
                         self.infcx,
                         self.body_id,
@@ -1579,12 +1569,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn normalize<T>(&mut self, value: &T, location: Location) -> T
+    fn normalize<T>(&mut self, value: &T, location: impl ToLocations) -> T
     where
         T: fmt::Debug + TypeFoldable<'tcx>,
     {
         debug!("normalize(value={:?}, location={:?})", value, location);
-        self.fully_perform_op(location.at_self(), |this| {
+        self.fully_perform_op(location.to_locations(), |this| {
             let Normalized { value, obligations } = this.infcx
                 .at(&this.misc(this.last_span), this.param_env)
                 .normalize(value)
@@ -1650,16 +1640,32 @@ trait AtLocation {
 
 impl AtLocation for Location {
     fn at_self(self) -> Locations {
-        Locations {
+        Locations::Pair {
             from_location: self,
             at_location: self,
         }
     }
 
     fn at_successor_within_block(self) -> Locations {
-        Locations {
+        Locations::Pair {
             from_location: self,
             at_location: self.successor_within_block(),
         }
     }
 }
+
+trait ToLocations: fmt::Debug + Copy {
+    fn to_locations(self) -> Locations;
+}
+
+impl ToLocations for Locations {
+    fn to_locations(self) -> Locations {
+        self
+    }
+}
+
+impl ToLocations for Location {
+    fn to_locations(self) -> Locations {
+        self.at_self()
+    }
+}
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index 94702927d26..fae06db3162 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 use build::{BlockAnd, BlockAndExtension, Builder};
+use build::ForGuard::OutsideGuard;
+use build::matches::ArmHasGuard;
 use hair::*;
 use rustc::mir::*;
 use rustc::hir;
@@ -113,7 +115,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     // Declare the bindings, which may create a visibility scope.
                     let remainder_span = remainder_scope.span(this.hir.tcx(),
                                                               &this.hir.region_scope_tree);
-                    let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern);
+                    let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern,
+                                                      ArmHasGuard(false));
 
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
@@ -135,8 +138,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         }
 
                         this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
-                            this.storage_live_binding(block, node, span);
-                            this.schedule_drop_for_binding(node, span);
+                            this.storage_live_binding(block, node, span, OutsideGuard);
+                            this.schedule_drop_for_binding(node, span, OutsideGuard);
                         })
                     }
 
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index 9e217908511..365b9babd08 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -11,9 +11,11 @@
 //! See docs in build/expr/mod.rs
 
 use build::{BlockAnd, BlockAndExtension, Builder};
+use build::ForGuard::{OutsideGuard, WithinGuard};
 use build::expr::category::Category;
 use hair::*;
 use rustc::mir::*;
+use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -73,7 +75,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                                            Operand::Copy(Place::Local(idx)),
                                                            Operand::Copy(len.clone())));
 
-                let msg = AssertMessage::BoundsCheck {
+                let msg = BoundsCheck {
                     len: Operand::Move(len),
                     index: Operand::Copy(Place::Local(idx))
                 };
@@ -85,8 +87,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 block.and(Place::Local(Local::new(1)))
             }
             ExprKind::VarRef { id } => {
-                let index = this.var_indices[&id];
-                block.and(Place::Local(index))
+                let place = if this.is_bound_var_in_guard(id) {
+                    let index = this.var_local_id(id, WithinGuard);
+                    if this.hir.tcx().all_pat_vars_are_implicit_refs_within_guards() {
+                        Place::Local(index).deref()
+                    } else {
+                        Place::Local(index)
+                    }
+                } else {
+                    let index = this.var_local_id(id, OutsideGuard);
+                    Place::Local(index)
+                };
+                block.and(place)
             }
             ExprKind::StaticRef { id } => {
                 block.and(Place::Static(Box::new(Static { def_id: id, ty: expr.ty })))
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index b7f402f61a9..9e96fdf8214 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -10,7 +10,6 @@
 
 //! See docs in build/expr/mod.rs
 
-use rustc_const_math::{ConstMathErr, Op};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -21,7 +20,7 @@ use rustc::middle::const_val::ConstVal;
 use rustc::middle::region;
 use rustc::ty::{self, Ty};
 use rustc::mir::*;
-use rustc::mir::interpret::{Value, PrimVal};
+use rustc::mir::interpret::{Value, PrimVal, EvalErrorKind};
 use syntax_pos::Span;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
@@ -86,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     this.cfg.push_assign(block, source_info, &is_min,
                                          Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval));
 
-                    let err = ConstMathErr::Overflow(Op::Neg);
                     block = this.assert(block, Operand::Move(is_min), false,
-                                        AssertMessage::Math(err), expr_span);
+                                        EvalErrorKind::OverflowNeg, expr_span);
                 }
                 block.and(Rvalue::UnaryOp(op, arg))
             }
@@ -311,19 +309,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let val = result_value.clone().field(val_fld, ty);
             let of = result_value.field(of_fld, bool_ty);
 
-            let err = ConstMathErr::Overflow(match op {
-                BinOp::Add => Op::Add,
-                BinOp::Sub => Op::Sub,
-                BinOp::Mul => Op::Mul,
-                BinOp::Shl => Op::Shl,
-                BinOp::Shr => Op::Shr,
-                _ => {
-                    bug!("MIR build_binary_op: {:?} is not checkable", op)
-                }
-            });
+            let err = EvalErrorKind::Overflow(op);
 
             block = self.assert(block, Operand::Move(of), false,
-                                AssertMessage::Math(err), span);
+                                err, span);
 
             block.and(Rvalue::Use(Operand::Move(val)))
         } else {
@@ -332,11 +321,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // and 2. there are two possible failure cases, divide-by-zero and overflow.
 
                 let (zero_err, overflow_err) = if op == BinOp::Div {
-                    (ConstMathErr::DivisionByZero,
-                     ConstMathErr::Overflow(Op::Div))
+                    (EvalErrorKind::DivisionByZero,
+                     EvalErrorKind::Overflow(op))
                 } else {
-                    (ConstMathErr::RemainderByZero,
-                     ConstMathErr::Overflow(Op::Rem))
+                    (EvalErrorKind::RemainderByZero,
+                     EvalErrorKind::Overflow(op))
                 };
 
                 // Check for / 0
@@ -346,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                      Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero));
 
                 block = self.assert(block, Operand::Move(is_zero), false,
-                                    AssertMessage::Math(zero_err), span);
+                                    zero_err, span);
 
                 // We only need to check for the overflow in one case:
                 // MIN / -1, and only for signed values.
@@ -371,7 +360,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                          Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min));
 
                     block = self.assert(block, Operand::Move(of), false,
-                                        AssertMessage::Math(overflow_err), span);
+                                        overflow_err, span);
                 }
             }
 
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index c130b4f550f..562f890b4c0 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -220,7 +220,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         let f = ty.fn_sig(this.hir.tcx());
                         if f.abi() == Abi::RustIntrinsic ||
                            f.abi() == Abi::PlatformIntrinsic {
-                            Some(this.hir.tcx().item_name(def_id))
+                            Some(this.hir.tcx().item_name(def_id).as_str())
                         } else {
                             None
                         }
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 7eb52a3cdee..6946ac4c7b2 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -14,6 +14,8 @@
 //! details.
 
 use build::{BlockAnd, BlockAndExtension, Builder};
+use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
+use build::ForGuard::{self, OutsideGuard, WithinGuard};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::bitvec::BitVector;
 use rustc::ty::{self, Ty};
@@ -28,6 +30,11 @@ mod simplify;
 mod test;
 mod util;
 
+/// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
+/// a match arm has a guard expression attached to it.
+#[derive(Copy, Clone, Debug)]
+pub(crate) struct ArmHasGuard(pub bool);
+
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn match_expr(&mut self,
                       destination: &Place<'tcx>,
@@ -66,7 +73,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let body = self.hir.mirror(arm.body.clone());
             let scope = self.declare_bindings(None, body.span,
                                               LintLevel::Inherited,
-                                              &arm.patterns[0]);
+                                              &arm.patterns[0],
+                                              ArmHasGuard(arm.guard.is_some()));
             (body, scope.unwrap_or(self.visibility_scope))
         }).collect();
 
@@ -149,7 +157,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                           var: NodeId, span: Span) {
         if self.hir.tcx().sess.opts.debugging_opts.disable_nll_user_type_assert { return; }
 
-        let local_id = self.var_indices[&var];
+        let local_id = self.var_local_id(var, OutsideGuard);
         let source_info = self.source_info(span);
 
         debug!("user_assert_ty: local_id={:?}", hir_id.local_id);
@@ -173,14 +181,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             PatternKind::Binding { mode: BindingMode::ByValue,
                                    var,
                                    subpattern: None, .. } => {
-                let place = self.storage_live_binding(block, var, irrefutable_pat.span);
+                let place = self.storage_live_binding(block, var, irrefutable_pat.span,
+                                                      OutsideGuard);
 
                 if let Some(ty) = ty {
                     self.user_assert_ty(block, ty, var, irrefutable_pat.span);
                 }
 
                 unpack!(block = self.into(&place, block, initializer));
-                self.schedule_drop_for_binding(var, irrefutable_pat.span);
+                self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
                 block.unit()
             }
             _ => {
@@ -220,7 +229,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         }
 
         // now apply the bindings, which will also declare the variables
-        self.bind_matched_candidate(block, candidate.bindings);
+        self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, false);
 
         block.unit()
     }
@@ -232,7 +241,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                             mut var_scope: Option<VisibilityScope>,
                             scope_span: Span,
                             lint_level: LintLevel,
-                            pattern: &Pattern<'tcx>)
+                            pattern: &Pattern<'tcx>,
+                            has_guard: ArmHasGuard)
                             -> Option<VisibilityScope> {
         assert!(!(var_scope.is_some() && lint_level.is_explicit()),
                 "can't have both a var and a lint scope at the same time");
@@ -254,15 +264,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 span,
                 scope: var_scope.unwrap()
             };
-            this.declare_binding(source_info, syntactic_scope, mutability, name, var, ty);
+            this.declare_binding(source_info, syntactic_scope, mutability, name, var,
+                                 ty, has_guard);
         });
         var_scope
     }
 
-    pub fn storage_live_binding(&mut self, block: BasicBlock, var: NodeId, span: Span)
+    pub fn storage_live_binding(&mut self,
+                                block: BasicBlock,
+                                var: NodeId,
+                                span: Span,
+                                for_guard: ForGuard)
                             -> Place<'tcx>
     {
-        let local_id = self.var_indices[&var];
+        let local_id = self.var_local_id(var, for_guard);
         let source_info = self.source_info(span);
         self.cfg.push(block, Statement {
             source_info,
@@ -271,8 +286,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         Place::Local(local_id)
     }
 
-    pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) {
-        let local_id = self.var_indices[&var];
+    pub fn schedule_drop_for_binding(&mut self,
+                                     var: NodeId,
+                                     span: Span,
+                                     for_guard: ForGuard) {
+        let local_id = self.var_local_id(var, for_guard);
         let var_ty = self.local_decls[local_id].ty;
         let hir_id = self.hir.tcx().hir.node_to_hir_id(var);
         let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
@@ -770,14 +788,129 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                        vec![candidate.next_candidate_pre_binding_block],
                                });
 
-        self.bind_matched_candidate(block, candidate.bindings);
 
+        // rust-lang/rust#27282: The `autoref` business deserves some
+        // explanation here.
+        //
+        // The intent of the `autoref` flag is that when it is true,
+        // then any pattern bindings of type T will map to a `&T`
+        // within the context of the guard expression, but will
+        // continue to map to a `T` in the context of the arm body. To
+        // avoid surfacing this distinction in the user source code
+        // (which would be a severe change to the language and require
+        // far more revision to the compiler), when `autoref` is true,
+        // then any occurrence of the identifier in the guard
+        // expression will automatically get a deref op applied to it.
+        //
+        // So an input like:
+        //
+        // ```
+        // let place = Foo::new();
+        // match place { foo if inspect(foo)
+        //     => feed(foo), ...  }
+        // ```
+        //
+        // will be treated as if it were really something like:
+        //
+        // ```
+        // let place = Foo::new();
+        // match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) }
+        //     => { let tmp2 = place; feed(tmp2) }, ... }
+        //
+        // And an input like:
+        //
+        // ```
+        // let place = Foo::new();
+        // match place { ref mut foo if inspect(foo)
+        //     => feed(foo), ...  }
+        // ```
+        //
+        // will be treated as if it were really something like:
+        //
+        // ```
+        // let place = Foo::new();
+        // match place { Foo { .. } if { let tmp1 = & &mut place; inspect(*tmp1) }
+        //     => { let tmp2 = &mut place; feed(tmp2) }, ... }
+        // ```
+        //
+        // In short, any pattern binding will always look like *some*
+        // kind of `&T` within the guard at least in terms of how the
+        // MIR-borrowck views it, and this will ensure that guard
+        // expressions cannot mutate their the match inputs via such
+        // bindings. (It also ensures that guard expressions can at
+        // most *copy* values from such bindings; non-Copy things
+        // cannot be moved via pattern bindings in guard expressions.)
+        //
+        // ----
+        //
+        // Implementation notes (under assumption `autoref` is true).
+        //
+        // To encode the distinction above, we must inject the
+        // temporaries `tmp1` and `tmp2`.
+        //
+        // There are two cases of interest: binding by-value, and binding by-ref.
+        //
+        // 1. Binding by-value: Things are simple.
+        //
+        //    * Establishing `tmp1` creates a reference into the
+        //      matched place. This code is emitted by
+        //      bind_matched_candidate_for_guard.
+        //
+        //    * `tmp2` is only initialized "lazily", after we have
+        //      checked the guard. Thus, the code that can trigger
+        //      moves out of the candidate can only fire after the
+        //      guard evaluated to true. This initialization code is
+        //      emitted by bind_matched_candidate_for_arm.
+        //
+        // 2. Binding by-reference: Things are tricky.
+        //
+        //    * Here, the guard expression wants a `&&` or `&&mut`
+        //      into the original input. This means we need to borrow
+        //      a reference that we do not immediately have at hand
+        //      (because all we have is the places associated with the
+        //      match input itself; it is up to us to create a place
+        //      holding a `&` or `&mut` that we can then borrow).
+        //
+        //    * Therefore, when the binding is by-reference, we
+        //      *eagerly* introduce the binding for the arm body
+        //      (`tmp2`) and then borrow it (`tmp1`).
+        //
+        //    * This is documented with "NOTE tricky business" below.
+        //
+        // FIXME The distinction in how `tmp2` is initialized is
+        // currently encoded in a pretty awkward fashion; namely, by
+        // passing a boolean to bind_matched_candidate_for_arm_body
+        // indicating whether all of the by-ref bindings were already
+        // initialized.
+        //
+        // * Also: pnkfelix thinks "laziness" is natural; but since
+        //   MIR-borrowck did not complain with earlier (universally
+        //   eager) MIR codegen, laziness might not be *necessary*.
+
+        let autoref = self.hir.tcx().all_pat_vars_are_implicit_refs_within_guards();
         if let Some(guard) = candidate.guard {
+            if autoref {
+                self.bind_matched_candidate_for_guard(block, &candidate.bindings);
+                let guard_frame = GuardFrame {
+                    locals: candidate.bindings.iter()
+                        .map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode))
+                        .collect(),
+                };
+                debug!("Entering guard translation context: {:?}", guard_frame);
+                self.guard_context.push(guard_frame);
+            } else {
+                self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, false);
+            }
+
             // the block to branch to if the guard fails; if there is no
             // guard, this block is simply unreachable
             let guard = self.hir.mirror(guard);
             let source_info = self.source_info(guard.span);
             let cond = unpack!(block = self.as_local_operand(block, guard));
+            if autoref {
+                let guard_frame = self.guard_context.pop().unwrap();
+                debug!("Exiting guard translation context with locals: {:?}", guard_frame);
+            }
 
             let false_edge_block = self.cfg.start_new_block();
             self.cfg.terminate(block, source_info,
@@ -785,6 +918,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                    false_edge_block));
 
             let otherwise = self.cfg.start_new_block();
+            if autoref {
+                self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, true);
+            }
             self.cfg.terminate(false_edge_block, source_info,
                                TerminatorKind::FalseEdges {
                                    real_target: otherwise,
@@ -793,47 +929,137 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                });
             Some(otherwise)
         } else {
+            self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, false);
             self.cfg.terminate(block, candidate_source_info,
                                TerminatorKind::Goto { target: arm_block });
             None
         }
     }
 
-    fn bind_matched_candidate(&mut self,
-                              block: BasicBlock,
-                              bindings: Vec<Binding<'tcx>>) {
-        debug!("bind_matched_candidate(block={:?}, bindings={:?})",
+    fn bind_matched_candidate_for_guard(&mut self,
+                                        block: BasicBlock,
+                                        bindings: &[Binding<'tcx>]) {
+        debug!("bind_matched_candidate_for_guard(block={:?}, bindings={:?})",
                block, bindings);
 
+        // Assign each of the bindings. Since we are binding for a
+        // guard expression, this will never trigger moves out of the
+        // candidate.
+        let re_empty = self.hir.tcx().types.re_empty;
+        for binding in bindings {
+            let source_info = self.source_info(binding.span);
+            let local_for_guard = self.storage_live_binding(
+                block, binding.var_id, binding.span, WithinGuard);
+            // Question: Why schedule drops if bindings are all
+            // shared-&'s?  Answer: Because schedule_drop_for_binding
+            // also emits StorageDead's for those locals.
+            self.schedule_drop_for_binding(binding.var_id, binding.span, WithinGuard);
+            match binding.binding_mode {
+                BindingMode::ByValue => {
+                    let rvalue = Rvalue::Ref(re_empty, BorrowKind::Shared, binding.source.clone());
+                    self.cfg.push_assign(block, source_info, &local_for_guard, rvalue);
+                }
+                BindingMode::ByRef(region, borrow_kind) => {
+                    // NOTE tricky business: For `ref id` and `ref mut
+                    // id` patterns, we want `id` within the guard to
+                    // correspond to a temp of type `& &T` or `& &mut
+                    // T`, while within the arm body it will
+                    // correspond to a temp of type `&T` or `&mut T`,
+                    // as usual.
+                    //
+                    // But to inject the level of indirection, we need
+                    // something to point to.
+                    //
+                    // So:
+                    //
+                    // 1. First set up the local for the arm body
+                    //   (even though we have not yet evaluated the
+                    //   guard itself),
+                    //
+                    // 2. Then setup the local for the guard, which is
+                    //    just a reference to the local from step 1.
+                    //
+                    // Note that since we are setting up the local for
+                    // the arm body a bit eagerly here (and likewise
+                    // scheduling its drop code), we should *not* do
+                    // it redundantly later on.
+                    //
+                    // While we could have kept track of this with a
+                    // flag or collection of such bindings, the
+                    // treatment of all of these cases is uniform, so
+                    // we should be safe just avoiding the code
+                    // without maintaining such state.)
+                    let local_for_arm_body = self.storage_live_binding(
+                        block, binding.var_id, binding.span, OutsideGuard);
+                    self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
+
+                    // rust-lang/rust#27282: this potentially mutable
+                    // borrow may require a cast in the future to
+                    // avoid conflicting with an implicit borrow of
+                    // the whole match input; or maybe it just
+                    // requires an extension of our two-phase borrows
+                    // system. See discussion on rust-lang/rust#49870.
+                    let rvalue = Rvalue::Ref(region, borrow_kind, binding.source.clone());
+                    self.cfg.push_assign(block, source_info, &local_for_arm_body, rvalue);
+                    let rvalue = Rvalue::Ref(region, BorrowKind::Shared, local_for_arm_body);
+                    self.cfg.push_assign(block, source_info, &local_for_guard, rvalue);
+                }
+            }
+        }
+    }
+
+    fn bind_matched_candidate_for_arm_body(&mut self,
+                                           block: BasicBlock,
+                                           bindings: &[Binding<'tcx>],
+                                           already_initialized_state_for_refs: bool) {
+        debug!("bind_matched_candidate_for_arm_body(block={:?}, bindings={:?}, \
+                already_initialized_state_for_refs={:?})",
+               block, bindings, already_initialized_state_for_refs);
+
         // Assign each of the bindings. This may trigger moves out of the candidate.
         for binding in bindings {
+            if let BindingMode::ByRef(..) = binding.binding_mode {
+                // See "NOTE tricky business" above
+                if already_initialized_state_for_refs { continue; }
+            }
+
             let source_info = self.source_info(binding.span);
-            let local = self.storage_live_binding(block, binding.var_id, binding.span);
-            self.schedule_drop_for_binding(binding.var_id, binding.span);
+            let local = self.storage_live_binding(block, binding.var_id, binding.span,
+                                                  OutsideGuard);
+            self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
             let rvalue = match binding.binding_mode {
-                BindingMode::ByValue =>
-                    Rvalue::Use(self.consume_by_copy_or_move(binding.source)),
-                BindingMode::ByRef(region, borrow_kind) =>
-                    Rvalue::Ref(region, borrow_kind, binding.source),
+                BindingMode::ByValue => {
+                    Rvalue::Use(self.consume_by_copy_or_move(binding.source.clone()))
+                }
+                BindingMode::ByRef(region, borrow_kind) => {
+                    Rvalue::Ref(region, borrow_kind, binding.source.clone())
+                }
             };
             self.cfg.push_assign(block, source_info, &local, rvalue);
         }
     }
 
+    /// Each binding (`ref mut var`/`ref var`/`mut var`/`var`, where
+    /// the bound `var` has type `T` in the arm body) in a pattern
+    /// maps to *two* locals. The first local is a binding for
+    /// occurrences of `var` in the guard, which will all have type
+    /// `&T`. The second local is a binding for occurrences of `var`
+    /// in the arm body, which will have type `T`.
     fn declare_binding(&mut self,
                        source_info: SourceInfo,
                        syntactic_scope: VisibilityScope,
                        mutability: Mutability,
                        name: Name,
                        var_id: NodeId,
-                       var_ty: Ty<'tcx>)
-                       -> Local
+                       var_ty: Ty<'tcx>,
+                       has_guard: ArmHasGuard)
     {
         debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?}, \
                 syntactic_scope={:?})",
                var_id, name, var_ty, source_info, syntactic_scope);
 
-        let var = self.local_decls.push(LocalDecl::<'tcx> {
+        let tcx = self.hir.tcx();
+        let for_arm_body = self.local_decls.push(LocalDecl::<'tcx> {
             mutability,
             ty: var_ty.clone(),
             name: Some(name),
@@ -842,10 +1068,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             internal: false,
             is_user_variable: true,
         });
-        self.var_indices.insert(var_id, var);
-
-        debug!("declare_binding: var={:?}", var);
-
-        var
+        let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
+            let for_guard = self.local_decls.push(LocalDecl::<'tcx> {
+                mutability,
+                ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
+                name: Some(name),
+                source_info,
+                syntactic_scope,
+                internal: false,
+                is_user_variable: true,
+            });
+            LocalsForNode::Two { for_guard, for_arm_body }
+        } else {
+            LocalsForNode::One(for_arm_body)
+        };
+        debug!("declare_binding: vars={:?}", locals);
+        self.var_indices.insert(var_id, locals);
     }
 }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 0d836f5cb97..dd2a336af41 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -291,8 +291,14 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     visibility_scope_info: IndexVec<VisibilityScope, VisibilityScopeInfo>,
     visibility_scope: VisibilityScope,
 
+    /// the guard-context: each time we build the guard expression for
+    /// a match arm, we push onto this stack, and then pop when we
+    /// finish building it.
+    guard_context: Vec<GuardFrame>,
+
     /// Maps node ids of variable bindings to the `Local`s created for them.
-    var_indices: NodeMap<Local>,
+    /// (A match binding can have two locals; the 2nd is for the arm's guard.)
+    var_indices: NodeMap<LocalsForNode>,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
     unit_temp: Option<Place<'tcx>>,
 
@@ -305,6 +311,74 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     cached_unreachable_block: Option<BasicBlock>,
 }
 
+impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
+    fn is_bound_var_in_guard(&self, id: ast::NodeId) -> bool {
+        self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
+    }
+
+    fn var_local_id(&self, id: ast::NodeId, for_guard: ForGuard) -> Local {
+        self.var_indices[&id].local_id(for_guard)
+    }
+}
+
+#[derive(Debug)]
+enum LocalsForNode {
+    One(Local),
+    Two { for_guard: Local, for_arm_body: Local },
+}
+
+#[derive(Debug)]
+struct GuardFrameLocal {
+    id: ast::NodeId,
+}
+
+impl GuardFrameLocal {
+    fn new(id: ast::NodeId, _binding_mode: BindingMode) -> Self {
+        GuardFrameLocal {
+            id: id,
+        }
+    }
+}
+
+#[derive(Debug)]
+struct GuardFrame {
+    /// These are the id's of names that are bound by patterns of the
+    /// arm of *this* guard.
+    ///
+    /// (Frames higher up the stack will have the id's bound in arms
+    /// further out, such as in a case like:
+    ///
+    /// match E1 {
+    ///      P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
+    /// }
+    ///
+    /// here, when building for FIXME
+    locals: Vec<GuardFrameLocal>,
+}
+
+/// ForGuard is isomorphic to a boolean flag. It indicates whether we are
+/// talking about the temp for a local binding for a use within a guard expression,
+/// or a temp for use outside of a guard expressions.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum ForGuard {
+    WithinGuard,
+    OutsideGuard,
+}
+
+impl LocalsForNode {
+    fn local_id(&self, for_guard: ForGuard) -> Local {
+        match (self, for_guard) {
+            (&LocalsForNode::One(local_id), ForGuard::OutsideGuard) |
+            (&LocalsForNode::Two { for_guard: local_id, .. }, ForGuard::WithinGuard) |
+            (&LocalsForNode::Two { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) =>
+                local_id,
+
+            (&LocalsForNode::One(_), ForGuard::WithinGuard) =>
+                bug!("anything with one local should never be within a guard."),
+        }
+    }
+}
+
 struct CFG<'tcx> {
     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
 }
@@ -548,6 +622,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
             visibility_scope_info: IndexVec::new(),
+            guard_context: vec![],
             push_unsafe_count: 0,
             unpushed_unsafe: safety,
             breakable_scopes: vec![],
@@ -636,11 +711,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     // Don't introduce extra copies for simple bindings
                     PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => {
                         self.local_decls[local].mutability = mutability;
-                        self.var_indices.insert(var, local);
+                        self.var_indices.insert(var, LocalsForNode::One(local));
                     }
                     _ => {
                         scope = self.declare_bindings(scope, ast_body.span,
-                                                      LintLevel::Inherited, &pattern);
+                                                      LintLevel::Inherited, &pattern,
+                                                      matches::ArmHasGuard(false));
                         unpack!(block = self.place_into_pattern(block, pattern, &place));
                     }
                 }
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 07585c08f6a..9096ac1444c 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -73,8 +73,8 @@ pub type Node = BasicBlock;
 pub struct Edge { source: BasicBlock, index: usize }
 
 fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
-    let succ_len = mir[bb].terminator().successors().len();
-    (0..succ_len).map(|index| Edge { source: bb, index: index}).collect()
+    mir[bb].terminator().successors().enumerate()
+        .map(|(index, _)| Edge { source: bb, index: index}).collect()
 }
 
 impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
@@ -285,6 +285,6 @@ impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P>
 
     fn target(&self, edge: &Edge) -> Node {
         let mir = self.mbcx.mir();
-        mir[edge.source].terminator().successors()[edge.index]
+        *mir[edge.source].terminator().successors().nth(edge.index).unwrap()
     }
 }
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index a21691813a4..098ad8e558f 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -179,8 +179,14 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                     if let RegionKind::ReEmpty = region {
                         // If the borrowed value dies before the borrow is used, the region for
                         // the borrow can be empty. Don't track the borrow in that case.
+                        debug!("Borrows::statement_effect_on_borrows \
+                                location: {:?} stmt: {:?} has empty region, killing {:?}",
+                               location, stmt.kind, index);
                         sets.kill(&index);
                         return
+                    } else {
+                        debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}",
+                               location, stmt.kind);
                     }
 
                     assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| {
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index e6aa2d3abb7..5890ea5c9d0 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -30,9 +30,9 @@ use syntax::ast::{self, LitKind};
 use syntax::attr;
 use syntax::symbol::Symbol;
 use rustc::hir;
-use rustc_const_math::ConstFloat;
 use rustc_data_structures::sync::Lrc;
 use rustc::mir::interpret::{Value, PrimVal};
+use hair::pattern::parse_float;
 
 #[derive(Clone)]
 pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
@@ -170,12 +170,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         neg: bool,
     ) -> Literal<'tcx> {
         trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg);
-        let tcx = self.tcx.global_tcx();
 
-        let parse_float = |num: &str, fty| -> ConstFloat {
-            ConstFloat::from_str(num, fty).unwrap_or_else(|_| {
+        let parse_float = |num, fty| -> Value {
+            parse_float(num, fty, neg).unwrap_or_else(|_| {
                 // FIXME(#31407) this is only necessary because float parsing is buggy
-                tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)");
+                self.tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)");
             })
         };
 
@@ -213,26 +212,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
             },
             LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))),
             LitKind::Float(n, fty) => {
-                let n = n.as_str();
-                let mut f = parse_float(&n, fty);
-                if neg {
-                    f = -f;
-                }
-                let bits = f.bits;
-                Value::ByVal(PrimVal::Bytes(bits))
+                parse_float(n, fty)
             }
             LitKind::FloatUnsuffixed(n) => {
                 let fty = match ty.sty {
                     ty::TyFloat(fty) => fty,
                     _ => bug!()
                 };
-                let n = n.as_str();
-                let mut f = parse_float(&n, fty);
-                if neg {
-                    f = -f;
-                }
-                let bits = f.bits;
-                Value::ByVal(PrimVal::Bytes(bits))
+                parse_float(n, fty)
             }
             LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
             LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index d924baaf005..77bcd88cecb 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -17,7 +17,7 @@ use super::{Pattern, PatternContext, PatternError, PatternKind};
 use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
 use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
 use rustc::middle::expr_use_visitor as euv;
-use rustc::middle::mem_categorization::{cmt};
+use rustc::middle::mem_categorization::cmt_;
 use rustc::middle::region;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -573,13 +573,13 @@ struct MutationChecker<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
-    fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {}
-    fn consume(&mut self, _: ast::NodeId, _: Span, _: cmt, _: ConsumeMode) {}
-    fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {}
+    fn matched_pat(&mut self, _: &Pat, _: &cmt_, _: euv::MatchMode) {}
+    fn consume(&mut self, _: ast::NodeId, _: Span, _: &cmt_, _: ConsumeMode) {}
+    fn consume_pat(&mut self, _: &Pat, _: &cmt_, _: ConsumeMode) {}
     fn borrow(&mut self,
               _: ast::NodeId,
               span: Span,
-              _: cmt,
+              _: &cmt_,
               _: ty::Region<'tcx>,
               kind:ty:: BorrowKind,
               _: LoanCause) {
@@ -594,7 +594,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
         }
     }
     fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {}
-    fn mutate(&mut self, _: ast::NodeId, span: Span, _: cmt, mode: MutateMode) {
+    fn mutate(&mut self, _: ast::NodeId, span: Span, _: &cmt_, mode: MutateMode) {
         match mode {
             MutateMode::JustWrite | MutateMode::WriteAndRead => {
                 struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index c2da8c11d87..623e0de478b 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -28,13 +28,13 @@ use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_const_math::ConstFloat;
 
 use std::cmp::Ordering;
 use std::fmt;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax_pos::Span;
+use syntax_pos::symbol::Symbol;
 
 #[derive(Clone, Debug)]
 pub enum PatternError {
@@ -792,7 +792,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                 ConstVal::Value(miri) => const_val_field(
                     self.tcx, self.param_env, instance,
                     variant_opt, field, miri, cv.ty,
-                ).unwrap(),
+                ).expect("field access failed"),
                 _ => bug!("{:#?} is not a valid adt", cv),
             };
             self.const_to_pat(instance, val, id, span)
@@ -1053,24 +1053,22 @@ pub fn compare_const_vals<'a, 'tcx>(
     b: &ConstVal,
     ty: Ty<'tcx>,
 ) -> Option<Ordering> {
-    use rustc_const_math::ConstFloat;
     trace!("compare_const_vals: {:?}, {:?}", a, b);
     use rustc::mir::interpret::{Value, PrimVal};
     match (a, b) {
         (&ConstVal::Value(Value::ByVal(PrimVal::Bytes(a))),
          &ConstVal::Value(Value::ByVal(PrimVal::Bytes(b)))) => {
+            use ::rustc_apfloat::Float;
             match ty.sty {
-                ty::TyFloat(ty) => {
-                    let l = ConstFloat {
-                        bits: a,
-                        ty,
-                    };
-                    let r = ConstFloat {
-                        bits: b,
-                        ty,
-                    };
-                    // FIXME(oli-obk): report cmp errors?
-                    l.try_cmp(r).ok()
+                ty::TyFloat(ast::FloatTy::F32) => {
+                    let l = ::rustc_apfloat::ieee::Single::from_bits(a);
+                    let r = ::rustc_apfloat::ieee::Single::from_bits(b);
+                    l.partial_cmp(&r)
+                },
+                ty::TyFloat(ast::FloatTy::F64) => {
+                    let l = ::rustc_apfloat::ieee::Double::from_bits(a);
+                    let r = ::rustc_apfloat::ieee::Double::from_bits(b);
+                    l.partial_cmp(&r)
                 },
                 ty::TyInt(_) => {
                     let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt");
@@ -1148,26 +1146,14 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
             Value::ByVal(PrimVal::Bytes(n))
         },
         LitKind::Float(n, fty) => {
-            let n = n.as_str();
-            let mut f = parse_float(&n, fty)?;
-            if neg {
-                f = -f;
-            }
-            let bits = f.bits;
-            Value::ByVal(PrimVal::Bytes(bits))
+            parse_float(n, fty, neg)?
         }
         LitKind::FloatUnsuffixed(n) => {
             let fty = match ty.sty {
                 ty::TyFloat(fty) => fty,
                 _ => bug!()
             };
-            let n = n.as_str();
-            let mut f = parse_float(&n, fty)?;
-            if neg {
-                f = -f;
-            }
-            let bits = f.bits;
-            Value::ByVal(PrimVal::Bytes(bits))
+            parse_float(n, fty, neg)?
         }
         LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
         LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
@@ -1175,7 +1161,36 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
     Ok(ConstVal::Value(lit))
 }
 
-fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
-                     -> Result<ConstFloat, ()> {
-    ConstFloat::from_str(num, fty).map_err(|_| ())
+pub fn parse_float(
+    num: Symbol,
+    fty: ast::FloatTy,
+    neg: bool,
+) -> Result<Value, ()> {
+    let num = num.as_str();
+    use rustc_apfloat::ieee::{Single, Double};
+    use rustc_apfloat::Float;
+    let bits = match fty {
+        ast::FloatTy::F32 => {
+            num.parse::<f32>().map_err(|_| ())?;
+            let mut f = num.parse::<Single>().unwrap_or_else(|e| {
+                panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
+            });
+            if neg {
+                f = -f;
+            }
+            f.to_bits()
+        }
+        ast::FloatTy::F64 => {
+            num.parse::<f64>().map_err(|_| ())?;
+            let mut f = num.parse::<Double>().unwrap_or_else(|e| {
+                panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
+            });
+            if neg {
+                f = -f;
+            }
+            f.to_bits()
+        }
+    };
+
+    Ok(Value::ByVal(PrimVal::Bytes(bits)))
 }
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index e654142d216..002b5eb187d 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -2,10 +2,9 @@ use rustc::ty::Ty;
 use rustc::ty::layout::LayoutOf;
 use syntax::ast::{FloatTy, IntTy, UintTy};
 
-use rustc_const_math::ConstFloat;
+use rustc_apfloat::ieee::{Single, Double};
 use super::{EvalContext, Machine};
 use rustc::mir::interpret::{PrimVal, EvalResult, MemoryPointer, PointerArithmetic};
-use rustc_apfloat::ieee::{Single, Double};
 use rustc_apfloat::Float;
 
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
@@ -50,8 +49,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 Ok(PrimVal::Bytes(v))
             }
 
-            TyFloat(fty) if signed => Ok(PrimVal::Bytes(ConstFloat::from_i128(v as i128, fty).bits)),
-            TyFloat(fty) => Ok(PrimVal::Bytes(ConstFloat::from_u128(v, fty).bits)),
+            TyFloat(FloatTy::F32) if signed => Ok(PrimVal::Bytes(Single::from_i128(v as i128).value.to_bits())),
+            TyFloat(FloatTy::F64) if signed => Ok(PrimVal::Bytes(Double::from_i128(v as i128).value.to_bits())),
+            TyFloat(FloatTy::F32) => Ok(PrimVal::Bytes(Single::from_u128(v).value.to_bits())),
+            TyFloat(FloatTy::F64) => Ok(PrimVal::Bytes(Double::from_u128(v).value.to_bits())),
 
             TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)),
             TyChar => err!(InvalidChar(v)),
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index a25331f7279..dff9fa271ab 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -263,7 +263,7 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
     ) -> EvalResult<'tcx> {
         let substs = instance.substs;
 
-        let intrinsic_name = &ecx.tcx.item_name(instance.def_id())[..];
+        let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..];
         match intrinsic_name {
             "min_align_of" => {
                 let elem_ty = substs.type_at(0);
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4b57c641546..bea29b6926a 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -513,7 +513,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                     // it emits in debug mode) is performance, but it doesn't cost us any performance in miri.
                     // If, however, the compiler ever starts transforming unchecked intrinsics into unchecked binops,
                     // we have to go back to just ignoring the overflow here.
-                    return err!(OverflowingMath);
+                    return err!(Overflow(bin_op));
                 }
             }
 
@@ -768,9 +768,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             }
         }
 
-        if log_enabled!(::log::Level::Trace) {
-            self.dump_local(dest);
-        }
+        self.dump_local(dest);
 
         Ok(())
     }
@@ -919,8 +917,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                 niche_start,
                 ..
             } => {
-                let variants_start = niche_variants.start as u128;
-                let variants_end = niche_variants.end as u128;
+                let variants_start = *niche_variants.start() as u128;
+                let variants_end = *niche_variants.end() as u128;
                 match raw_discr {
                     PrimVal::Ptr(_) => {
                         assert!(niche_start == 0);
@@ -986,7 +984,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                 if variant_index != dataful_variant {
                     let (niche_dest, niche) =
                         self.place_field(dest, mir::Field::new(0), layout)?;
-                    let niche_value = ((variant_index - niche_variants.start) as u128)
+                    let niche_value = ((variant_index - niche_variants.start()) as u128)
                         .wrapping_add(niche_start);
                     self.write_primval(niche_dest, PrimVal::Bytes(niche_value), niche.ty)?;
                 }
@@ -1342,9 +1340,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         use syntax::ast::FloatTy;
 
         let layout = self.layout_of(ty)?;
-        // do the strongest layout check of the two
-        let align = layout.align.max(ptr_align);
-        self.memory.check_align(ptr, align)?;
+        self.memory.check_align(ptr, ptr_align)?;
 
         if layout.size.bytes() == 0 {
             return Ok(Some(Value::ByVal(PrimVal::Undef)));
@@ -1572,6 +1568,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
 
     pub fn dump_local(&self, place: Place) {
         // Debug output
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         match place {
             Place::Local { frame, local } => {
                 let mut allocs = Vec::new();
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 5e156e9271f..7f8205b8327 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -334,11 +334,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
 
     /// For debugging, print an allocation and all allocations it points to, recursively.
     pub fn dump_alloc(&self, id: AllocId) {
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         self.dump_allocs(vec![id]);
     }
 
     /// For debugging, print a list of allocations and all allocations they point to, recursively.
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
+        if !log_enabled!(::log::Level::Trace) {
+            return;
+        }
         use std::fmt::Write;
         allocs.sort();
         allocs.dedup();
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index dfc0c4a824a..ef6deab0477 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -1,9 +1,10 @@
 use rustc::mir;
 use rustc::ty::{self, Ty};
-use rustc_const_math::ConstFloat;
 use syntax::ast::FloatTy;
 use std::cmp::Ordering;
 use rustc::ty::layout::LayoutOf;
+use rustc_apfloat::ieee::{Double, Single};
+use rustc_apfloat::Float;
 
 use super::{EvalContext, Place, Machine, ValTy};
 
@@ -125,31 +126,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             return err!(Unimplemented(msg));
         }
 
-        let float_op = |op, l, r, ty| {
-            let l = ConstFloat {
-                bits: l,
-                ty,
-            };
-            let r = ConstFloat {
-                bits: r,
-                ty,
-            };
-            match op {
-                Eq => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Equal),
-                Ne => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Equal),
-                Lt => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Less),
-                Le => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Greater),
-                Gt => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Greater),
-                Ge => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Less),
-                Add => PrimVal::Bytes((l + r).unwrap().bits),
-                Sub => PrimVal::Bytes((l - r).unwrap().bits),
-                Mul => PrimVal::Bytes((l * r).unwrap().bits),
-                Div => PrimVal::Bytes((l / r).unwrap().bits),
-                Rem => PrimVal::Bytes((l % r).unwrap().bits),
-                _ => bug!("invalid float op: `{:?}`", op),
-            }
-        };
-
         if left_layout.abi.is_signed() {
             let op: Option<fn(&i128, &i128) -> bool> = match bin_op {
                 Lt => Some(i128::lt),
@@ -164,7 +140,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 return Ok((PrimVal::from_bool(op(&l, &r)), false));
             }
             let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
-                Rem | Div if r == 0 => return Ok((PrimVal::Bytes(l), true)),
+                Div if r == 0 => return err!(DivisionByZero),
+                Rem if r == 0 => return err!(RemainderByZero),
                 Div => Some(i128::overflowing_div),
                 Rem => Some(i128::overflowing_rem),
                 Add => Some(i128::overflowing_add),
@@ -199,7 +176,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
         }
 
         if let ty::TyFloat(fty) = left_ty.sty {
-            return Ok((float_op(bin_op, l, r, fty), false));
+            macro_rules! float_math {
+                ($ty:path) => {{
+                    let l = <$ty>::from_bits(l);
+                    let r = <$ty>::from_bits(r);
+                    let val = match bin_op {
+                        Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Equal),
+                        Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Equal),
+                        Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Less),
+                        Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Greater),
+                        Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Greater),
+                        Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Less),
+                        Add => PrimVal::Bytes((l + r).value.to_bits()),
+                        Sub => PrimVal::Bytes((l - r).value.to_bits()),
+                        Mul => PrimVal::Bytes((l * r).value.to_bits()),
+                        Div => PrimVal::Bytes((l / r).value.to_bits()),
+                        Rem => PrimVal::Bytes((l % r).value.to_bits()),
+                        _ => bug!("invalid float op: `{:?}`", bin_op),
+                    };
+                    return Ok((val, false));
+                }};
+            }
+            match fty {
+                FloatTy::F32 => float_math!(Single),
+                FloatTy::F64 => float_math!(Double),
+            }
         }
 
         // only ints left
@@ -221,7 +222,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                     Add => u128::overflowing_add,
                     Sub => u128::overflowing_sub,
                     Mul => u128::overflowing_mul,
-                    Rem | Div if r == 0 => return Ok((PrimVal::Bytes(l), true)),
+                    Div if r == 0 => return err!(DivisionByZero),
+                    Rem if r == 0 => return err!(RemainderByZero),
                     Div => u128::overflowing_div,
                     Rem => u128::overflowing_rem,
                     _ => bug!(),
@@ -269,7 +271,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             (Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)),
             (Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)),
 
-            (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowingMath),
+            (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowNeg),
             (Neg, _) => (-(bytes as i128)) as u128,
         };
 
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 42cb149d682..d03204bfab1 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -219,9 +219,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             }
         };
 
-        if log_enabled!(::log::Level::Trace) {
-            self.dump_local(place);
-        }
+        self.dump_local(place);
 
         Ok(place)
     }
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index aa80ee7af18..0e0d91f4724 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -148,23 +148,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 if expected == cond_val {
                     self.goto_block(target);
                 } else {
-                    use rustc::mir::AssertMessage::*;
+                    use rustc::mir::interpret::EvalErrorKind::*;
                     return match *msg {
                         BoundsCheck { ref len, ref index } => {
-                            let span = terminator.source_info.span;
                             let len = self.eval_operand_to_primval(len)
                                 .expect("can't eval len")
                                 .to_u64()?;
                             let index = self.eval_operand_to_primval(index)
                                 .expect("can't eval index")
                                 .to_u64()?;
-                            err!(ArrayIndexOutOfBounds(span, len, index))
-                        }
-                        Math(ref err) => {
-                            err!(Math(terminator.source_info.span, err.clone()))
+                            err!(BoundsCheck { len, index })
                         }
+                        Overflow(op) => Err(Overflow(op).into()),
+                        OverflowNeg => Err(OverflowNeg.into()),
+                        DivisionByZero => Err(DivisionByZero.into()),
+                        RemainderByZero => Err(RemainderByZero.into()),
                         GeneratorResumedAfterReturn |
                         GeneratorResumedAfterPanic => unimplemented!(),
+                        _ => bug!(),
                     };
                 }
             }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 399892522a3..2545ba3a94a 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -24,16 +24,17 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
-#![feature(dyn_trait)]
+#![cfg_attr(stage0, feature(dyn_trait))]
 #![feature(fs_read_write)]
 #![feature(macro_vis_matcher)]
 #![feature(exhaustive_patterns)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(nonzero)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 #![feature(crate_visibility_modifier)]
 #![feature(never_type)]
+#![feature(specialization)]
 #![cfg_attr(stage0, feature(try_trait))]
 
 extern crate arena;
@@ -50,8 +51,6 @@ extern crate rustc_errors;
 extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_target;
-extern crate rustc_const_math;
-extern crate core; // for NonZero
 extern crate log_settings;
 extern crate rustc_apfloat;
 extern crate byteorder;
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 9e0c977a3f0..9e43bed1b63 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
             MonoItem::GlobalAsm(node_id) => {
                 let def_id = tcx.hir.local_def_id(node_id);
                 ty::SymbolName {
-                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_str()
+                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str()
                 }
             }
         }
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index f29f86af4ab..3a65cd4ea77 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -146,7 +146,7 @@ pub trait CodegenUnitExt<'tcx> {
     }
 
     fn work_product_id(&self) -> WorkProductId {
-        WorkProductId::from_cgu_name(self.name())
+        WorkProductId::from_cgu_name(&self.name().as_str())
     }
 
     fn items_in_deterministic_order<'a>(&self,
@@ -206,9 +206,9 @@ fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
     const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
 
     if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
-        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str()
+        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str()
     } else {
-        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str()
+        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str()
     }
 }
 
@@ -740,7 +740,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         }
                     }) {
         cgu_name.push_str("-");
-        cgu_name.push_str(&part.data.as_interned_str());
+        cgu_name.push_str(&part.data.as_interned_str().as_str());
     }
 
     if volatile {
@@ -753,11 +753,11 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         CodegenUnit::mangle_name(&cgu_name)
     };
 
-    Symbol::intern(&cgu_name[..]).as_str()
+    Symbol::intern(&cgu_name[..]).as_interned_str()
 }
 
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
-    Symbol::intern(&format!("{}{}", crate_name, index)).as_str()
+    Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str()
 }
 
 fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -772,7 +772,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             debug!("CodegenUnit {}:", cgu.name());
 
             for (trans_item, linkage) in cgu.items() {
-                let symbol_name = trans_item.symbol_name(tcx);
+                let symbol_name = trans_item.symbol_name(tcx).name.as_str();
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
                                                    .unwrap_or("<no hash>");
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index af60a83a4a2..699a5b17435 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -210,7 +210,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(..) = ty {
         let patch = {
-            let param_env = tcx.param_env(def_id);
+            let param_env = tcx.param_env(def_id).with_reveal_all();
             let mut elaborator = DropShimElaborator {
                 mir: &mir,
                 patch: MirPatch::new(&mir),
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 31af7c21857..2bf5a49c97e 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     self.visibility_scope_info[source_info.scope].lint_root;
                 self.register_violations(&[UnsafetyViolation {
                     source_info,
-                    description: Symbol::intern("borrow of packed field").as_str(),
+                    description: Symbol::intern("borrow of packed field").as_interned_str(),
                     kind: UnsafetyViolationKind::BorrowPacked(lint_root)
                 }], &[]);
             }
@@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.visibility_scope_info[source_info.scope].lint_root;
                     self.register_violations(&[UnsafetyViolation {
                         source_info,
-                        description: Symbol::intern("use of extern static").as_str(),
+                        description: Symbol::intern("use of extern static").as_interned_str(),
                         kind: UnsafetyViolationKind::ExternStatic(lint_root)
                     }], &[]);
                 }
@@ -231,7 +231,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info,
-            description: Symbol::intern(description).as_str(),
+            description: Symbol::intern(description).as_interned_str(),
             kind: UnsafetyViolationKind::General,
         }], &[]);
     }
@@ -444,7 +444,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                 struct_span_err!(
                     tcx.sess, source_info.span, E0133,
                     "{} requires unsafe function or block", description)
-                    .span_label(source_info.span, &description[..])
+                    .span_label(source_info.span, &description.as_str()[..])
                     .emit();
             }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
@@ -452,7 +452,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                               lint_node_id,
                               source_info.span,
                               &format!("{} requires unsafe function or \
-                                        block (error E0133)", &description[..]));
+                                        block (error E0133)", &description.as_str()[..]));
             }
             UnsafetyViolationKind::BorrowPacked(lint_node_id) => {
                 if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) {
@@ -462,7 +462,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                                   lint_node_id,
                                   source_info.span,
                                   &format!("{} requires unsafe function or \
-                                            block (error E0133)", &description[..]));
+                                            block (error E0133)", &description.as_str()[..]));
                 }
             }
         }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 47b2f430bc7..e1db216b6bb 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -328,7 +328,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                         } else {
                             if overflow {
                                 use rustc::mir::interpret::EvalErrorKind;
-                                let mut err = EvalErrorKind::OverflowingMath.into();
+                                let mut err = EvalErrorKind::Overflow(op).into();
                                 ecx.report(&mut err, false, Some(span));
                                 return None;
                             }
@@ -478,12 +478,12 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         .hir
                         .as_local_node_id(self.source.def_id)
                         .expect("some part of a failing const eval must be local");
-                    use rustc::mir::AssertMessage::*;
+                    use rustc::mir::interpret::EvalErrorKind::*;
                     let msg = match msg {
-                        // Need proper const propagator for these
-                        GeneratorResumedAfterReturn |
-                        GeneratorResumedAfterPanic => return,
-                        Math(ref err) => err.description().to_owned(),
+                        Overflow(_) |
+                        OverflowNeg |
+                        DivisionByZero |
+                        RemainderByZero => msg.description().to_owned(),
                         BoundsCheck { ref len, ref index } => {
                             let len = self.eval_operand(len).expect("len must be const");
                             let len = match len.0 {
@@ -504,6 +504,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                                 index,
                             )
                         },
+                        // Need proper const propagator for these
+                        _ => return,
                     };
                     self.tcx.lint_node(
                         ::rustc::lint::builtin::CONST_ERR,
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 95fe99a1bec..fba60c7e8dc 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -29,7 +29,6 @@
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
-use rustc::hir;
 use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
@@ -41,26 +40,8 @@ pub struct CopyPropagation;
 impl MirPass for CopyPropagation {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          source: MirSource,
+                          _source: MirSource,
                           mir: &mut Mir<'tcx>) {
-        // Don't run on constant MIR, because trans might not be able to
-        // evaluate the modified MIR.
-        // FIXME(eddyb) Remove check after miri is merged.
-        let id = tcx.hir.as_local_node_id(source.def_id).unwrap();
-        match (tcx.hir.body_owner_kind(id), source.promoted) {
-            (_, Some(_)) |
-            (hir::BodyOwnerKind::Const, _) |
-            (hir::BodyOwnerKind::Static(_), _) => return,
-
-            (hir::BodyOwnerKind::Fn, _) => {
-                if tcx.is_const_fn(source.def_id) {
-                    // Don't run on const functions, as, again, trans might not be able to evaluate
-                    // the optimized IR.
-                    return
-                }
-            }
-        }
-
         // We only run when the MIR optimization level is > 1.
         // This avoids a slow pass, and messing up debug info.
         if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index 503354ebc4f..8b2b9ef7e81 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::hir;
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
 use rustc_data_structures::indexed_vec::Idx;
@@ -19,26 +18,8 @@ pub struct Deaggregator;
 impl MirPass for Deaggregator {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          source: MirSource,
+                          _source: MirSource,
                           mir: &mut Mir<'tcx>) {
-        // Don't run on constant MIR, because trans might not be able to
-        // evaluate the modified MIR.
-        // FIXME(eddyb) Remove check after miri is merged.
-        let id = tcx.hir.as_local_node_id(source.def_id).unwrap();
-        match (tcx.hir.body_owner_kind(id), source.promoted) {
-            (_, Some(_)) |
-            (hir::BodyOwnerKind::Const, _) |
-            (hir::BodyOwnerKind::Static(_), _) => return,
-
-            (hir::BodyOwnerKind::Fn, _) => {
-                if tcx.is_const_fn(source.def_id) {
-                    // Don't run on const functions, as, again, trans might not be able to evaluate
-                    // the optimized IR.
-                    return
-                }
-            }
-        }
-
         let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
         let local_decls = &*local_decls;
         for bb in basic_blocks {
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 2e8dd623d74..5397d18cdd7 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -15,7 +15,6 @@ use dataflow::{on_all_children_bits, on_all_drop_children_bits};
 use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits};
 use dataflow::MoveDataParamEnv;
 use dataflow::{self, do_dataflow, DebugFormatted};
-use rustc::hir;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::middle::const_val::ConstVal;
@@ -42,15 +41,8 @@ impl MirPass for ElaborateDrops {
     {
         debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
 
-        // Don't run on constant MIR, because trans might not be able to
-        // evaluate the modified MIR.
-        // FIXME(eddyb) Remove check after miri is merged.
         let id = tcx.hir.as_local_node_id(src.def_id).unwrap();
-        match (tcx.hir.body_owner_kind(id), src.promoted) {
-            (hir::BodyOwnerKind::Fn, None) => {},
-            _ => return
-        }
-        let param_env = tcx.param_env(src.def_id);
+        let param_env = tcx.param_env(src.def_id).with_reveal_all();
         let move_data = MoveData::gather_moves(mir, tcx).unwrap();
         let elaborate_patch = {
             let mir = &*mir;
@@ -558,7 +550,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     }
 
     fn drop_flags_on_init(&mut self) {
-        let loc = Location { block: START_BLOCK, statement_index: 0 };
+        let loc = Location::START;
         let span = self.patch.source_info_for_location(self.mir, loc).span;
         let false_ = self.constant_bool(span, false);
         for flag in self.drop_flags.values() {
@@ -584,7 +576,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     }
 
     fn drop_flags_for_args(&mut self) {
-        let loc = Location { block: START_BLOCK, statement_index: 0 };
+        let loc = Location::START;
         dataflow::drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.env, |path, ds| {
                 self.set_drop_flag(loc, path, ds);
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 0ff73569433..36735586e81 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -738,12 +738,17 @@ fn create_generator_resume_function<'a, 'tcx>(
 
     let mut cases = create_cases(mir, &transform, |point| Some(point.resume));
 
+    use rustc::mir::interpret::EvalErrorKind::{
+        GeneratorResumedAfterPanic,
+        GeneratorResumedAfterReturn,
+    };
+
     // Jump to the entry point on the 0 state
     cases.insert(0, (0, BasicBlock::new(0)));
     // Panic when resumed on the returned (1) state
-    cases.insert(1, (1, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterReturn)));
+    cases.insert(1, (1, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn)));
     // Panic when resumed on the poisoned (2) state
-    cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic)));
+    cases.insert(2, (2, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic)));
 
     insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable);
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 2b491385d66..ee6d42b1fe5 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -126,7 +126,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     continue;
                 }
 
-                let callee_mir = match ty::queries::optimized_mir::try_get(self.tcx,
+                let callee_mir = match self.tcx.try_get_query::<ty::queries::optimized_mir>(
                                                                            callsite.location.span,
                                                                            callsite.callee) {
                     Ok(callee_mir) if self.should_inline(callsite, callee_mir) => {
@@ -330,7 +330,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             }
 
             if !is_drop {
-                for &succ in &term.successors()[..] {
+                for &succ in term.successors() {
                     work_list.push(succ);
                 }
             }
@@ -379,8 +379,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
                 debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
 
-                let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn();
-
                 let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len());
                 let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len());
                 let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len());
@@ -460,24 +458,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
                 let return_block = destination.1;
 
-                let args : Vec<_> = if is_box_free {
-                    assert!(args.len() == 1);
-                    // box_free takes a Box, but is defined with a *mut T, inlining
-                    // needs to generate the cast.
-                    // FIXME: we should probably just generate correct MIR in the first place...
-
-                    let arg = if let Operand::Move(ref place) = args[0] {
-                        place.clone()
-                    } else {
-                        bug!("Constant arg to \"box_free\"");
-                    };
-
-                    let ptr_ty = args[0].ty(caller_mir, self.tcx);
-                    vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)]
-                } else {
-                    // Copy the arguments if needed.
-                    self.make_call_args(args, &callsite, caller_mir)
-                };
+                // Copy the arguments if needed.
+                let args: Vec<_> = self.make_call_args(args, &callsite, caller_mir);
 
                 let bb_len = caller_mir.basic_blocks().len();
                 let mut integrator = Integrator {
@@ -518,49 +500,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         }
     }
 
-    fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>,
-                         callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
-        let arg = Rvalue::Ref(
-            self.tcx.types.re_erased,
-            BorrowKind::Mut { allow_two_phase_borrow: false },
-            arg.deref());
-
-        let ty = arg.ty(caller_mir, self.tcx);
-        let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
-        let ref_tmp = caller_mir.local_decls.push(ref_tmp);
-        let ref_tmp = Place::Local(ref_tmp);
-
-        let ref_stmt = Statement {
-            source_info: callsite.location,
-            kind: StatementKind::Assign(ref_tmp.clone(), arg)
-        };
-
-        caller_mir[callsite.bb]
-            .statements.push(ref_stmt);
-
-        let pointee_ty = match ptr_ty.sty {
-            ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty,
-            _ if ptr_ty.is_box() => ptr_ty.boxed_ty(),
-            _ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty)
-        };
-        let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty);
-
-        let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Move(ref_tmp), ptr_ty);
-
-        let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
-        let cast_tmp = caller_mir.local_decls.push(cast_tmp);
-
-        let cast_stmt = Statement {
-            source_info: callsite.location,
-            kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr)
-        };
-
-        caller_mir[callsite.bb]
-            .statements.push(cast_stmt);
-
-        cast_tmp
-    }
-
     fn make_call_args(
         &self,
         args: Vec<Operand<'tcx>>,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index ff7551ed6f4..4762c6aaa27 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -868,7 +868,7 @@ This does not pose a problem by itself because they can't be accessed directly."
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
                         assert!(!self.tcx.is_const_fn(def_id));
-                        match &self.tcx.item_name(def_id)[..] {
+                        match &self.tcx.item_name(def_id).as_str()[..] {
                             "size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id),
 
                             name if name.starts_with("simd_shuffle") => {
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 6d365012525..bcc8fef18f0 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -78,7 +78,7 @@ impl RemoveNoopLandingPads {
             TerminatorKind::SwitchInt { .. } |
             TerminatorKind::FalseEdges { .. } |
             TerminatorKind::FalseUnwind { .. } => {
-                terminator.successors().iter().all(|succ| {
+                terminator.successors().all(|succ| {
                     nop_landing_pads.contains(succ.index())
                 })
             },
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 2c6ed1f19b7..691fdd130e5 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -91,7 +91,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
 
         for (_, data) in traversal::preorder(mir) {
             if let Some(ref term) = data.terminator {
-                for &tgt in term.successors().iter() {
+                for &tgt in term.successors() {
                     pred_count[tgt] += 1;
                 }
             }
@@ -219,10 +219,10 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
         };
 
         let first_succ = {
-            let successors = terminator.successors();
-            if let Some(&first_succ) = terminator.successors().get(0) {
-                if successors.iter().all(|s| *s == first_succ) {
-                    self.pred_count[first_succ] -= (successors.len()-1) as u32;
+            if let Some(&first_succ) = terminator.successors().nth(0) {
+                if terminator.successors().all(|s| *s == first_succ) {
+                    let count = terminator.successors().count();
+                    self.pred_count[first_succ] -= (count - 1) as u32;
                     first_succ
                 } else {
                     return false
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 19f33ef5d45..4b7c581d3c8 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -13,6 +13,7 @@ use rustc::hir;
 use rustc::mir::*;
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::lang_items;
+use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Substs};
 use rustc::ty::util::IntTypeExt;
@@ -206,6 +207,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             let field = Field::new(i);
             let subpath = self.elaborator.field_subpath(variant_path, field);
 
+            assert_eq!(self.elaborator.param_env().reveal, Reveal::All);
             let field_ty = self.tcx().normalize_erasing_regions(
                 self.elaborator.param_env(),
                 f.ty(self.tcx(), substs),
@@ -337,18 +339,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         self.drop_ladder(fields, succ, unwind).0
     }
 
-    fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock
+    fn open_drop_for_box<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
+                             -> BasicBlock
     {
-        debug!("open_drop_for_box({:?}, {:?})", self, ty);
+        debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);
 
         let interior = self.place.clone().deref();
         let interior_path = self.elaborator.deref_subpath(self.path);
 
         let succ = self.succ; // FIXME(#43234)
         let unwind = self.unwind;
-        let succ = self.box_free_block(ty, succ, unwind);
+        let succ = self.box_free_block(adt, substs, succ, unwind);
         let unwind_succ = self.unwind.map(|unwind| {
-            self.box_free_block(ty, unwind, Unwind::InCleanup)
+            self.box_free_block(adt, substs, unwind, Unwind::InCleanup)
         });
 
         self.drop_subpath(&interior, interior_path, succ, unwind_succ)
@@ -791,11 +794,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             ty::TyTuple(tys) => {
                 self.open_drop_for_tuple(tys)
             }
-            ty::TyAdt(def, _) if def.is_box() => {
-                self.open_drop_for_box(ty.boxed_ty())
-            }
             ty::TyAdt(def, substs) => {
-                self.open_drop_for_adt(def, substs)
+                if def.is_box() {
+                    self.open_drop_for_box(def, substs)
+                } else {
+                    self.open_drop_for_adt(def, substs)
+                }
             }
             ty::TyDynamic(..) => {
                 let unwind = self.unwind; // FIXME(#43234)
@@ -858,28 +862,34 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
 
     fn box_free_block<'a>(
         &mut self,
-        ty: Ty<'tcx>,
+        adt: &'tcx ty::AdtDef,
+        substs: &'tcx Substs<'tcx>,
         target: BasicBlock,
         unwind: Unwind,
     ) -> BasicBlock {
-        let block = self.unelaborated_free_block(ty, target, unwind);
+        let block = self.unelaborated_free_block(adt, substs, target, unwind);
         self.drop_flag_test_block(block, target, unwind)
     }
 
     fn unelaborated_free_block<'a>(
         &mut self,
-        ty: Ty<'tcx>,
+        adt: &'tcx ty::AdtDef,
+        substs: &'tcx Substs<'tcx>,
         target: BasicBlock,
         unwind: Unwind
     ) -> BasicBlock {
         let tcx = self.tcx();
         let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
         let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
-        let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
+        let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
+            let field = Field::new(i);
+            let field_ty = f.ty(self.tcx(), substs);
+            Operand::Move(self.place.clone().field(field, field_ty))
+        }).collect();
 
         let call = TerminatorKind::Call {
             func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
-            args: vec![Operand::Move(self.place.clone())],
+            args: args,
             destination: Some((unit_temp, target)),
             cleanup: None
         }; // FIXME(#43234)
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 85b66c29be1..22e2b1b0b09 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -125,7 +125,7 @@ fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result
     let terminator = mir[source].terminator();
     let labels = terminator.kind.fmt_successor_labels();
 
-    for (&target, label) in terminator.successors().iter().zip(labels) {
+    for (&target, label) in terminator.successors().zip(labels) {
         writeln!(w, r#"    {} -> {} [label="{}"];"#, node(source), node(target), label)?;
     }
 
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 42ddabddd2d..cfb1a2cd28b 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -138,7 +138,7 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness
         for b in mir.basic_blocks().indices().rev() {
             // outs[b] = ∪ {ins of successors}
             bits.clear();
-            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
+            for &successor in mir.basic_blocks()[b].terminator().successors() {
                 bits.union(&ins[successor]);
             }
             outs[b].clone_from(&bits);
diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml
index 4bab24ae139..2babb93eedb 100644
--- a/src/librustc_passes/Cargo.toml
+++ b/src/librustc_passes/Cargo.toml
@@ -12,7 +12,6 @@ crate-type = ["dylib"]
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_mir = { path = "../librustc_mir"}
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index e65c9de8df1..b6b5edc0940 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -23,7 +23,6 @@
 #[macro_use]
 extern crate rustc;
 extern crate rustc_mir;
-extern crate rustc_const_math;
 extern crate rustc_data_structures;
 
 #[macro_use]
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index a4e056c6b58..45c6e89321d 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -18,6 +18,7 @@ use rustc::mir::{Place, PlaceElem, PlaceProjection};
 use rustc::mir::{Mir, Operand, ProjectionElem};
 use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
+use rustc::mir::interpret::EvalErrorKind;
 use rustc::mir::visit as mir_visit;
 use rustc::ty::{self, ClosureSubsts, TyCtxt};
 use rustc::util::nodemap::{FxHashMap};
@@ -133,14 +134,18 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
                             location: Location) {
         self.record("AssertMessage", msg);
         self.record(match *msg {
-            AssertMessage::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
-            AssertMessage::Math(..) => "AssertMessage::Math",
-            AssertMessage::GeneratorResumedAfterReturn => {
+            EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
+            EvalErrorKind::Overflow(..) => "AssertMessage::Overflow",
+            EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg",
+            EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero",
+            EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero",
+            EvalErrorKind::GeneratorResumedAfterReturn => {
                 "AssertMessage::GeneratorResumedAfterReturn"
             }
-            AssertMessage::GeneratorResumedAfterPanic => {
+            EvalErrorKind::GeneratorResumedAfterPanic => {
                 "AssertMessage::GeneratorResumedAfterPanic"
             }
+            _ => bug!(),
         }, msg);
         self.super_assert_message(msg, location);
     }
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index c5d2f0041a0..3a577341f7e 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -468,13 +468,13 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
     fn consume(&mut self,
                _consume_id: ast::NodeId,
                _consume_span: Span,
-               _cmt: mc::cmt,
+               _cmt: &mc::cmt_,
                _mode: euv::ConsumeMode) {}
 
     fn borrow(&mut self,
               borrow_id: ast::NodeId,
               _borrow_span: Span,
-              cmt: mc::cmt<'tcx>,
+              cmt: &mc::cmt_<'tcx>,
               _loan_region: ty::Region<'tcx>,
               bk: ty::BorrowKind,
               loan_cause: euv::LoanCause) {
@@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
             _ => {}
         }
 
-        let mut cur = &cmt;
+        let mut cur = cmt;
         loop {
             match cur.cat {
                 Categorization::Rvalue(..) => {
@@ -521,11 +521,11 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
     fn mutate(&mut self,
               _assignment_id: ast::NodeId,
               _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
+              _assignee_cmt: &mc::cmt_,
               _mode: euv::MutateMode) {
     }
 
-    fn matched_pat(&mut self, _: &hir::Pat, _: mc::cmt, _: euv::MatchMode) {}
+    fn matched_pat(&mut self, _: &hir::Pat, _: &mc::cmt_, _: euv::MatchMode) {}
 
-    fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: mc::cmt, _mode: euv::ConsumeMode) {}
+    fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: &mc::cmt_, _mode: euv::ConsumeMode) {}
 }
diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs
index 622d8e51a6c..348aa6a7cef 100644
--- a/src/librustc_plugin/lib.rs
+++ b/src/librustc_plugin/lib.rs
@@ -65,7 +65,6 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(rustc_diagnostic_macros)]
-#![feature(staged_api)]
 
 #[macro_use] extern crate syntax;
 
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index ebfd8785a0a..7e3c411c1d2 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -128,8 +128,6 @@ impl<'a> Registry<'a> {
     /// This can be used in place of `register_syntax_extension` to register legacy custom derives
     /// (i.e. attribute syntax extensions whose name begins with `derive_`). Legacy custom
     /// derives defined by this function do not trigger deprecation warnings when used.
-    #[unstable(feature = "rustc_private", issue = "27812")]
-    #[rustc_deprecated(since = "1.15.0", reason = "replaced by macros 1.1 (RFC 1861)")]
     pub fn register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension) {
         assert!(name.as_str().starts_with("derive_"));
         self.whitelisted_custom_derives.push(name);
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index f4e2136a5a1..ef5cc958283 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -17,7 +17,7 @@ use macros::{InvocationData, LegacyScope};
 use resolve_imports::ImportDirective;
 use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
 use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
-use {Resolver, ResolverArenas};
+use {PerNS, Resolver, ResolverArenas};
 use Namespace::{self, TypeNS, ValueNS, MacroNS};
 use {resolve_error, resolve_struct_error, ResolutionError};
 
@@ -41,7 +41,6 @@ use syntax::ext::tt::macro_rules;
 use syntax::parse::token::{self, Token};
 use syntax::std_inject::injected_crate_name;
 use syntax::symbol::keywords;
-use syntax::symbol::Symbol;
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -72,7 +71,6 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
 struct LegacyMacroImports {
     import_all: Option<Span>,
     imports: Vec<(Name, Span)>,
-    reexports: Vec<(Name, Span)>,
 }
 
 impl<'a> Resolver<'a> {
@@ -176,7 +174,11 @@ impl<'a> Resolver<'a> {
                 let subclass = SingleImport {
                     target: ident,
                     source,
-                    result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
+                    result: PerNS {
+                        type_ns: Cell::new(Err(Undetermined)),
+                        value_ns: Cell::new(Err(Undetermined)),
+                        macro_ns: Cell::new(Err(Undetermined)),
+                    },
                     type_ns_only,
                 };
                 self.add_import_directive(
@@ -544,14 +546,14 @@ impl<'a> Resolver<'a> {
         }
 
         let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
-            (self.cstore.crate_name_untracked(def_id.krate).as_str(), None)
+            (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
         } else {
             let def_key = self.cstore.def_key(def_id);
             (def_key.disambiguated_data.data.get_opt_name().unwrap(),
              Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
         };
 
-        let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name));
+        let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol());
         let module =
             self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
         self.extern_module_map.insert((def_id, macros_only), module);
@@ -622,7 +624,7 @@ impl<'a> Resolver<'a> {
         let legacy_imports = self.legacy_macro_imports(&item.attrs);
         let mut used = legacy_imports != LegacyMacroImports::default();
 
-        // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root.
+        // `#[macro_use]` is only allowed at the crate root.
         if self.current_module.parent.is_some() && used {
             span_err!(self.session, item.span, E0468,
                       "an `extern crate` loading macros must be at the crate root");
@@ -670,17 +672,6 @@ impl<'a> Resolver<'a> {
                 }
             }
         }
-        for (name, span) in legacy_imports.reexports {
-            self.cstore.export_macros_untracked(module.def_id().unwrap().krate);
-            let ident = Ident::with_empty_ctxt(name);
-            let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
-            if let Ok(binding) = result {
-                let (def, vis) = (binding.def(), binding.vis);
-                self.macro_exports.push(Export { ident, def, vis, span, is_import: true });
-            } else {
-                span_err!(self.session, span, E0470, "re-exported macro not found");
-            }
-        }
         used
     }
 
@@ -715,28 +706,13 @@ impl<'a> Resolver<'a> {
                 match attr.meta_item_list() {
                     Some(names) => for attr in names {
                         if let Some(word) = attr.word() {
-                            imports.imports.push((word.ident.name, attr.span()));
+                            imports.imports.push((word.name(), attr.span()));
                         } else {
                             span_err!(self.session, attr.span(), E0466, "bad macro import");
                         }
                     },
                     None => imports.import_all = Some(attr.span),
                 }
-            } else if attr.check_name("macro_reexport") {
-                let bad_macro_reexport = |this: &mut Self, span| {
-                    span_err!(this.session, span, E0467, "bad macro re-export");
-                };
-                if let Some(names) = attr.meta_item_list() {
-                    for attr in names {
-                        if let Some(word) = attr.word() {
-                            imports.reexports.push((word.ident.name, attr.span()));
-                        } else {
-                            bad_macro_reexport(self, attr.span());
-                        }
-                    }
-                } else {
-                    bad_macro_reexport(self, attr.span());
-                }
             }
         }
         imports
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index a0fc5533f8e..232a32deb86 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1395,35 +1395,6 @@ If you would like to import all exported macros, write `macro_use` with no
 arguments.
 "##,
 
-E0467: r##"
-Macro re-export declarations were empty or malformed.
-
-Erroneous code examples:
-
-```compile_fail,E0467
-#[macro_reexport]                    // error: no macros listed for export
-extern crate core as macros_for_good;
-
-#[macro_reexport(fun_macro = "foo")] // error: not a macro identifier
-extern crate core as other_macros_for_good;
-```
-
-This is a syntax error at the level of attribute declarations.
-
-Currently, `macro_reexport` requires at least one macro name to be listed.
-Unlike `macro_use`, listing no names does not re-export all macros from the
-given crate.
-
-Decide which macros you would like to export and list them properly.
-
-These are proper re-export declarations:
-
-```ignore (cannot-doctest-multicrate-project)
-#[macro_reexport(some_macro, another_macro)]
-extern crate macros_for_good;
-```
-"##,
-
 E0468: r##"
 A non-root module attempts to import macros from another crate.
 
@@ -1496,48 +1467,6 @@ extern crate some_crate; //ok!
 ```
 "##,
 
-E0470: r##"
-A macro listed for re-export was not found.
-
-Erroneous code example:
-
-```compile_fail,E0470
-#[macro_reexport(drink, be_merry)]
-extern crate alloc;
-
-fn main() {
-    // ...
-}
-```
-
-Either the listed macro is not contained in the imported crate, or it is not
-exported from the given crate.
-
-This could be caused by a typo. Did you misspell the macro's name?
-
-Double-check the names of the macros listed for re-export, and that the crate
-in question exports them.
-
-A working version:
-
-```ignore (cannot-doctest-multicrate-project)
-// In some_crate crate:
-#[macro_export]
-macro_rules! eat {
-    ...
-}
-
-#[macro_export]
-macro_rules! drink {
-    ...
-}
-
-// In your_crate:
-#[macro_reexport(eat, drink)]
-extern crate some_crate;
-```
-"##,
-
 E0530: r##"
 A binding shadowed something it shouldn't.
 
@@ -1715,6 +1644,8 @@ register_diagnostics! {
 //  E0421, merged into 531
     E0531, // unresolved pattern path kind `name`
 //  E0427, merged into 530
+//  E0467, removed
+//  E0470, removed
     E0573,
     E0574,
     E0575,
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 127331152c1..d4b212a15d8 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -700,7 +700,7 @@ pub enum Namespace {
 pub struct PerNS<T> {
     value_ns: T,
     type_ns: T,
-    macro_ns: Option<T>,
+    macro_ns: T,
 }
 
 impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
@@ -709,7 +709,7 @@ impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
         match ns {
             ValueNS => &self.value_ns,
             TypeNS => &self.type_ns,
-            MacroNS => self.macro_ns.as_ref().unwrap(),
+            MacroNS => &self.macro_ns,
         }
     }
 }
@@ -719,7 +719,7 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
         match ns {
             ValueNS => &mut self.value_ns,
             TypeNS => &mut self.type_ns,
-            MacroNS => self.macro_ns.as_mut().unwrap(),
+            MacroNS => &mut self.macro_ns,
         }
     }
 }
@@ -1407,6 +1407,7 @@ pub struct Resolver<'a> {
     graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
+    extern_prelude: FxHashSet<Name>,
 
     /// n.b. This is used only for better diagnostics, not name resolution itself.
     has_self: FxHashSet<DefId>,
@@ -1715,6 +1716,7 @@ impl<'a> Resolver<'a> {
             // AST.
             graph_root,
             prelude: None,
+            extern_prelude: session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(),
 
             has_self: FxHashSet(),
             field_names: FxHashMap(),
@@ -1726,7 +1728,7 @@ impl<'a> Resolver<'a> {
             ribs: PerNS {
                 value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
                 type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
-                macro_ns: Some(vec![Rib::new(ModuleRibKind(graph_root))]),
+                macro_ns: vec![Rib::new(ModuleRibKind(graph_root))],
             },
             label_ribs: Vec::new(),
 
@@ -1806,14 +1808,11 @@ impl<'a> Resolver<'a> {
     }
 
     /// Runs the function on each namespace.
-    fn per_ns<T, F: FnMut(&mut Self, Namespace) -> T>(&mut self, mut f: F) -> PerNS<T> {
-        PerNS {
-            type_ns: f(self, TypeNS),
-            value_ns: f(self, ValueNS),
-            macro_ns: match self.use_extern_macros {
-                true => Some(f(self, MacroNS)),
-                false => None,
-            },
+    fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
+        f(self, TypeNS);
+        f(self, ValueNS);
+        if self.use_extern_macros {
+            f(self, MacroNS);
         }
     }
 
@@ -1970,13 +1969,32 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        match self.prelude {
-            Some(prelude) if !module.no_implicit_prelude => {
-                self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span)
-                    .ok().map(LexicalScopeBinding::Item)
+        if !module.no_implicit_prelude {
+            // `record_used` means that we don't try to load crates during speculative resolution
+            if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
+                if !self.session.features_untracked().extern_prelude {
+                    feature_err(&self.session.parse_sess, "extern_prelude",
+                                ident.span, GateIssue::Language,
+                                "access to extern crates through prelude is experimental").emit();
+                }
+
+                let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
+                let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+                self.populate_module_if_necessary(crate_root);
+
+                let binding = (crate_root, ty::Visibility::Public,
+                               ident.span, Mark::root()).to_name_binding(self.arenas);
+                return Some(LexicalScopeBinding::Item(binding));
+            }
+            if let Some(prelude) = self.prelude {
+                if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
+                                                                        false, false, path_span) {
+                    return Some(LexicalScopeBinding::Item(binding));
+                }
             }
-            _ => None,
         }
+
+        None
     }
 
     fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
@@ -3587,8 +3605,9 @@ impl<'a> Resolver<'a> {
                         // We can see through blocks
                     } else {
                         // Items from the prelude
-                        if let Some(prelude) = self.prelude {
-                            if !module.no_implicit_prelude {
+                        if !module.no_implicit_prelude {
+                            names.extend(self.extern_prelude.iter().cloned());
+                            if let Some(prelude) = self.prelude {
                                 add_module_candidates(prelude, &mut names);
                             }
                         }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index af1e17cd89c..4afc621ad8b 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -206,10 +206,10 @@ impl<'a> base::Resolver for Resolver<'a> {
     }
 
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
-    fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
+    fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_derive: bool)
                               -> Option<ast::Attribute> {
         for i in 0..attrs.len() {
-            let name = unwrap_or!(attrs[i].name(), continue);
+            let name = attrs[i].name();
 
             if self.session.plugin_attributes.borrow().iter()
                     .any(|&(ref attr_nm, _)| name == &**attr_nm) {
@@ -227,9 +227,11 @@ impl<'a> base::Resolver for Resolver<'a> {
             }
         }
 
+        if !allow_derive { return None }
+
         // Check for legacy derives
         for i in 0..attrs.len() {
-            let name = unwrap_or!(attrs[i].name(), continue);
+            let name = attrs[i].name();
 
             if name == "derive" {
                 let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
@@ -397,7 +399,7 @@ impl<'a> Resolver<'a> {
 
     fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                             -> Result<Def, Determinacy> {
-        if path.segments.len() > 1 {
+        if kind != MacroKind::Bang && path.segments.len() > 1 {
             if !self.session.features_untracked().proc_macro_path_invoc {
                 emit_feature_err(
                     &self.session.parse_sess,
@@ -409,6 +411,7 @@ impl<'a> Resolver<'a> {
                 );
             }
         }
+
         let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
         if def != Err(Determinacy::Undetermined) {
             // Do not report duplicated errors on every undetermined resolution.
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index e2a7f5668d2..17aa510b565 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -33,7 +33,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
 
 use std::cell::{Cell, RefCell};
-use std::mem;
+use std::{mem, ptr};
 
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
@@ -89,6 +89,8 @@ enum SingleImports<'a> {
     None,
     /// Only the given single import can define the name in the namespace.
     MaybeOne(&'a ImportDirective<'a>),
+    /// Only one of these two single imports can define the name in the namespace.
+    MaybeTwo(&'a ImportDirective<'a>, &'a ImportDirective<'a>),
     /// At least one single import will define the name in the namespace.
     AtLeastOne,
 }
@@ -101,21 +103,28 @@ impl<'a> Default for SingleImports<'a> {
 }
 
 impl<'a> SingleImports<'a> {
-    fn add_directive(&mut self, directive: &'a ImportDirective<'a>) {
+    fn add_directive(&mut self, directive: &'a ImportDirective<'a>, use_extern_macros: bool) {
         match *self {
             SingleImports::None => *self = SingleImports::MaybeOne(directive),
-            // If two single imports can define the name in the namespace, we can assume that at
-            // least one of them will define it since otherwise both would have to define only one
-            // namespace, leading to a duplicate error.
-            SingleImports::MaybeOne(_) => *self = SingleImports::AtLeastOne,
+            SingleImports::MaybeOne(directive_one) => *self = if use_extern_macros {
+                SingleImports::MaybeTwo(directive_one, directive)
+            } else {
+                SingleImports::AtLeastOne
+            },
+            // If three single imports can define the name in the namespace, we can assume that at
+            // least one of them will define it since otherwise we'd get duplicate errors in one of
+            // other namespaces.
+            SingleImports::MaybeTwo(..) => *self = SingleImports::AtLeastOne,
             SingleImports::AtLeastOne => {}
         };
     }
 
-    fn directive_failed(&mut self) {
+    fn directive_failed(&mut self, dir: &'a ImportDirective<'a>) {
         match *self {
             SingleImports::None => unreachable!(),
             SingleImports::MaybeOne(_) => *self = SingleImports::None,
+            SingleImports::MaybeTwo(dir1, dir2) =>
+                *self = SingleImports::MaybeOne(if ptr::eq(dir1, dir) { dir1 } else { dir2 }),
             SingleImports::AtLeastOne => {}
         }
     }
@@ -199,23 +208,50 @@ impl<'a> Resolver<'a> {
         }
 
         // Check if a single import can still define the name.
+        let resolve_single_import = |this: &mut Self, directive: &'a ImportDirective<'a>| {
+            let module = match directive.imported_module.get() {
+                Some(module) => module,
+                None => return false,
+            };
+            let ident = match directive.subclass {
+                SingleImport { source, .. } => source,
+                _ => unreachable!(),
+            };
+            match this.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
+                Err(Determined) => {}
+                _ => return false,
+            }
+            true
+        };
         match resolution.single_imports {
             SingleImports::AtLeastOne => return Err(Undetermined),
-            SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
-                let module = match directive.imported_module.get() {
-                    Some(module) => module,
-                    None => return Err(Undetermined),
-                };
-                let ident = match directive.subclass {
-                    SingleImport { source, .. } => source,
-                    _ => unreachable!(),
-                };
-                match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
-                    Err(Determined) => {}
-                    _ => return Err(Undetermined),
+            SingleImports::MaybeOne(directive) => {
+                let accessible = self.is_accessible(directive.vis.get());
+                if accessible {
+                    if !resolve_single_import(self, directive) {
+                        return Err(Undetermined)
+                    }
+                }
+            }
+            SingleImports::MaybeTwo(directive1, directive2) => {
+                let accessible1 = self.is_accessible(directive1.vis.get());
+                let accessible2 = self.is_accessible(directive2.vis.get());
+                if accessible1 && accessible2 {
+                    if !resolve_single_import(self, directive1) &&
+                       !resolve_single_import(self, directive2) {
+                        return Err(Undetermined)
+                    }
+                } else if accessible1 {
+                    if !resolve_single_import(self, directive1) {
+                        return Err(Undetermined)
+                    }
+                } else {
+                    if !resolve_single_import(self, directive2) {
+                        return Err(Undetermined)
+                    }
                 }
             }
-            SingleImports::MaybeOne(_) | SingleImports::None => {},
+            SingleImports::None => {},
         }
 
         let no_unresolved_invocations =
@@ -281,7 +317,7 @@ impl<'a> Resolver<'a> {
             SingleImport { target, .. } => {
                 self.per_ns(|this, ns| {
                     let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
-                    resolution.single_imports.add_directive(directive);
+                    resolution.single_imports.add_directive(directive, this.use_extern_macros);
                 });
             }
             // We don't add prelude imports to the globs since they only affect lexical scopes,
@@ -575,7 +611,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 Err(Undetermined) => indeterminate = true,
                 Err(Determined) => {
                     this.update_resolution(parent, target, ns, |_, resolution| {
-                        resolution.single_imports.directive_failed()
+                        resolution.single_imports.directive_failed(directive)
                     });
                 }
                 Ok(binding) if !binding.is_importable() => {
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 18dd04c0ee8..fd1f779f9ec 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -14,7 +14,7 @@ pub use self::Primitive::*;
 use spec::Target;
 
 use std::cmp;
-use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive};
+use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
 pub mod call;
 
@@ -326,9 +326,9 @@ impl AddAssign for Size {
 }
 
 /// Alignment of a type in bytes, both ABI-mandated and preferred.
-/// Each field is a power of two, giving the alignment a maximum value of
-/// 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a i32,
-/// with a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
+/// Each field is a power of two, giving the alignment a maximum value
+/// of 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a
+/// maximum capacity of 2<sup>29</sup> or 536870912.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct Align {
     abi_pow2: u8,
@@ -356,7 +356,7 @@ impl Align {
             }
             if bytes != 1 {
                 Err(format!("`{}` is not a power of 2", align))
-            } else if pow > 30 {
+            } else if pow > 29 {
                 Err(format!("`{}` is too large", align))
             } else {
                 Ok(pow)
@@ -544,6 +544,23 @@ impl Scalar {
             false
         }
     }
+
+    /// Returns the valid range as a `x..y` range.
+    ///
+    /// If `x` and `y` are equal, the range is full, not empty.
+    pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: C) -> Range<u128> {
+        // For a (max) value of -1, max will be `-1 as usize`, which overflows.
+        // However, that is fine here (it would still represent the full range),
+        // i.e., if the range is everything.
+        let bits = self.value.size(cx).bits();
+        assert!(bits <= 128);
+        let mask = !0u128 >> (128 - bits);
+        let start = *self.valid_range.start();
+        let end = *self.valid_range.end();
+        assert_eq!(start, start & mask);
+        assert_eq!(end, end & mask);
+        start..(end.wrapping_add(1) & mask)
+    }
 }
 
 /// Describes how the fields of a type are located in memory.
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index 8f491157439..45f2ee13bbd 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -29,6 +29,7 @@
 #![feature(const_fn)]
 #![feature(fs_read_write)]
 #![feature(inclusive_range)]
+#![feature(inclusive_range_methods)]
 #![feature(slice_patterns)]
 
 #[macro_use]
diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
index acbbab313fe..46bb01e7c42 100644
--- a/src/librustc_target/spec/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_ios_base.rs
@@ -98,6 +98,7 @@ pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
         executables: true,
         pre_link_args,
         has_elf_tls: false,
+        eliminate_frame_pointer: false,
         // The following line is a workaround for jemalloc 4.5 being broken on
         // ios. jemalloc 5.0 is supposed to fix this.
         // see https://github.com/rust-lang/rust/issues/45262
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
new file mode 100644
index 00000000000..2d4e95ab01d
--- /dev/null
+++ b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
@@ -0,0 +1,38 @@
+// Copyright 2018 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 spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let base = super::linux_musl_base::opts();
+    Ok(Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and LLVM
+        // doesn't support the "musleabihf" value.
+        llvm_target: "armv5te-unknown-linux-gnueabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+
+        options: TargetOptions {
+            features: "+soft-float,+strict-align".to_string(),
+            // Atomic operations provided by compiler-builtins
+            max_atomic_width: Some(32),
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            .. base
+        }
+    })
+}
diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index 06ea1e4649b..d17789dfcc0 100644
--- a/src/librustc_target/spec/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -16,6 +16,7 @@ pub fn target() -> TargetResult {
     base.max_atomic_width = Some(64);
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
     base.stack_probes = true;
+    base.eliminate_frame_pointer = false;
 
     Ok(Target {
         llvm_target: "i686-apple-darwin".to_string(),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 1e94f037885..48e771e0aaf 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -283,6 +283,7 @@ supported_targets! {
     ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
     ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi),
     ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi),
+    ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi),
     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
     ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 5f4daf0d568..ba31ce2692f 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -193,14 +193,38 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
-        ty::TyGenerator(def_id, substs, _) => {
-            // Note that the interior types are ignored here.
-            // Any type reachable inside the interior must also be reachable
-            // through the upvars.
-            substs
-                .upvar_tys(def_id, tcx)
-                .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
-                .collect()
+        ty::TyGenerator(def_id, substs, _interior) => {
+            // rust-lang/rust#49918: types can be constructed, stored
+            // in the interior, and sit idle when generator yields
+            // (and is subsequently dropped).
+            //
+            // It would be nice to descend into interior of a
+            // generator to determine what effects dropping it might
+            // have (by looking at any drop effects associated with
+            // its interior).
+            //
+            // However, the interior's representation uses things like
+            // TyGeneratorWitness that explicitly assume they are not
+            // traversed in such a manner. So instead, we will
+            // simplify things for now by treating all generators as
+            // if they were like trait objects, where its upvars must
+            // all be alive for the generator's (potential)
+            // destructor.
+            //
+            // In particular, skipping over `_interior` is safe
+            // because any side-effects from dropping `_interior` can
+            // only take place through references with lifetimes
+            // derived from lifetimes attached to the upvars, and we
+            // *do* incorporate the upvars here.
+
+            let constraint = DtorckConstraint {
+                outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(),
+                dtorck_types: vec![],
+                overflows: vec![],
+            };
+            debug!("dtorck_constraint: generator {:?} => {:?}", def_id, constraint);
+
+            Ok(constraint)
         }
 
         ty::TyAdt(def, substs) => {
diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs
new file mode 100644
index 00000000000..21259bbcd38
--- /dev/null
+++ b/src/librustc_traits/evaluate_obligation.rs
@@ -0,0 +1,35 @@
+// Copyright 2018 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 rustc::traits::{EvaluationResult, Obligation, ObligationCause,
+                    OverflowError, SelectionContext, TraitQueryMode};
+use rustc::traits::query::CanonicalPredicateGoal;
+use rustc::ty::{ParamEnvAnd, TyCtxt};
+use syntax::codemap::DUMMY_SP;
+
+crate fn evaluate_obligation<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    goal: CanonicalPredicateGoal<'tcx>,
+) -> Result<EvaluationResult, OverflowError> {
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let (
+            ParamEnvAnd {
+                param_env,
+                value: predicate,
+            },
+            _canonical_inference_vars,
+        ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
+
+        let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
+        let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+
+        selcx.evaluate_obligation_recursively(&obligation)
+    })
+}
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index 90c870096e1..7f18fac2db5 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -22,6 +22,7 @@ extern crate syntax;
 extern crate syntax_pos;
 
 mod dropck_outlives;
+mod evaluate_obligation;
 mod normalize_projection_ty;
 mod normalize_erasing_regions;
 mod util;
@@ -38,6 +39,7 @@ pub fn provide(p: &mut Providers) {
             normalize_erasing_regions::normalize_ty_after_erasing_regions,
         program_clauses_for: lowering::program_clauses_for,
         program_clauses_for_env: lowering::program_clauses_for_env,
+        evaluate_obligation: evaluate_obligation::evaluate_obligation,
         ..*p
     };
 }
diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs
index 1857df5717b..299433d479d 100644
--- a/src/librustc_traits/normalize_erasing_regions.rs
+++ b/src/librustc_traits/normalize_erasing_regions.rs
@@ -17,6 +17,8 @@ crate fn normalize_ty_after_erasing_regions<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> Ty<'tcx> {
+    debug!("normalize_ty_after_erasing_regions(goal={:#?})", goal);
+
     let ParamEnvAnd { param_env, value } = goal;
     tcx.sess.perf_stats.normalize_ty_after_erasing_regions.fetch_add(1, Ordering::Relaxed);
     tcx.infer_ctxt().enter(|infcx| {
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 32432d6cc83..a4dd02e97b2 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -21,7 +21,6 @@ rustc-demangle = "0.1.4"
 rustc_allocator = { path = "../librustc_allocator" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 483f36afe27..1838dae049a 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -265,7 +265,7 @@ pub trait FnTypeExt<'a, 'tcx> {
     fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
     fn apply_attrs_llfn(&self, llfn: ValueRef);
-    fn apply_attrs_callsite(&self, callsite: ValueRef);
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef);
 }
 
 impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
@@ -388,8 +388,8 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
                 return;
             }
 
-            if scalar.valid_range.start < scalar.valid_range.end {
-                if scalar.valid_range.start > 0 {
+            if scalar.valid_range.start() < scalar.valid_range.end() {
+                if *scalar.valid_range.start() > 0 {
                     attrs.set(ArgAttribute::NonNull);
                 }
             }
@@ -640,7 +640,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn apply_attrs_callsite(&self, callsite: ValueRef) {
+    fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
@@ -653,6 +653,24 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
             PassMode::Indirect(ref attrs) => apply(attrs),
             _ => {}
         }
+        if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
+            // If the value is a boolean, the range is 0..2 and that ultimately
+            // become 0..0 when the type becomes i1, which would be rejected
+            // by the LLVM verifier.
+            match scalar.value {
+                layout::Int(..) if !scalar.is_bool() => {
+                    let range = scalar.valid_range_exclusive(bx.cx);
+                    if range.start != range.end {
+                        // FIXME(nox): This causes very weird type errors about
+                        // SHL operators in constants in stage 2 with LLVM 3.9.
+                        if unsafe { llvm::LLVMRustVersionMajor() >= 4 } {
+                            bx.range_metadata(callsite, range);
+                        }
+                    }
+                }
+                _ => {}
+            }
+        }
         for arg in &self.args {
             if arg.pad.is_some() {
                 apply(&ArgAttributes::new());
diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs
index ffebb959ebf..871fe98ec01 100644
--- a/src/librustc_trans/allocator.rs
+++ b/src/librustc_trans/allocator.rs
@@ -11,6 +11,7 @@
 use std::ffi::CString;
 use std::ptr;
 
+use attributes;
 use libc::c_uint;
 use rustc::middle::allocator::AllocatorKind;
 use rustc::ty::TyCtxt;
@@ -67,6 +68,9 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
         if tcx.sess.target.target.options.default_hidden_visibility {
             llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
         }
+       if tcx.sess.target.target.options.requires_uwtable {
+           attributes::emit_uwtable(llfn, true);
+       }
 
         let callee = CString::new(kind.fn_name(method.name)).unwrap();
         let callee = llvm::LLVMRustGetOrInsertFunction(llmod,
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index eb5c7396ae0..5baed57092d 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -14,6 +14,7 @@ use std::ffi::{CStr, CString};
 use rustc::hir::{self, TransFnAttrFlags};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::session::Session;
 use rustc::session::config::Sanitizer;
 use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
@@ -68,8 +69,6 @@ pub fn naked(val: ValueRef, is_naked: bool) {
 }
 
 pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) {
-    // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
-    // parameter.
     if cx.sess().must_not_eliminate_frame_pointers() {
         llvm::AddFunctionAttrStringValue(
             llfn, llvm::AttributePlace::Function,
@@ -104,6 +103,18 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
         cstr("probe-stack\0"), cstr("__rust_probestack\0"));
 }
 
+pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
+    const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
+        "crt-static",
+    ];
+
+    let cmdline = sess.opts.cg.target_feature.split(',')
+        .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)));
+    sess.target.target.options.features.split(',')
+        .chain(cmdline)
+        .filter(|l| !l.is_empty())
+}
+
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
 pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
@@ -131,13 +142,16 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
         unwind(llfn, false);
     }
 
-    let features =
-        trans_fn_attrs.target_features
-        .iter()
-        .map(|f| {
-            let feature = &*f.as_str();
-            format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
-        })
+    let features = llvm_target_features(cx.tcx.sess)
+        .map(|s| s.to_string())
+        .chain(
+            trans_fn_attrs.target_features
+                .iter()
+                .map(|f| {
+                    let feature = &*f.as_str();
+                    format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+                })
+        )
         .collect::<Vec<String>>()
         .join(",");
 
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index f9a8473464d..ea3f5b40860 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -959,7 +959,11 @@ impl Linker for WasmLd {
     }
 
     fn finalize(&mut self) -> Command {
-        self.cmd.arg("--threads");
+        // There have been reports in the wild (rustwasm/wasm-bindgen#119) of
+        // using threads causing weird hangs and bugs. Disable it entirely as
+        // this isn't yet the bottleneck of compilation at all anyway.
+        self.cmd.arg("--no-threads");
+
         self.cmd.arg("-z").arg("stack-size=1048576");
 
         // FIXME we probably shouldn't pass this but instead pass an explicit
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 965a34eccb8..d8520b61d91 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -132,7 +132,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         })
         .map(|def_id| {
             let export_level = if special_runtime_crate {
-                let name = tcx.symbol_name(Instance::mono(tcx, def_id));
+                let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str();
                 // We can probably do better here by just ensuring that
                 // it has hidden visibility rather than public
                 // visibility, as this is primarily here to ensure it's
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 613a07cd269..148e3d0025c 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use attributes;
 use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
 use back::lto::{self, ModuleBuffer, ThinBuffer};
 use back::link::{self, get_linker, remove};
@@ -111,31 +112,6 @@ pub fn write_output_file(
     }
 }
 
-// On android, we by default compile for armv7 processors. This enables
-// things like double word CAS instructions (rather than emulating them)
-// which are *far* more efficient. This is obviously undesirable in some
-// cases, so if any sort of target feature is specified we don't append v7
-// to the feature list.
-//
-// On iOS only armv7 and newer are supported. So it is useful to
-// get all hardware potential via VFP3 (hardware floating point)
-// and NEON (SIMD) instructions supported by LLVM.
-// Note that without those flags various linking errors might
-// arise as some of intrinsics are converted into function calls
-// and nobody provides implementations those functions
-fn target_feature(sess: &Session) -> String {
-    let rustc_features = [
-        "crt-static",
-    ];
-    let requested_features = sess.opts.cg.target_feature.split(',');
-    let llvm_features = requested_features.filter(|f| {
-        !rustc_features.iter().any(|s| f.contains(s))
-    });
-    format!("{},{}",
-            sess.target.target.options.features,
-            llvm_features.collect::<Vec<_>>().join(","))
-}
-
 fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
     match optimize {
       config::OptLevel::No => llvm::CodeGenOptLevel::None,
@@ -203,7 +179,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
         None => &*sess.target.target.options.cpu
     };
     let cpu = CString::new(cpu.as_bytes()).unwrap();
-    let features = CString::new(target_feature(sess).as_bytes()).unwrap();
+    let features = attributes::llvm_target_features(sess)
+        .collect::<Vec<_>>()
+        .join(",");
+    let features = CString::new(features).unwrap();
     let is_pie_binary = !find_features && is_pie_binary(sess);
     let trap_unreachable = sess.target.target.options.trap_unreachable;
 
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 2323ec3ef11..b756a6695f9 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1037,7 +1037,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
                 cgus.dedup();
                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
                     output.push_str(" ");
-                    output.push_str(&cgu_name);
+                    output.push_str(&cgu_name.as_str());
 
                     let linkage_abbrev = match linkage {
                         Linkage::External => "External",
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 5849437758a..9263d9a5f5d 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -52,7 +52,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return llfn;
     }
 
-    let sym = tcx.symbol_name(instance);
+    let sym = tcx.symbol_name(instance).as_str();
     debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
 
     // Create a fn pointer with the substituted signature.
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 25ca2152b27..4a0619b2336 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -33,7 +33,7 @@ use libc::{c_uint, c_char};
 use std::iter;
 
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use syntax_pos::{Span, DUMMY_SP};
 
 pub use context::CodegenCx;
@@ -183,7 +183,7 @@ pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef {
 
 // This is a 'c-like' raw string, which differs from
 // our boxed-and-length-annotated strings.
-pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> ValueRef {
+pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef {
     unsafe {
         if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
             return llval;
@@ -208,7 +208,7 @@ pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> Value
 
 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
 // you will be kicked off fast isel. See issue #4352 for an example of this.
-pub fn C_str_slice(cx: &CodegenCx, s: InternedString) -> ValueRef {
+pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef {
     let len = s.len();
     let cs = consts::ptrcast(C_cstr(cx, s, false),
         cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 122b51dbbb7..405cb83ad4d 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -118,7 +118,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
              def_id);
 
     let ty = instance.ty(cx.tcx);
-    let sym = cx.tcx.symbol_name(instance);
+    let sym = cx.tcx.symbol_name(instance).as_str();
 
     let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
 
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 76f8be9ee98..90b2fb4b59a 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -39,7 +39,7 @@ use std::ptr;
 use std::iter;
 use std::str;
 use std::sync::Arc;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
 use abi::Abi;
 
 /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
@@ -62,7 +62,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> {
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
                                 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
     /// Cache of constant strings,
-    pub const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
+    pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, ValueRef>>,
 
     /// Reverse-direction for const ptrs cast from globals.
     /// Key is a ValueRef holding a *T,
@@ -273,7 +273,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
             let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
                 let dctx = debuginfo::CrateDebugContext::new(llmod);
                 debuginfo::metadata::compile_unit_metadata(tcx,
-                                                           codegen_unit.name(),
+                                                           &codegen_unit.name().as_str(),
                                                            &dctx);
                 Some(dctx)
             } else {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 5359e0e0405..2fc6c9d4433 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -1236,7 +1236,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                                    self.layout,
                                    self.layout.fields.offset(0),
                                    self.layout.field(cx, 0).size);
-                name.push_str(&adt.variants[niche_variants.start].name.as_str());
+                name.push_str(&adt.variants[*niche_variants.start()].name.as_str());
 
                 // Create the (singleton) list of descriptions of union members.
                 vec![
@@ -1399,7 +1399,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                     (discr.size(cx), discr.align(cx));
                 let discriminant_base_type_metadata =
                     type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
-                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
+                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str();
 
                 let name = CString::new(discriminant_name.as_bytes()).unwrap();
                 let discriminant_type_metadata = unsafe {
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 706dc3dca8a..30676b91620 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -271,7 +271,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         }
         None => {}
     };
-    if sig.output().is_never() {
+    if cx.layout_of(sig.output()).abi == ty::layout::Abi::Uninhabited {
         flags = flags | DIFlags::FlagNoReturn;
     }
 
@@ -394,7 +394,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             substs.types().zip(names).map(|(ty, name)| {
                 let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                 let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
-                let name = CString::new(name.as_bytes()).unwrap();
+                let name = CString::new(name.as_str().as_bytes()).unwrap();
                 unsafe {
                     llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index 891bf649c38..51c45de9dc2 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -47,7 +47,7 @@ pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope {
 
     let namespace_name = match def_key.disambiguated_data.data {
         DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(),
-        data => data.as_interned_str()
+        data => data.as_interned_str().as_str()
     };
 
     let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 96ed4e88471..825fac36c93 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -190,10 +190,10 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
             for path_element in cx.tcx.def_path(def_id).data {
                 output.push_str("::");
-                output.push_str(&path_element.data.as_interned_str());
+                output.push_str(&path_element.data.as_interned_str().as_str());
             }
         } else {
-            output.push_str(&cx.tcx.item_name(def_id));
+            output.push_str(&cx.tcx.item_name(def_id).as_str());
         }
     }
 
diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs
index bbe4e18b18c..97721ffbf06 100644
--- a/src/librustc_trans/declare.rs
+++ b/src/librustc_trans/declare.rs
@@ -23,6 +23,7 @@
 use llvm::{self, ValueRef};
 use llvm::AttributePlace::Function;
 use rustc::ty::{self, Ty};
+use rustc::ty::layout::{self, LayoutOf};
 use rustc::session::config::Sanitizer;
 use rustc_target::spec::PanicStrategy;
 use abi::{Abi, FnType, FnTypeExt};
@@ -133,8 +134,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
     let fty = FnType::new(cx, sig, &[]);
     let llfn = declare_raw_fn(cx, name, fty.llvm_cconv(), fty.llvm_type(cx));
 
-    // FIXME(canndrew): This is_never should really be an is_uninhabited
-    if sig.output().is_never() {
+    if cx.layout_of(sig.output()).abi == layout::Abi::Uninhabited {
         llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
     }
 
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 103b04e6f13..49a207a2d8a 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -103,7 +103,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
     let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
     let arg_tys = sig.inputs();
     let ret_ty = sig.output();
-    let name = &*tcx.item_name(def_id);
+    let name = &*tcx.item_name(def_id).as_str();
 
     let llret_ty = cx.layout_of(ret_ty).llvm_type(cx);
     let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align);
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index dab01abd335..7a152d6ded4 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -25,10 +25,11 @@
 #![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(quote)]
+#![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
-#![feature(inclusive_range_fields)]
+#![feature(inclusive_range_methods)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
@@ -42,7 +43,6 @@ extern crate rustc_mir;
 extern crate rustc_allocator;
 extern crate rustc_apfloat;
 extern crate rustc_target;
-extern crate rustc_const_math;
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_demangle;
 extern crate rustc_incremental;
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index 0fe7163da7a..9e5298eb736 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -322,7 +322,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
             debug!("cleanup_kinds: {:?}/{:?}/{:?} propagating funclet {:?}",
                    bb, data, result[bb], funclet);
 
-            for &succ in data.terminator().successors().iter() {
+            for &succ in data.terminator().successors() {
                 let kind = result[succ];
                 debug!("cleanup_kinds: propagating {:?} to {:?}/{:?}",
                        funclet, succ, kind);
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 36f03605fea..b666c2b2115 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -13,6 +13,7 @@ use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf};
 use rustc::mir;
+use rustc::mir::interpret::EvalErrorKind;
 use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode};
 use base;
 use callee;
@@ -127,7 +128,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                                            ret_bx,
                                            llblock(this, cleanup),
                                            cleanup_bundle);
-                fn_ty.apply_attrs_callsite(invokeret);
+                fn_ty.apply_attrs_callsite(&bx, invokeret);
 
                 if let Some((ret_dest, target)) = destination {
                     let ret_bx = this.build_block(target);
@@ -136,7 +137,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 }
             } else {
                 let llret = bx.call(fn_ptr, &llargs, cleanup_bundle);
-                fn_ty.apply_attrs_callsite(llret);
+                fn_ty.apply_attrs_callsite(&bx, llret);
                 if this.mir[bb].is_cleanup {
                     // Cleanup is always the cold path. Don't inline
                     // drop glue. Also, when there is a deeply-nested
@@ -311,10 +312,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 // checked operation, just a comparison with the minimum
                 // value, so we have to check for the assert message.
                 if !bx.cx.check_overflow {
-                    use rustc_const_math::ConstMathErr::Overflow;
-                    use rustc_const_math::Op::Neg;
-
-                    if let mir::AssertMessage::Math(Overflow(Neg)) = *msg {
+                    if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
                         const_cond = Some(expected);
                     }
                 }
@@ -354,7 +352,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
 
                 // Put together the arguments to the panic entry point.
                 let (lang_item, args) = match *msg {
-                    mir::AssertMessage::BoundsCheck { ref len, ref index } => {
+                    EvalErrorKind::BoundsCheck { ref len, ref index } => {
                         let len = self.trans_operand(&mut bx, len).immediate();
                         let index = self.trans_operand(&mut bx, index).immediate();
 
@@ -366,26 +364,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                         (lang_items::PanicBoundsCheckFnLangItem,
                          vec![file_line_col, index, len])
                     }
-                    mir::AssertMessage::Math(ref err) => {
-                        let msg_str = Symbol::intern(err.description()).as_str();
-                        let msg_str = C_str_slice(bx.cx, msg_str);
-                        let msg_file_line_col = C_struct(bx.cx,
-                                                     &[msg_str, filename, line, col],
-                                                     false);
-                        let msg_file_line_col = consts::addr_of(bx.cx,
-                                                                msg_file_line_col,
-                                                                align,
-                                                                "panic_loc");
-                        (lang_items::PanicFnLangItem,
-                         vec![msg_file_line_col])
-                    }
-                    mir::AssertMessage::GeneratorResumedAfterReturn |
-                    mir::AssertMessage::GeneratorResumedAfterPanic => {
-                        let str = if let mir::AssertMessage::GeneratorResumedAfterReturn = *msg {
-                            "generator resumed after completion"
-                        } else {
-                            "generator resumed after panicking"
-                        };
+                    _ => {
+                        let str = msg.description();
                         let msg_str = Symbol::intern(str).as_str();
                         let msg_str = C_str_slice(bx.cx, msg_str);
                         let msg_file_line_col = C_struct(bx.cx,
@@ -442,7 +422,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 // Handle intrinsics old trans wants Expr's for, ourselves.
                 let intrinsic = match def {
                     Some(ty::InstanceDef::Intrinsic(def_id))
-                        => Some(bx.tcx().item_name(def_id)),
+                        => Some(bx.tcx().item_name(def_id).as_str()),
                     _ => None
                 };
                 let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs
index b8b0c019ca6..79859aee64d 100644
--- a/src/librustc_trans/mir/place.rs
+++ b/src/librustc_trans/mir/place.rs
@@ -91,24 +91,15 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
         }
 
         let scalar_load_metadata = |load, scalar: &layout::Scalar| {
-            let (min, max) = (scalar.valid_range.start, scalar.valid_range.end);
-            let max_next = max.wrapping_add(1);
-            let bits = scalar.value.size(bx.cx).bits();
-            assert!(bits <= 128);
-            let mask = !0u128 >> (128 - bits);
-            // For a (max) value of -1, max will be `-1 as usize`, which overflows.
-            // However, that is fine here (it would still represent the full range),
-            // i.e., if the range is everything.  The lo==hi case would be
-            // rejected by the LLVM verifier (it would mean either an
-            // empty set, which is impossible, or the entire range of the
-            // type, which is pointless).
+            let vr = scalar.valid_range.clone();
             match scalar.value {
-                layout::Int(..) if max_next & mask != min & mask => {
-                    // llvm::ConstantRange can deal with ranges that wrap around,
-                    // so an overflow on (max + 1) is fine.
-                    bx.range_metadata(load, min..max_next);
+                layout::Int(..) => {
+                    let range = scalar.valid_range_exclusive(bx.cx);
+                    if range.start != range.end {
+                        bx.range_metadata(load, range);
+                    }
                 }
-                layout::Pointer if 0 < min && min < max => {
+                layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
                     bx.nonnull_metadata(load);
                 }
                 _ => {}
@@ -296,7 +287,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
                 ..
             } => {
                 let niche_llty = discr.layout.immediate_llvm_type(bx.cx);
-                if niche_variants.start == niche_variants.end {
+                if niche_variants.start() == niche_variants.end() {
                     // FIXME(eddyb) Check the actual primitive type here.
                     let niche_llval = if niche_start == 0 {
                         // HACK(eddyb) Using `C_null` as it works on all types.
@@ -305,13 +296,13 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
                         C_uint_big(niche_llty, niche_start)
                     };
                     bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
-                        C_uint(cast_to, niche_variants.start as u64),
+                        C_uint(cast_to, *niche_variants.start() as u64),
                         C_uint(cast_to, dataful_variant as u64))
                 } else {
                     // Rebase from niche values to discriminant values.
-                    let delta = niche_start.wrapping_sub(niche_variants.start as u128);
+                    let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
                     let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
-                    let lldiscr_max = C_uint(niche_llty, niche_variants.end as u64);
+                    let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64);
                     bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
                         bx.intcast(lldiscr, cast_to, false),
                         C_uint(cast_to, dataful_variant as u64))
@@ -361,7 +352,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
 
                     let niche = self.project_field(bx, 0);
                     let niche_llty = niche.layout.immediate_llvm_type(bx.cx);
-                    let niche_value = ((variant_index - niche_variants.start) as u128)
+                    let niche_value = ((variant_index - *niche_variants.start()) as u128)
                         .wrapping_add(niche_start);
                     // FIXME(eddyb) Check the actual primitive type here.
                     let niche_llval = if niche_value == 0 {
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index c932777402e..0cd823391b9 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -15,7 +15,6 @@ use rustc::ty::layout::{self, LayoutOf};
 use rustc::mir;
 use rustc::middle::lang_items::ExchangeMallocFnLangItem;
 use rustc_apfloat::{ieee, Float, Status, Round};
-use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
 use std::{u128, i128};
 
 use base;
@@ -301,7 +300,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                             if let layout::Int(_, s) = scalar.value {
                                 signed = s;
 
-                                if scalar.valid_range.end > scalar.valid_range.start {
+                                if scalar.valid_range.end() > scalar.valid_range.start() {
                                     // We want `table[e as usize]` to not
                                     // have bound checks, and this is the most
                                     // convenient place to put the `assume`.
@@ -309,7 +308,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                                     base::call_assume(&bx, bx.icmp(
                                         llvm::IntULE,
                                         llval,
-                                        C_uint_big(ll_t_in, scalar.valid_range.end)
+                                        C_uint_big(ll_t_in, *scalar.valid_range.end())
                                     ));
                                 }
                             }
@@ -536,7 +535,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         let is_float = input_ty.is_fp();
         let is_signed = input_ty.is_signed();
         let is_nil = input_ty.is_nil();
-        let is_bool = input_ty.is_bool();
         match op {
             mir::BinOp::Add => if is_float {
                 bx.fadd(lhs, rhs)
@@ -586,15 +584,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     lhs, rhs
                 )
             } else {
-                let (lhs, rhs) = if is_bool {
-                    // FIXME(#36856) -- extend the bools into `i8` because
-                    // LLVM's i1 comparisons are broken.
-                    (bx.zext(lhs, Type::i8(bx.cx)),
-                     bx.zext(rhs, Type::i8(bx.cx)))
-                } else {
-                    (lhs, rhs)
-                };
-
                 bx.icmp(
                     base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed),
                     lhs, rhs
@@ -815,6 +804,10 @@ fn cast_int_to_float(bx: &Builder,
     if is_u128_to_f32 {
         // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
         // and for everything else LLVM's uitofp works just fine.
+        use rustc_apfloat::ieee::Single;
+        use rustc_apfloat::Float;
+        const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
+                                            << (Single::MAX_EXP - Single::PRECISION as i16);
         let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
         let overflow = bx.icmp(llvm::IntUGE, x, max);
         let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32);
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 06d94e8d155..d19b5af2527 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -88,7 +88,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
                self.to_raw_string(),
                cx.codegen_unit.name());
 
-        let symbol_name = self.symbol_name(cx.tcx);
+        let symbol_name = self.symbol_name(cx.tcx).as_str();
 
         debug!("symbol {}", &symbol_name);
 
diff --git a/src/librustc_trans_utils/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs
index f3b7326b210..be5bff60805 100644
--- a/src/librustc_trans_utils/symbol_names.rs
+++ b/src/librustc_trans_utils/symbol_names.rs
@@ -229,7 +229,7 @@ fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
                          -> ty::SymbolName
 {
-    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() }
+    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_interned_str() }
 }
 
 fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
@@ -355,12 +355,12 @@ impl SymbolPathBuffer {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16)
         };
-        result.result.push_str(&symbol.name);
+        result.result.push_str(&symbol.name.as_str());
         result
     }
 
     fn into_interned(self) -> ty::SymbolName {
-        ty::SymbolName { name: Symbol::intern(&self.result).as_str() }
+        ty::SymbolName { name: Symbol::intern(&self.result).as_interned_str() }
     }
 
     fn finish(mut self, hash: u64) -> String {
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index 70c13e9b7d6..c426533779c 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -15,7 +15,6 @@ syntax = { path = "../libsyntax" }
 arena = { path = "../libarena" }
 fmt_macros = { path = "../libfmt_macros" }
 rustc = { path = "../librustc" }
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 6cdce127308..93dbba6e873 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -101,7 +101,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     {
         let tcx = self.tcx();
         let lifetime_name = |def_id| {
-            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_str()
+            tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_interned_str()
         };
 
         let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
@@ -981,7 +981,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 let item_def_id = tcx.hir.local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)];
-                tcx.mk_param(index, tcx.hir.name(node_id).as_str())
+                tcx.mk_param(index, tcx.hir.name(node_id).as_interned_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index a87058d1fa5..3199ff17ae9 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -120,15 +120,15 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
 
         let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
 
-        let mut selcx = traits::SelectionContext::new(self.fcx);
         let obligation = traits::Obligation::new(cause.clone(),
                                                  self.fcx.param_env,
                                                  trait_ref.to_predicate());
-        if !selcx.evaluate_obligation(&obligation) {
+        if !self.fcx.predicate_may_hold(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
             return None;
         }
 
+        let mut selcx = traits::SelectionContext::new(self.fcx);
         let normalized = traits::normalize_projection_type(&mut selcx,
                                                            self.fcx.param_env,
                                                            ty::ProjectionTy::from_ref_and_name(
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index c9e53fa7674..91264849cad 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -732,8 +732,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if impl_ty.synthetic != trait_ty.synthetic {
             let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
             let impl_span = tcx.hir.span(impl_node_id);
-            let trait_node_id = tcx.hir.as_local_node_id(trait_ty.def_id).unwrap();
-            let trait_span = tcx.hir.span(trait_node_id);
+            let trait_span = tcx.def_span(trait_ty.def_id);
             let mut err = struct_span_err!(tcx.sess,
                                            impl_span,
                                            E0643,
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 283fbf8fecc..fcf7541a159 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_str());
+    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
     let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
@@ -341,7 +341,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                it: &hir::ForeignItem) {
     let param = |n| {
-        let name = Symbol::intern(&format!("P{}", n)).as_str();
+        let name = Symbol::intern(&format!("P{}", n)).as_interned_str();
         tcx.mk_param(n, name)
     };
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 5f55ee6163b..5f904a9419b 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -277,8 +277,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                      poly_trait_ref.to_predicate());
 
         // Now we want to know if this can be matched
-        let mut selcx = traits::SelectionContext::new(self);
-        if !selcx.evaluate_obligation(&obligation) {
+        if !self.predicate_may_hold(&obligation) {
             debug!("--> Cannot match obligation");
             return None; // Cannot be matched, no such method resolution is possible.
         }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index b41a6dcf384..907c80f0daf 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                     let predicate = trait_ref.to_predicate();
                     let obligation =
                         traits::Obligation::new(cause.clone(), self.param_env, predicate);
-                    if !selcx.evaluate_obligation(&obligation) {
+                    if !self.predicate_may_hold(&obligation) {
                         if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
                             // This candidate's primary obligation doesn't even
                             // select - don't bother registering anything in
@@ -1201,7 +1201,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             // Evaluate those obligations to see if they might possibly hold.
             for o in candidate_obligations.into_iter().chain(sub_obligations) {
                 let o = self.resolve_type_vars_if_possible(&o);
-                if !selcx.evaluate_obligation(&o) {
+                if !self.predicate_may_hold(&o) {
                     result = ProbeResult::NoMatch;
                     if let &ty::Predicate::Trait(ref pred) = &o.predicate {
                         possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref);
@@ -1485,7 +1485,10 @@ impl<'tcx> Candidate<'tcx> {
                     // inference variables or other artifacts. This
                     // means they are safe to put into the
                     // `WhereClausePick`.
-                    assert!(!trait_ref.skip_binder().substs.needs_infer());
+                    assert!(
+                        !trait_ref.skip_binder().substs.needs_infer()
+                            && !trait_ref.skip_binder().substs.has_skol()
+                    );
 
                     WhereClausePick(trait_ref.clone())
                 }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index d8907866467..2dc7c7fe71a 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -19,7 +19,7 @@ use hir::def::Def;
 use hir::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::lang_items::FnOnceTraitLangItem;
 use namespace::Namespace;
-use rustc::traits::{Obligation, SelectionContext};
+use rustc::traits::Obligation;
 use util::nodemap::FxHashSet;
 
 use syntax::ast;
@@ -65,7 +65,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                              self.body_id,
                                              self.param_env,
                                              poly_trait_ref.to_predicate());
-                        SelectionContext::new(self).evaluate_obligation(&obligation)
+                        self.predicate_may_hold(&obligation)
                     })
                 })
             }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 787df7c6479..db859e42057 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -124,7 +124,7 @@ use syntax::attr;
 use syntax::codemap::{original_sp, Spanned};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, InternedString, keywords};
+use syntax::symbol::{Symbol, LocalInternedString, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{self, BytePos, Span, MultiSpan};
 
@@ -3172,7 +3172,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // Return an hint about the closest match in field names
     fn suggest_field_name(variant: &'tcx ty::VariantDef,
                           field: &Spanned<ast::Name>,
-                          skip: Vec<InternedString>)
+                          skip: Vec<LocalInternedString>)
                           -> Option<Symbol> {
         let name = field.node.as_str();
         let names = variant.fields.iter().filter_map(|field| {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index b5e862fac95..e7e70a19e49 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -96,6 +96,7 @@ use rustc::ty::adjustment;
 
 use std::mem;
 use std::ops::Deref;
+use std::rc::Rc;
 use rustc_data_structures::sync::Lrc;
 use syntax::ast;
 use syntax_pos::Span;
@@ -513,7 +514,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
         // the adjusted form if there is an adjustment.
         match cmt_result {
             Ok(head_cmt) => {
-                self.check_safety_of_rvalue_destructor_if_necessary(head_cmt, expr.span);
+                self.check_safety_of_rvalue_destructor_if_necessary(&head_cmt, expr.span);
             }
             Err(..) => {
                 self.tcx.sess.delay_span_bug(expr.span, "cat_expr Errd");
@@ -799,7 +800,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
 
     /// Invoked on any adjustments that occur. Checks that if this is a region pointer being
     /// dereferenced, the lifetime of the pointer includes the deref expr.
-    fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt<'tcx>> {
+    fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt_<'tcx>> {
         debug!("constrain_adjustments(expr={:?})", expr);
 
         let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
@@ -814,7 +815,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
 
         // If necessary, constrain destructors in the unadjusted form of this
         // expression.
-        self.check_safety_of_rvalue_destructor_if_necessary(cmt.clone(), expr.span);
+        self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
 
         let expr_region = self.tcx.mk_region(ty::ReScope(
             region::Scope::Node(expr.hir_id.local_id)));
@@ -837,7 +838,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                 });
 
                 self.link_region(expr.span, deref.region,
-                                 ty::BorrowKind::from_mutbl(deref.mutbl), cmt.clone());
+                                 ty::BorrowKind::from_mutbl(deref.mutbl), &cmt);
 
                 // Specialized version of constrain_call.
                 self.type_must_outlive(infer::CallRcvr(expr.span),
@@ -847,7 +848,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
             }
 
             if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind {
-                self.link_autoref(expr, cmt.clone(), autoref);
+                self.link_autoref(expr, &cmt, autoref);
 
                 // Require that the resulting region encompasses
                 // the current node.
@@ -878,7 +879,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn check_safety_of_rvalue_destructor_if_necessary(&mut self,
-                                                     cmt: mc::cmt<'tcx>,
+                                                     cmt: &mc::cmt_<'tcx>,
                                                      span: Span) {
         match cmt.cat {
             Categorization::Rvalue(region) => {
@@ -980,7 +981,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
 
         debug!("link_addr_of: cmt={:?}", cmt);
 
-        self.link_region_from_node_type(expr.span, expr.hir_id, mutability, cmt);
+        self.link_region_from_node_type(expr.span, expr.hir_id, mutability, &cmt);
     }
 
     /// Computes the guarantors for any ref bindings in a `let` and
@@ -992,7 +993,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
             None => { return; }
             Some(ref expr) => &**expr,
         };
-        let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr)));
+        let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))));
         self.link_pattern(discr_cmt, &local.pat);
     }
 
@@ -1001,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     /// linked to the lifetime of its guarantor (if any).
     fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
         debug!("regionck::for_match()");
-        let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)));
+        let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))));
         debug!("discr_cmt={:?}", discr_cmt);
         for arm in arms {
             for root_pat in &arm.pats {
@@ -1019,7 +1020,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
             let arg_ty = self.node_ty(arg.hir_id);
             let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
             let arg_cmt = self.with_mc(|mc| {
-                mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty)
+                Rc::new(mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty))
             });
             debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
                    arg_ty,
@@ -1044,7 +1045,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                                                                .expect("missing binding mode");
                         if let ty::BindByReference(mutbl) = bm {
                             self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id,
-                                                            mutbl, sub_cmt);
+                                                            mutbl, &sub_cmt);
                         }
                     }
                     _ => {}
@@ -1057,15 +1058,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
     /// autoref'd.
     fn link_autoref(&self,
                     expr: &hir::Expr,
-                    expr_cmt: mc::cmt<'tcx>,
+                    expr_cmt: &mc::cmt_<'tcx>,
                     autoref: &adjustment::AutoBorrow<'tcx>)
     {
         debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt);
 
         match *autoref {
             adjustment::AutoBorrow::Ref(r, m) => {
-                self.link_region(expr.span, r,
-                                 ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
+                self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
             }
 
             adjustment::AutoBorrow::RawPtr(m) => {
@@ -1081,15 +1081,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                                   span: Span,
                                   id: hir::HirId,
                                   mutbl: hir::Mutability,
-                                  cmt_borrowed: mc::cmt<'tcx>) {
+                                  cmt_borrowed: &mc::cmt_<'tcx>) {
         debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
                id, mutbl, cmt_borrowed);
 
         let rptr_ty = self.resolve_node_type(id);
         if let ty::TyRef(r, _) = rptr_ty.sty {
             debug!("rptr_ty={}",  rptr_ty);
-            self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl),
-                             cmt_borrowed);
+            self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed);
         }
     }
 
@@ -1101,19 +1100,19 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                    span: Span,
                    borrow_region: ty::Region<'tcx>,
                    borrow_kind: ty::BorrowKind,
-                   borrow_cmt: mc::cmt<'tcx>) {
-        let mut borrow_cmt = borrow_cmt;
-        let mut borrow_kind = borrow_kind;
-
+                   borrow_cmt: &mc::cmt_<'tcx>) {
         let origin = infer::DataBorrowed(borrow_cmt.ty, span);
         self.type_must_outlive(origin, borrow_cmt.ty, borrow_region);
 
+        let mut borrow_kind = borrow_kind;
+        let mut borrow_cmt_cat = borrow_cmt.cat.clone();
+
         loop {
             debug!("link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})",
                    borrow_region,
                    borrow_kind,
                    borrow_cmt);
-            match borrow_cmt.cat.clone() {
+            match borrow_cmt_cat {
                 Categorization::Deref(ref_cmt, mc::Implicit(ref_kind, ref_region)) |
                 Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => {
                     match self.link_reborrowed_region(span,
@@ -1121,7 +1120,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                                                       ref_cmt, ref_region, ref_kind,
                                                       borrow_cmt.note) {
                         Some((c, k)) => {
-                            borrow_cmt = c;
+                            borrow_cmt_cat = c.cat.clone();
                             borrow_kind = k;
                         }
                         None => {
@@ -1135,7 +1134,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                 Categorization::Interior(cmt_base, _) => {
                     // Borrowing interior or owned data requires the base
                     // to be valid and borrowable in the same fashion.
-                    borrow_cmt = cmt_base;
+                    borrow_cmt_cat = cmt_base.cat.clone();
                     borrow_kind = borrow_kind;
                 }
 
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 4fc3344dab2..58dc5839578 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -298,7 +298,8 @@ struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
-    fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) {
+    fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'tcx>,
+                                            mode: euv::ConsumeMode) {
         debug!(
             "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})",
             cmt,
@@ -377,7 +378,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
     /// Indicates that `cmt` is being directly mutated (e.g., assigned
     /// to). If cmt contains any by-ref upvars, this implies that
     /// those upvars must be borrowed using an `&mut` borrow.
-    fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) {
+    fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) {
         debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt);
 
         match cmt.cat.clone() {
@@ -386,7 +387,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
             Categorization::Downcast(base, _) => {
                 // Interior or owned data is mutable if base is
                 // mutable, so iterate to the base.
-                self.adjust_upvar_borrow_kind_for_mut(base);
+                self.adjust_upvar_borrow_kind_for_mut(&base);
             }
 
             Categorization::Deref(base, mc::BorrowedPtr(..)) |
@@ -396,7 +397,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                     // borrowed pointer implies that the
                     // pointer itself must be unique, but not
                     // necessarily *mutable*
-                    self.adjust_upvar_borrow_kind_for_unique(base);
+                    self.adjust_upvar_borrow_kind_for_unique(&base);
                 }
             }
 
@@ -410,7 +411,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) {
+    fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) {
         debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt);
 
         match cmt.cat.clone() {
@@ -419,7 +420,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
             Categorization::Downcast(base, _) => {
                 // Interior or owned data is unique if base is
                 // unique.
-                self.adjust_upvar_borrow_kind_for_unique(base);
+                self.adjust_upvar_borrow_kind_for_unique(&base);
             }
 
             Categorization::Deref(base, mc::BorrowedPtr(..)) |
@@ -427,7 +428,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                 if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
                     // for a borrowed pointer to be unique, its
                     // base must be unique
-                    self.adjust_upvar_borrow_kind_for_unique(base);
+                    self.adjust_upvar_borrow_kind_for_unique(&base);
                 }
             }
 
@@ -439,7 +440,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn try_adjust_upvar_deref(&mut self, cmt: mc::cmt<'tcx>, borrow_kind: ty::BorrowKind) -> bool {
+    fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind)
+                              -> bool
+    {
         assert!(match borrow_kind {
             ty::MutBorrow => true,
             ty::UniqueImmBorrow => true,
@@ -581,17 +584,19 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
         &mut self,
         _consume_id: ast::NodeId,
         _consume_span: Span,
-        cmt: mc::cmt<'tcx>,
+        cmt: &mc::cmt_<'tcx>,
         mode: euv::ConsumeMode,
     ) {
         debug!("consume(cmt={:?},mode={:?})", cmt, mode);
         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
     }
 
-    fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: mc::cmt<'tcx>, _mode: euv::MatchMode) {
+    fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: &mc::cmt_<'tcx>,
+                   _mode: euv::MatchMode) {
     }
 
-    fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) {
+    fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: &mc::cmt_<'tcx>,
+                   mode: euv::ConsumeMode) {
         debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode);
         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
     }
@@ -600,7 +605,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
         &mut self,
         borrow_id: ast::NodeId,
         _borrow_span: Span,
-        cmt: mc::cmt<'tcx>,
+        cmt: &mc::cmt_<'tcx>,
         _loan_region: ty::Region<'tcx>,
         bk: ty::BorrowKind,
         _loan_cause: euv::LoanCause,
@@ -629,7 +634,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
         &mut self,
         _assignment_id: ast::NodeId,
         _assignment_span: Span,
-        assignee_cmt: mc::cmt<'tcx>,
+        assignee_cmt: &mc::cmt_<'tcx>,
         _mode: euv::MutateMode,
     ) {
         debug!("mutate(assignee_cmt={:?})", assignee_cmt);
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 9c4807bec2f..d0ff44c8e7e 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -655,7 +655,7 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
             // local so it should be okay to just unwrap everything.
             let trait_def_id = impl_params[&method_param.name];
             let trait_decl_span = tcx.def_span(trait_def_id);
-            error_194(tcx, type_span, trait_decl_span, &method_param.name[..]);
+            error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
         }
     }
 }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 6e0d7dd8508..802e5375b6b 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -107,7 +107,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) {
         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer());
+        assert!(!ty.needs_infer() && !ty.has_skol());
         self.tables.node_types_mut().insert(hir_id, ty);
     }
 
@@ -431,7 +431,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) {
             let substs = self.resolve(&substs, &span);
             debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
-            assert!(!substs.needs_infer());
+            assert!(!substs.needs_infer() && !substs.has_skol());
             self.tables.node_substs_mut().insert(hir_id, substs);
         }
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 2ebbd64cab9..1b8f2e661c3 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -244,7 +244,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_owner_def_id = tcx.hir.local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
     let index = generics.type_param_to_index[&def_id];
-    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_str());
+    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -842,7 +842,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     opt_self = Some(ty::TypeParameterDef {
                         index: 0,
-                        name: keywords::SelfType.name().as_str(),
+                        name: keywords::SelfType.name().as_interned_str(),
                         def_id: tcx.hir.local_def_id(param_id),
                         has_default: false,
                         object_lifetime_default: rl::Set1::Empty,
@@ -888,7 +888,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
     let regions = early_lifetimes.enumerate().map(|(i, l)| {
         ty::RegionParameterDef {
-            name: l.lifetime.name.name().as_str(),
+            name: l.lifetime.name.name().as_interned_str(),
             index: own_start + i as u32,
             def_id: tcx.hir.local_def_id(l.lifetime.id),
             pure_wrt_drop: l.pure_wrt_drop,
@@ -918,7 +918,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         ty::TypeParameterDef {
             index: type_start + i as u32,
-            name: p.name.as_str(),
+            name: p.name.as_interned_str(),
             def_id: tcx.hir.local_def_id(p.id),
             has_default: p.default.is_some(),
             object_lifetime_default:
@@ -937,7 +937,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure kind
         types.push(ty::TypeParameterDef {
             index: type_start,
-            name: Symbol::intern("<closure_kind>").as_str(),
+            name: Symbol::intern("<closure_kind>").as_interned_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -948,7 +948,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure signature
         types.push(ty::TypeParameterDef {
             index: type_start + 1,
-            name: Symbol::intern("<closure_signature>").as_str(),
+            name: Symbol::intern("<closure_signature>").as_interned_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -959,7 +959,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.with_freevars(node_id, |fv| {
             types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
                 index: type_start + i,
-                name: Symbol::intern("<upvar>").as_str(),
+                name: Symbol::intern("<upvar>").as_interned_str(),
                 def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
@@ -1429,7 +1429,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: tcx.hir.local_def_id(param.lifetime.id),
             index,
-            name: param.lifetime.name.name().as_str(),
+            name: param.lifetime.name.name().as_interned_str(),
         }));
         index += 1;
 
@@ -1443,7 +1443,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Collect the predicates that were written inline by the user on each
     // type parameter (e.g., `<T:Foo>`).
     for param in ast_generics.ty_params() {
-        let param_ty = ty::ParamTy::new(index, param.name.as_str()).to_ty(tcx);
+        let param_ty = ty::ParamTy::new(index, param.name.as_interned_str()).to_ty(tcx);
         index += 1;
 
         let bounds = compute_bounds(&icx,
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 23fe91ffdeb..350b53a406b 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -71,6 +71,8 @@ This API is completely unstable and subject to change.
 
 #![allow(non_camel_case_types)]
 
+#![cfg_attr(stage0, feature(dyn_trait))]
+
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
@@ -81,7 +83,6 @@ This API is completely unstable and subject to change.
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(slice_sort_by_cached_key)]
-#![feature(dyn_trait)]
 #![feature(never_type)]
 
 #[macro_use] extern crate log;
@@ -91,7 +92,6 @@ extern crate syntax_pos;
 extern crate arena;
 #[macro_use] extern crate rustc;
 extern crate rustc_platform_intrinsics as intrinsics;
-extern crate rustc_const_math;
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
 extern crate rustc_target;
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 477b576ad21..221fc4dab72 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -224,7 +224,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                     let name = if p.name == "" {
                         hir::LifetimeName::Static
                     } else {
-                        hir::LifetimeName::Name(Symbol::intern(&p.name))
+                        hir::LifetimeName::Name(p.name.as_symbol())
                     };
 
                     hir::Lifetime {
@@ -261,7 +261,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                     span: DUMMY_SP,
                     def: Def::TyParam(param.def_id),
                     segments: HirVec::from_vec(vec![
-                        hir::PathSegment::from_name(Symbol::intern(&param.name))
+                        hir::PathSegment::from_name(param.name.as_symbol())
                     ]),
                 }),
             )),
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 7f89b3e6b3a..d5e0f95ddf4 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -67,7 +67,7 @@ impl Cfg {
     /// If the content is not properly formatted, it will return an error indicating what and where
     /// the error is.
     pub fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
-        let name = cfg.ident.name;
+        let name = cfg.name();
         match cfg.node {
             MetaItemKind::Word => Ok(Cfg::Cfg(name, None)),
             MetaItemKind::NameValue(ref lit) => match lit.node {
@@ -436,6 +436,42 @@ mod test {
         Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value)))
     }
 
+    fn dummy_meta_item_word(name: &str) -> MetaItem {
+        MetaItem {
+            ident: Path::from_ident(Ident::from_str(name)),
+            node: MetaItemKind::Word,
+            span: DUMMY_SP,
+        }
+    }
+
+    macro_rules! dummy_meta_item_list {
+        ($name:ident, [$($list:ident),* $(,)*]) => {
+            MetaItem {
+                ident: Path::from_ident(Ident::from_str(stringify!($name))),
+                node: MetaItemKind::List(vec![
+                    $(
+                        dummy_spanned(NestedMetaItemKind::MetaItem(
+                            dummy_meta_item_word(stringify!($list)),
+                        )),
+                    )*
+                ]),
+                span: DUMMY_SP,
+            }
+        };
+
+        ($name:ident, [$($list:expr),* $(,)*]) => {
+            MetaItem {
+                ident: Path::from_ident(Ident::from_str(stringify!($name))),
+                node: MetaItemKind::List(vec![
+                    $(
+                        dummy_spanned(NestedMetaItemKind::MetaItem($list)),
+                    )*
+                ]),
+                span: DUMMY_SP,
+            }
+        };
+    }
+
     #[test]
     fn test_cfg_not() {
         with_globals(|| {
@@ -561,15 +597,11 @@ mod test {
     #[test]
     fn test_parse_ok() {
         with_globals(|| {
-            let mi = MetaItem {
-                ident: Ident::from_str("all"),
-                node: MetaItemKind::Word,
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_word("all");
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
 
             let mi = MetaItem {
-                ident: Ident::from_str("all"),
+                ident: Path::from_ident(Ident::from_str("all")),
                 node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str(
                     Symbol::intern("done"),
                     StrStyle::Cooked,
@@ -578,111 +610,24 @@ mod test {
             };
             assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
 
-            let mi = MetaItem {
-                ident: Ident::from_str("all"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("b"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(all, [a, b]);
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b")));
 
-            let mi = MetaItem {
-                ident: Ident::from_str("any"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("b"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(any, [a, b]);
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b")));
 
-            let mi = MetaItem {
-                ident: Ident::from_str("not"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(not, [a]);
             assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a")));
 
-            let mi = MetaItem {
-                ident: Ident::from_str("not"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("any"),
-                        node: MetaItemKind::List(vec![
-                            dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                ident: Ident::from_str("a"),
-                                node: MetaItemKind::Word,
-                                span: DUMMY_SP,
-                            })),
-                            dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                ident: Ident::from_str("all"),
-                                node: MetaItemKind::List(vec![
-                                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                        ident: Ident::from_str("b"),
-                                        node: MetaItemKind::Word,
-                                        span: DUMMY_SP,
-                                    })),
-                                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                        ident: Ident::from_str("c"),
-                                        node: MetaItemKind::Word,
-                                        span: DUMMY_SP,
-                                    })),
-                                ]),
-                                span: DUMMY_SP,
-                            })),
-                        ]),
-                        span: DUMMY_SP,
-                    })),
+            let mi = dummy_meta_item_list!(not, [
+                dummy_meta_item_list!(any, [
+                    dummy_meta_item_word("a"),
+                    dummy_meta_item_list!(all, [b, c]),
                 ]),
-                span: DUMMY_SP,
-            };
+            ]);
             assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c")))));
 
-            let mi = MetaItem {
-                ident: Ident::from_str("all"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("b"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("c"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(all, [a, b, c]);
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c")));
         })
     }
@@ -691,97 +636,36 @@ mod test {
     fn test_parse_err() {
         with_globals(|| {
             let mi = MetaItem {
-                ident: Ident::from_str("foo"),
+                ident: Path::from_ident(Ident::from_str("foo")),
                 node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))),
                 span: DUMMY_SP,
             };
             assert!(Cfg::parse(&mi).is_err());
 
-            let mi = MetaItem {
-                ident: Ident::from_str("not"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("b"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(not, [a, b]);
             assert!(Cfg::parse(&mi).is_err());
 
-            let mi = MetaItem {
-                ident: Ident::from_str("not"),
-                node: MetaItemKind::List(vec![]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(not, []);
             assert!(Cfg::parse(&mi).is_err());
 
-            let mi = MetaItem {
-                ident: Ident::from_str("foo"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(foo, []);
             assert!(Cfg::parse(&mi).is_err());
 
-            let mi = MetaItem {
-                ident: Ident::from_str("all"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("foo"),
-                        node: MetaItemKind::List(vec![]),
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("b"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(all, [
+                dummy_meta_item_list!(foo, []),
+                dummy_meta_item_word("b"),
+            ]);
             assert!(Cfg::parse(&mi).is_err());
 
-            let mi = MetaItem {
-                ident: Ident::from_str("any"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("a"),
-                        node: MetaItemKind::Word,
-                        span: DUMMY_SP,
-                    })),
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("foo"),
-                        node: MetaItemKind::List(vec![]),
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(any, [
+                dummy_meta_item_word("a"),
+                dummy_meta_item_list!(foo, []),
+            ]);
             assert!(Cfg::parse(&mi).is_err());
 
-            let mi = MetaItem {
-                ident: Ident::from_str("not"),
-                node: MetaItemKind::List(vec![
-                    dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        ident: Ident::from_str("foo"),
-                        node: MetaItemKind::List(vec![]),
-                        span: DUMMY_SP,
-                    })),
-                ]),
-                span: DUMMY_SP,
-            };
+            let mi = dummy_meta_item_list!(not, [
+                dummy_meta_item_list!(foo, []),
+            ]);
             assert!(Cfg::parse(&mi).is_err());
         })
     }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fb05cbfe32c..edbf5f3abd2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1367,7 +1367,7 @@ impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
         let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, &cx.tcx.item_name(did),
+        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
             Some(did), false, vec![], empty);
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
         TraitBound(PolyTrait {
@@ -1474,7 +1474,7 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         let (trait_ref, ref bounds) = *self;
         inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
-        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id),
+        let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
                                  Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
@@ -1755,8 +1755,18 @@ pub struct Generics {
 
 impl Clean<Generics> for hir::Generics {
     fn clean(&self, cx: &DocContext) -> Generics {
+        let mut params = Vec::with_capacity(self.params.len());
+        for p in &self.params {
+            let p = p.clean(cx);
+            if let GenericParam::Type(ref tp) = p {
+                if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
+                    cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone());
+                }
+            }
+            params.push(p);
+        }
         let mut g = Generics {
-            params: self.params.clean(cx),
+            params,
             where_predicates: self.where_clause.predicates.clean(cx)
         };
 
@@ -1869,9 +1879,11 @@ pub struct Method {
 
 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
     fn clean(&self, cx: &DocContext) -> Method {
-        let generics = self.1.clean(cx);
+        let (generics, decl) = enter_impl_trait(cx, || {
+            (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
+        });
         Method {
-            decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)),
+            decl,
             generics,
             unsafety: self.0.unsafety,
             constness: self.0.constness,
@@ -1899,8 +1911,9 @@ pub struct Function {
 
 impl Clean<Item> for doctree::Function {
     fn clean(&self, cx: &DocContext) -> Item {
-        let generics = self.generics.clean(cx);
-        let decl = enter_impl_trait(cx, &generics.params, || (&self.decl, self.body).clean(cx));
+        let (generics, decl) = enter_impl_trait(cx, || {
+            (self.generics.clean(cx), (&self.decl, self.body).clean(cx))
+        });
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -2139,12 +2152,12 @@ impl Clean<Item> for hir::TraitItem {
                 MethodItem((sig, &self.generics, body).clean(cx))
             }
             hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
-                let generics = self.generics.clean(cx);
+                let (generics, decl) = enter_impl_trait(cx, || {
+                    (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
+                });
                 TyMethodItem(TyMethod {
                     unsafety: sig.unsafety.clone(),
-                    decl: enter_impl_trait(cx, &generics.params, || {
-                        (&*sig.decl, &names[..]).clean(cx)
-                    }),
+                    decl,
                     generics,
                     abi: sig.abi
                 })
@@ -2801,7 +2814,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     AdtKind::Enum => TypeKind::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, &cx.tcx.item_name(did),
+                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], substs);
                 ResolvedPath {
                     path,
@@ -2812,7 +2825,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             }
             ty::TyForeign(did) => {
                 inline::record_extern_fqn(cx, did, TypeKind::Foreign);
-                let path = external_path(cx, &cx.tcx.item_name(did),
+                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], Substs::empty());
                 ResolvedPath {
                     path: path,
@@ -2830,7 +2843,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
                     for did in obj.auto_traits() {
                         let empty = cx.tcx.intern_substs(&[]);
-                        let path = external_path(cx, &cx.tcx.item_name(did),
+                        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                             Some(did), false, vec![], empty);
                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
                         let bound = TraitBound(PolyTrait {
@@ -2853,7 +2866,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                         });
                     }
 
-                    let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
+                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
                         false, bindings, principal.skip_binder().substs);
                     ResolvedPath {
                         path,
@@ -3415,12 +3428,12 @@ pub struct BareFunctionDecl {
 
 impl Clean<BareFunctionDecl> for hir::BareFnTy {
     fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
-        let generic_params = self.generic_params.clean(cx);
+        let (generic_params, decl) = enter_impl_trait(cx, || {
+            (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx))
+        });
         BareFunctionDecl {
             unsafety: self.unsafety,
-            decl: enter_impl_trait(cx, &generic_params, || {
-                (&*self.decl, &self.arg_names[..]).clean(cx)
-            }),
+            decl,
             generic_params,
             abi: self.abi,
         }
@@ -3661,7 +3674,7 @@ impl Clean<Vec<Item>> for doctree::Import {
         // #[doc(no_inline)] attribute is present.
         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
         let denied = self.vis != hir::Public || self.attrs.iter().any(|a| {
-            a.name().unwrap() == "doc" && match a.meta_item_list() {
+            a.name() == "doc" && match a.meta_item_list() {
                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
                            attr::list_contains_name(&l, "hidden"),
                 None => false,
@@ -3722,11 +3735,11 @@ impl Clean<Item> for hir::ForeignItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
             hir::ForeignItemFn(ref decl, ref names, ref generics) => {
-                let generics = generics.clean(cx);
+                let (generics, decl) = enter_impl_trait(cx, || {
+                    (generics.clean(cx), (&**decl, &names[..]).clean(cx))
+                });
                 ForeignFunctionItem(Function {
-                    decl: enter_impl_trait(cx, &generics.params, || {
-                        (&**decl, &names[..]).clean(cx)
-                    }),
+                    decl,
                     generics,
                     unsafety: hir::Unsafety::Unsafe,
                     abi: Abi::Rust,
@@ -3881,6 +3894,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
         Def::Union(i) => (i, TypeKind::Union),
         Def::Mod(i) => (i, TypeKind::Module),
         Def::TyForeign(i) => (i, TypeKind::Foreign),
+        Def::Const(i) => (i, TypeKind::Const),
         Def::Static(i, _) => (i, TypeKind::Static),
         Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
         Def::Macro(i, _) => (i, TypeKind::Macro),
@@ -4029,23 +4043,11 @@ pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option<String>) -> Vec<
     once(crate_name).chain(relative).collect()
 }
 
-pub fn enter_impl_trait<F, R>(cx: &DocContext, gps: &[GenericParam], f: F) -> R
+pub fn enter_impl_trait<F, R>(cx: &DocContext, f: F) -> R
 where
     F: FnOnce() -> R,
 {
-    let bounds = gps.iter()
-        .filter_map(|p| {
-            if let GenericParam::Type(ref tp) = *p {
-                if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
-                    return Some((tp.did, tp.bounds.clone()));
-                }
-            }
-
-            None
-        })
-        .collect::<FxHashMap<DefId, Vec<TyParamBound>>>();
-
-    let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), bounds);
+    let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
     let r = f();
     assert!(cx.impl_trait_bounds.borrow().is_empty());
     *cx.impl_trait_bounds.borrow_mut() = old_bounds;
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index d423203b996..61fb0b40c23 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -177,7 +177,7 @@ pub fn run_core(search_paths: SearchPaths,
                 None,
                 codemap.clone(),
                 pretty,
-                sessopts.debugging_opts.approximate_suggestions,
+                sessopts.debugging_opts.suggestion_applicability,
             ).ui_testing(sessopts.debugging_opts.ui_testing)
         ),
         ErrorOutputType::Short(color_config) => Box::new(
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index fd54e9bd1e0..5e93b20ea17 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -146,9 +146,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
         window.rootPath = \"{root_path}\";\
         window.currentCrate = \"{krate}\";\
     </script>\
+    <script src=\"{root_path}aliases.js\"></script>\
     <script src=\"{root_path}main{suffix}.js\"></script>\
     <script defer src=\"{root_path}search-index.js\"></script>\
-    <script defer src=\"{root_path}aliases.js\"></script>\
 </body>\
 </html>",
     css_extension = if css_file_extension {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 82449e9b5f9..21de2db1dfe 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1427,7 +1427,7 @@ impl<'a> Cache {
         }
         if let Some(ref item_name) = item.name {
             let path = self.paths.get(&item.def_id)
-                                 .map(|p| p.0.join("::").to_string())
+                                 .map(|p| p.0[..p.0.len() - 1].join("::"))
                                  .unwrap_or("std".to_owned());
             for alias in item.attrs.lists("doc")
                                    .filter(|a| a.check_name("alias"))
@@ -1595,6 +1595,8 @@ impl<'a> Settings<'a> {
             settings: vec![
                 ("item-declarations", "Auto-hide item declarations.", true),
                 ("item-attributes", "Auto-hide item attributes.", true),
+                ("go-to-only-result", "Directly go to item in search if there is only one result",
+                 false),
             ],
             root_path,
             suffix,
@@ -3282,7 +3284,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 }
 
 fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
-    let name = attr.ident.name;
+    let name = attr.name();
 
     if attr.is_word() {
         Some(format!("{}", name))
@@ -3317,7 +3319,7 @@ fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
-        let name = attr.name().unwrap();
+        let name = attr.name();
         if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) {
             continue;
         }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 58a57f43d37..6d80145b29c 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1013,7 +1013,8 @@
                 'returned': sortResults(results_returned, true),
                 'others': sortResults(results),
             };
-            if (ALIASES[window.currentCrate][query.raw]) {
+            if (ALIASES && ALIASES[window.currentCrate] &&
+                    ALIASES[window.currentCrate][query.raw]) {
                 var aliases = ALIASES[window.currentCrate][query.raw];
                 for (var i = 0; i < aliases.length; ++i) {
                     ret['others'].unshift(aliases[i]);
@@ -1188,6 +1189,44 @@
             return '<span>' + path.replace(/::/g, '::</span><span>');
         }
 
+        function buildHrefAndPath(item) {
+            var displayPath;
+            var href;
+            var type = itemTypes[item.ty];
+            var name = item.name;
+
+            if (type === 'mod') {
+                displayPath = item.path + '::';
+                href = rootPath + item.path.replace(/::/g, '/') + '/' +
+                       name + '/index.html';
+            } else if (type === "primitive") {
+                displayPath = "";
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + type + '.' + name + '.html';
+            } else if (type === "externcrate") {
+                displayPath = "";
+                href = rootPath + name + '/index.html';
+            } else if (item.parent !== undefined) {
+                var myparent = item.parent;
+                var anchor = '#' + type + '.' + name;
+                var parentType = itemTypes[myparent.ty];
+                if (parentType === "primitive") {
+                    displayPath = myparent.name + '::';
+                } else {
+                    displayPath = item.path + '::' + myparent.name + '::';
+                }
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + parentType +
+                       '.' + myparent.name +
+                       '.html' + anchor;
+            } else {
+                displayPath = item.path + '::';
+                href = rootPath + item.path.replace(/::/g, '/') +
+                       '/' + type + '.' + name + '.html';
+            }
+            return [displayPath, href];
+        }
+
         function addTab(array, query, display) {
             var extraStyle = '';
             if (display === false) {
@@ -1211,35 +1250,9 @@
                     name = item.name;
                     type = itemTypes[item.ty];
 
-                    if (type === 'mod') {
-                        displayPath = item.path + '::';
-                        href = rootPath + item.path.replace(/::/g, '/') + '/' +
-                               name + '/index.html';
-                    } else if (type === "primitive") {
-                        displayPath = "";
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + type + '.' + name + '.html';
-                    } else if (type === "externcrate") {
-                        displayPath = "";
-                        href = rootPath + name + '/index.html';
-                    } else if (item.parent !== undefined) {
-                        var myparent = item.parent;
-                        var anchor = '#' + type + '.' + name;
-                        var parentType = itemTypes[myparent.ty];
-                        if (parentType === "primitive") {
-                            displayPath = myparent.name + '::';
-                        } else {
-                            displayPath = item.path + '::' + myparent.name + '::';
-                        }
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + parentType +
-                               '.' + myparent.name +
-                               '.html' + anchor;
-                    } else {
-                        displayPath = item.path + '::';
-                        href = rootPath + item.path.replace(/::/g, '/') +
-                               '/' + type + '.' + name + '.html';
-                    }
+                    var res = buildHrefAndPath(item);
+                    var href = res[1];
+                    var displayPath = res[0];
 
                     output += '<tr class="' + type + ' result"><td>' +
                               '<a href="' + href + '">' +
@@ -1268,6 +1281,16 @@
         }
 
         function showResults(results) {
+            if (results['others'].length === 1 &&
+                getCurrentValue('rustdoc-go-to-only-result') === "true") {
+                var elem = document.createElement('a');
+                var res = buildHrefAndPath(results['others'][0]);
+                elem.href = res[1];
+                elem.style.display = 'none';
+                // For firefox, we need the element to be in the DOM so it can be clicked.
+                document.body.appendChild(elem);
+                elem.click();
+            }
             var output, query = getQuery(search_input.value);
 
             currentResults = query.id;
@@ -1721,6 +1744,9 @@
 
     function toggleAllDocs(pageId) {
         var toggle = document.getElementById("toggle-all-docs");
+        if (!toggle) {
+            return;
+        }
         if (hasClass(toggle, "will-expand")) {
             updateLocalStorage("rustdoc-collapse", "false");
             removeClass(toggle, "will-expand");
@@ -1970,14 +1996,14 @@
         if (e.parentNode.id === "main") {
             var otherMessage;
             if (hasClass(e, "type-decl")) {
-                otherMessage = '&nbsp;Show&nbsp;type&nbsp;declaration';
+                otherMessage = '&nbsp;Show&nbsp;declaration';
             }
             e.parentNode.insertBefore(createToggle(otherMessage), e);
             if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") {
                 collapseDocs(e.previousSibling.childNodes[0], "toggle");
             }
         }
-    })
+    });
 
     autoCollapseAllImpls(getPageId());
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 614386a583a..059d4169895 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -13,6 +13,8 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
+#![cfg_attr(stage0, feature(dyn_trait))]
+
 #![feature(ascii_ctype)]
 #![feature(rustc_private)]
 #![feature(box_patterns)]
@@ -23,14 +25,12 @@
 #![feature(test)]
 #![feature(vec_remove_item)]
 #![feature(entry_and_modify)]
-#![feature(dyn_trait)]
 
 extern crate arena;
 extern crate getopts;
 extern crate env_logger;
 extern crate rustc;
 extern crate rustc_data_structures;
-extern crate rustc_const_math;
 extern crate rustc_trans_utils;
 extern crate rustc_driver;
 extern crate rustc_resolve;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 967c50e62db..6db02cc6cc1 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -49,7 +49,6 @@ pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
     inlining: bool,
     /// Is the current module and all of its parents public?
     inside_public_path: bool,
-    reexported_macros: FxHashSet<DefId>,
     exact_paths: Option<FxHashMap<DefId, Vec<String>>>,
 }
 
@@ -66,7 +65,6 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
             view_item_stack: stack,
             inlining: false,
             inside_public_path: true,
-            reexported_macros: FxHashSet(),
             exact_paths: Some(FxHashMap()),
             cstore,
         }
@@ -221,7 +219,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
         if let Some(exports) = self.cx.tcx.module_exports(def_id) {
             for export in exports.iter().filter(|e| e.vis == Visibility::Public) {
                 if let Def::Macro(def_id, ..) = export.def {
-                    if def_id.krate == LOCAL_CRATE || self.reexported_macros.contains(&def_id) {
+                    if def_id.krate == LOCAL_CRATE {
                         continue // These are `krate.exported_macros`, handled in `self.visit()`.
                     }
 
@@ -298,17 +296,6 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
         let is_no_inline = use_attrs.lists("doc").has_word("no_inline") ||
                            use_attrs.lists("doc").has_word("hidden");
 
-        // Memoize the non-inlined `pub use`'d macros so we don't push an extra
-        // declaration in `visit_mod_contents()`
-        if !def_did.is_local() {
-            if let Def::Macro(did, _) = def {
-                if please_inline { return true }
-                debug!("memoizing non-inlined macro export: {:?}", def);
-                self.reexported_macros.insert(did);
-                return false;
-            }
-        }
-
         // For cross-crate impl inlining we need to know whether items are
         // reachable in documentation - a previously nonreachable item can be
         // made reachable by cross-crate inlining which we're checking here.
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index a8c70489f44..a7eb002d5a1 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -33,6 +33,7 @@ const MIN_NONZERO_RAW_CAPACITY: usize = 32;     // must be a power of two
 struct DefaultResizePolicy;
 
 impl DefaultResizePolicy {
+    #[inline]
     fn new() -> DefaultResizePolicy {
         DefaultResizePolicy
     }
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 52c53dc3b12..b50652ed6b5 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -79,7 +79,7 @@ impl TaggedHashUintPtr {
 ///
 /// Essential invariants of this structure:
 ///
-///   - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw`
+///   - if `t.hashes[i] == EMPTY_BUCKET`, then `Bucket::at_index(&t, i).raw`
 ///     points to 'undefined' contents. Don't read from it. This invariant is
 ///     enforced outside this module with the `EmptyBucket`, `FullBucket`,
 ///     and `SafeHash` types.
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 749b8ccc13d..817eea5eaf1 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -9,34 +9,6 @@
 // except according to those terms.
 
 //! Traits for working with Errors.
-//!
-//! # The `Error` trait
-//!
-//! `Error` is a trait representing the basic expectations for error values,
-//! i.e. values of type `E` in [`Result<T, E>`]. At a minimum, errors must provide
-//! a description, but they may optionally provide additional detail (via
-//! [`Display`]) and cause chain information:
-//!
-//! ```
-//! use std::fmt::Display;
-//!
-//! trait Error: Display {
-//!     fn description(&self) -> &str;
-//!
-//!     fn cause(&self) -> Option<&Error> { None }
-//! }
-//! ```
-//!
-//! The [`cause`] method is generally used when errors cross "abstraction
-//! boundaries", i.e.  when a one module must report an error that is "caused"
-//! by an error from a lower-level module. This setup makes it possible for the
-//! high-level module to provide its own errors that do not commit to any
-//! particular implementation, but also reveal some of its implementation for
-//! debugging via [`cause`] chains.
-//!
-//! [`Result<T, E>`]: ../result/enum.Result.html
-//! [`Display`]: ../fmt/trait.Display.html
-//! [`cause`]: trait.Error.html#method.cause
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -63,33 +35,48 @@ use num;
 use str;
 use string;
 
-/// Base functionality for all errors in Rust.
+/// `Error` is a trait representing the basic expectations for error values,
+/// i.e. values of type `E` in [`Result<T, E>`]. Errors must describe
+/// themselves through the [`Display`] and [`Debug`] traits, and may provide
+/// cause chain information:
+///
+/// The [`cause`] method is generally used when errors cross "abstraction
+/// boundaries", i.e.  when a one module must report an error that is "caused"
+/// by an error from a lower-level module. This setup makes it possible for the
+/// high-level module to provide its own errors that do not commit to any
+/// particular implementation, but also reveal some of its implementation for
+/// debugging via [`cause`] chains.
+///
+/// [`Result<T, E>`]: ../result/enum.Result.html
+/// [`Display`]: ../fmt/trait.Display.html
+/// [`cause`]: trait.Error.html#method.cause
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Error: Debug + Display {
-    /// A short description of the error.
+    /// **This method is soft-deprecated.**
     ///
-    /// The description should only be used for a simple message.
-    /// It should not contain newlines or sentence-ending punctuation,
-    /// to facilitate embedding in larger user-facing strings.
-    /// For showing formatted error messages with more information see
-    /// [`Display`].
+    /// Although using it won’t cause compilation warning,
+    /// new code should use [`Display`] instead
+    /// and new `impl`s can omit it.
+    ///
+    /// To obtain error description as a string, use `to_string()`.
     ///
     /// [`Display`]: ../fmt/trait.Display.html
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::error::Error;
-    ///
     /// match "xc".parse::<u32>() {
     ///     Err(e) => {
-    ///         println!("Error: {}", e.description());
+    ///         // Print `e` itself, not `e.description()`.
+    ///         println!("Error: {}", e);
     ///     }
     ///     _ => println!("No error"),
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn description(&self) -> &str;
+    fn description(&self) -> &str {
+        "description() is deprecated; use Display"
+    }
 
     /// The lower-level cause of this error, if any.
     ///
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index c88c2bc9137..7c358aafa9b 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -988,6 +988,7 @@ impl CStr {
     /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
+    /// # #![allow(unused_must_use)]
     /// use std::ffi::{CString};
     ///
     /// let ptr = CString::new("Hello").unwrap().as_ptr();
@@ -1003,6 +1004,7 @@ impl CStr {
     /// To fix the problem, bind the `CString` to a local variable:
     ///
     /// ```no_run
+    /// # #![allow(unused_must_use)]
     /// use std::ffi::{CString};
     ///
     /// let hello = CString::new("Hello").unwrap();
@@ -1118,6 +1120,7 @@ impl CStr {
     ///
     /// [`Cow`]: ../borrow/enum.Cow.html
     /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
+    /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
     /// [`str`]: ../primitive.str.html
     /// [`String`]: ../string/struct.String.html
     ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 41992193135..d41739ab02c 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -273,7 +273,6 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
-#![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
@@ -313,6 +312,7 @@
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
+#![feature(use_extern_macros)]
 #![feature(vec_push_all)]
 #![feature(doc_cfg)]
 #![feature(doc_masked)]
@@ -330,10 +330,10 @@
 // with a rustc without jemalloc.
 // FIXME(#44236) shouldn't need MSVC logic
 #![cfg_attr(all(not(target_env = "msvc"),
-                any(stage0, feature = "force_alloc_system")),
+                any(all(stage0, not(test)), feature = "force_alloc_system")),
             feature(global_allocator))]
 #[cfg(all(not(target_env = "msvc"),
-          any(stage0, feature = "force_alloc_system")))]
+          any(all(stage0, not(test)), feature = "force_alloc_system")))]
 #[global_allocator]
 static ALLOC: alloc_system::System = alloc_system::System;
 
@@ -347,15 +347,14 @@ use prelude::v1::*;
 #[cfg(test)] extern crate test;
 #[cfg(test)] extern crate rand;
 
-// We want to re-export a few macros from core but libcore has already been
-// imported by the compiler (via our #[no_std] attribute) In this case we just
-// add a new crate name so we can attach the re-exports to it.
-#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
-                 debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
-extern crate core as __core;
+// Re-export a few macros from core
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::{unreachable, unimplemented, write, writeln, try};
 
+#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
 #[macro_use]
-#[macro_reexport(vec, format)]
 extern crate alloc as alloc_crate;
 extern crate alloc_system;
 #[doc(masked)]
@@ -450,6 +449,8 @@ pub use alloc_crate::borrow;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::fmt;
 #[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::format;
+#[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::slice;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use alloc_crate::str;
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 6902ec82047..d1274a40900 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -450,8 +450,8 @@ pub mod builtin {
     #[unstable(feature = "concat_idents_macro", issue = "29599")]
     #[macro_export]
     macro_rules! concat_idents {
-        ($($e:ident),*) => ({ /* compiler built-in */ });
-        ($($e:ident,)*) => ({ /* compiler built-in */ });
+        ($($e:ident),+) => ({ /* compiler built-in */ });
+        ($($e:ident,)+) => ({ /* compiler built-in */ });
     }
 
     /// Concatenates literals into a static string slice.
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index bc2c9f522d3..e80c3eeb876 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -13,11 +13,10 @@ use hash;
 use io;
 use mem;
 use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
-#[allow(deprecated)]
-use net::lookup_host;
 use option;
 use sys::net::netc as c;
 use sys_common::{FromInner, AsInner, IntoInner};
+use sys_common::net::lookup_host;
 use vec;
 use iter;
 use slice;
@@ -856,7 +855,6 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
     }
 }
 
-#[allow(deprecated)]
 fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
     let ips = lookup_host(s)?;
     let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect();
diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs
index b0d5e563cb9..be4bcee8a68 100644
--- a/src/libstd/net/mod.rs
+++ b/src/libstd/net/mod.rs
@@ -38,9 +38,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use fmt;
 use io::{self, Error, ErrorKind};
-use sys_common::net as net_imp;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
@@ -128,66 +126,3 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
                    "could not resolve to any addresses")
     }))
 }
-
-/// An iterator over `SocketAddr` values returned from a host lookup operation.
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
-pub struct LookupHost(net_imp::LookupHost);
-
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
-#[allow(deprecated)]
-impl Iterator for LookupHost {
-    type Item = SocketAddr;
-    fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
-}
-
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
-#[allow(deprecated)]
-impl fmt::Debug for LookupHost {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("LookupHost { .. }")
-    }
-}
-
-/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
-///
-/// This method may perform a DNS query to resolve `host` and may also inspect
-/// system configuration to resolve the specified hostname.
-///
-/// The returned iterator will skip over any unknown addresses returned by the
-/// operating system.
-///
-/// # Examples
-///
-/// ```no_run
-/// #![feature(lookup_host)]
-///
-/// use std::net;
-///
-/// fn main() -> std::io::Result<()> {
-///     for host in net::lookup_host("rust-lang.org")? {
-///         println!("found address: {}", host);
-///     }
-///     Ok(())
-/// }
-/// ```
-#[unstable(feature = "lookup_host", reason = "unsure about the returned \
-                                              iterator and returning socket \
-                                              addresses",
-           issue = "27705")]
-#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")]
-#[allow(deprecated)]
-pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
-    net_imp::lookup_host(host).map(LookupHost)
-}
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 28c178307a5..229034eb779 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -31,10 +31,14 @@ pub use core::panic::{PanicInfo, Location};
 /// A marker trait which represents "panic safe" types in Rust.
 ///
 /// This trait is implemented by default for many types and behaves similarly in
-/// terms of inference of implementation to the `Send` and `Sync` traits. The
-/// purpose of this trait is to encode what types are safe to cross a `catch_unwind`
+/// terms of inference of implementation to the [`Send`] and [`Sync`] traits. The
+/// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`]
 /// boundary with no fear of unwind safety.
 ///
+/// [`Send`]: ../marker/trait.Send.html
+/// [`Sync`]: ../marker/trait.Sync.html
+/// [`catch_unwind`]: ./fn.catch_unwind.html
+///
 /// ## What is unwind safety?
 ///
 /// In Rust a function can "return" early if it either panics or calls a
@@ -95,12 +99,13 @@ pub use core::panic::{PanicInfo, Location};
 ///
 /// ## When should `UnwindSafe` be used?
 ///
-/// Is not intended that most types or functions need to worry about this trait.
-/// It is only used as a bound on the `catch_unwind` function and as mentioned above,
-/// the lack of `unsafe` means it is mostly an advisory. The `AssertUnwindSafe`
-/// wrapper struct in this module can be used to force this trait to be
-/// implemented for any closed over variables passed to the `catch_unwind` function
-/// (more on this below).
+/// It is not intended that most types or functions need to worry about this trait.
+/// It is only used as a bound on the `catch_unwind` function and as mentioned
+/// above, the lack of `unsafe` means it is mostly an advisory. The
+/// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be
+/// implemented for any closed over variables passed to `catch_unwind`.
+///
+/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                             across an unwind boundary"]
@@ -109,11 +114,14 @@ pub auto trait UnwindSafe {}
 /// A marker trait representing types where a shared reference is considered
 /// unwind safe.
 ///
-/// This trait is namely not implemented by `UnsafeCell`, the root of all
+/// This trait is namely not implemented by [`UnsafeCell`], the root of all
 /// interior mutability.
 ///
 /// This is a "helper marker trait" used to provide impl blocks for the
-/// `UnwindSafe` trait, for more information see that documentation.
+/// [`UnwindSafe`] trait, for more information see that documentation.
+///
+/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html
+/// [`UnwindSafe`]: ./trait.UnwindSafe.html
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
                             and a reference may not be safely transferrable \
@@ -122,14 +130,15 @@ pub auto trait RefUnwindSafe {}
 
 /// A simple wrapper around a type to assert that it is unwind safe.
 ///
-/// When using `catch_unwind` it may be the case that some of the closed over
+/// When using [`catch_unwind`] it may be the case that some of the closed over
 /// variables are not unwind safe. For example if `&mut T` is captured the
 /// compiler will generate a warning indicating that it is not unwind safe. It
 /// may not be the case, however, that this is actually a problem due to the
-/// specific usage of `catch_unwind` if unwind safety is specifically taken into
+/// specific usage of [`catch_unwind`] if unwind safety is specifically taken into
 /// account. This wrapper struct is useful for a quick and lightweight
 /// annotation that a variable is indeed unwind safe.
 ///
+/// [`catch_unwind`]: ./fn.catch_unwind.html
 /// # Examples
 ///
 /// One way to use `AssertUnwindSafe` is to assert that the entire closure
@@ -318,18 +327,22 @@ impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
 /// panic and allowing a graceful handling of the error.
 ///
 /// It is **not** recommended to use this function for a general try/catch
-/// mechanism. The `Result` type is more appropriate to use for functions that
+/// mechanism. The [`Result`] type is more appropriate to use for functions that
 /// can fail on a regular basis. Additionally, this function is not guaranteed
 /// to catch all panics, see the "Notes" section below.
 ///
-/// The closure provided is required to adhere to the `UnwindSafe` trait to ensure
+/// [`Result`]: ../result/enum.Result.html
+///
+/// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure
 /// that all captured variables are safe to cross this boundary. The purpose of
 /// this bound is to encode the concept of [exception safety][rfc] in the type
 /// system. Most usage of this function should not need to worry about this
 /// bound as programs are naturally unwind safe without `unsafe` code. If it
-/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this
-/// module can be used to quickly assert that the usage here is indeed unwind
-/// safe.
+/// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly
+/// assert that the usage here is indeed unwind safe.
+///
+/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
+/// [`UnwindSafe`]: ./trait.UnwindSafe.html
 ///
 /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
 ///
@@ -364,9 +377,11 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 
 /// Triggers a panic without invoking the panic hook.
 ///
-/// This is designed to be used in conjunction with `catch_unwind` to, for
+/// This is designed to be used in conjunction with [`catch_unwind`] to, for
 /// example, carry a panic across a layer of C code.
 ///
+/// [`catch_unwind`]: ./fn.catch_unwind.html
+///
 /// # Notes
 ///
 /// Note that panics in Rust are not always implemented via unwinding, but they
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 24eae6a4c82..403056240bf 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -76,7 +76,9 @@ static mut HOOK: Hook = Hook::Default;
 /// is invoked. As such, the hook will run with both the aborting and unwinding
 /// runtimes. The default hook prints a message to standard error and generates
 /// a backtrace if requested, but this behavior can be customized with the
-/// `set_hook` and `take_hook` functions.
+/// `set_hook` and [`take_hook`] functions.
+///
+/// [`take_hook`]: ./fn.take_hook.html
 ///
 /// The hook is provided with a `PanicInfo` struct which contains information
 /// about the origin of the panic, including the payload passed to `panic!` and
@@ -121,6 +123,10 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
 
 /// Unregisters the current panic hook, returning it.
 ///
+/// *See also the function [`set_hook`].*
+///
+/// [`set_hook`]: ./fn.set_hook.html
+///
 /// If no custom hook is registered, the default hook will be returned.
 ///
 /// # Panics
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 955a6af1ae6..696711a70d4 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -87,7 +87,6 @@ use io;
 use iter::{self, FusedIterator};
 use ops::{self, Deref};
 use rc::Rc;
-use str::FromStr;
 use sync::Arc;
 
 use ffi::{OsStr, OsString};
@@ -1441,32 +1440,6 @@ impl From<String> for PathBuf {
     }
 }
 
-/// Error returned from [`PathBuf::from_str`][`from_str`].
-///
-/// Note that parsing a path will never fail. This error is just a placeholder
-/// for implementing `FromStr` for `PathBuf`.
-///
-/// [`from_str`]: struct.PathBuf.html#method.from_str
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[stable(feature = "path_from_str", since = "1.26.0")]
-pub enum ParsePathError {}
-
-#[stable(feature = "path_from_str", since = "1.26.0")]
-impl fmt::Display for ParsePathError {
-    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
-        match *self {}
-    }
-}
-
-#[stable(feature = "path_from_str", since = "1.26.0")]
-impl FromStr for PathBuf {
-    type Err = ParsePathError;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        Ok(PathBuf::from(s))
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
     fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index a9f3cea243f..9310dad9172 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -518,6 +518,7 @@ mod tests {
         }
     }
 
+    #[allow(unused_must_use)]
     #[test]
     fn cloning() {
         let (tx1, rx1) = channel::<i32>();
@@ -540,6 +541,7 @@ mod tests {
         tx3.send(()).unwrap();
     }
 
+    #[allow(unused_must_use)]
     #[test]
     fn cloning2() {
         let (tx1, rx1) = channel::<i32>();
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index cbfcad12f1e..f8cd6103bdf 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -474,10 +474,10 @@ pub enum NestedMetaItemKind {
 
 /// A spanned compile-time attribute item.
 ///
-/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
+/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct MetaItem {
-    pub ident: Ident,
+    pub ident: Path,
     pub node: MetaItemKind,
     pub span: Span,
 }
@@ -821,7 +821,7 @@ impl Stmt {
 
     pub fn is_item(&self) -> bool {
         match self.node {
-            StmtKind::Local(_) => true,
+            StmtKind::Item(_) => true,
             _ => false,
         }
     }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index c68a743303a..ace9904e0c0 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -15,10 +15,10 @@ pub use self::ReprAttr::*;
 pub use self::IntType::*;
 
 use ast;
-use ast::{AttrId, Attribute, Name, Ident};
+use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment};
 use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
 use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
-use codemap::{Spanned, respan, dummy_spanned};
+use codemap::{BytePos, Spanned, respan, dummy_spanned};
 use syntax_pos::Span;
 use errors::Handler;
 use feature_gate::{Features, GatedCfg};
@@ -107,6 +107,14 @@ pub fn is_known(attr: &Attribute) -> bool {
     })
 }
 
+const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
+
+pub fn is_known_tool(attr: &Attribute) -> bool {
+    let tool_name =
+        attr.path.segments.iter().next().expect("empty path in attribute").ident.name;
+    RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
+}
+
 impl NestedMetaItem {
     /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
     pub fn meta_item(&self) -> Option<&MetaItem> {
@@ -137,7 +145,7 @@ impl NestedMetaItem {
     /// Returns the name of the meta item, e.g. `foo` in `#[foo]`,
     /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem
     pub fn name(&self) -> Option<Name> {
-        self.meta_item().and_then(|meta_item| Some(meta_item.ident.name))
+        self.meta_item().and_then(|meta_item| Some(meta_item.name()))
     }
 
     /// Gets the string value if self is a MetaItem and the MetaItem is a
@@ -154,7 +162,7 @@ impl NestedMetaItem {
                     if meta_item_list.len() == 1 {
                         let nested_item = &meta_item_list[0];
                         if nested_item.is_literal() {
-                            Some((meta_item.ident.name, nested_item.literal().unwrap()))
+                            Some((meta_item.name(), nested_item.literal().unwrap()))
                         } else {
                             None
                         }
@@ -204,6 +212,10 @@ impl NestedMetaItem {
     }
 }
 
+fn name_from_path(path: &Path) -> Name {
+    path.segments.last().expect("empty path in attribute").ident.name
+}
+
 impl Attribute {
     pub fn check_name(&self, name: &str) -> bool {
         let matches = self.path == name;
@@ -213,11 +225,10 @@ impl Attribute {
         matches
     }
 
-    pub fn name(&self) -> Option<Name> {
-        match self.path.segments.len() {
-            1 => Some(self.path.segments[0].ident.name),
-            _ => None,
-        }
+    /// Returns the **last** segment of the name of this attribute.
+    /// E.g. `foo` for `#[foo]`, `skip` for `#[rustfmt::skip]`.
+    pub fn name(&self) -> Name {
+        name_from_path(&self.path)
     }
 
     pub fn value_str(&self) -> Option<Symbol> {
@@ -247,9 +258,17 @@ impl Attribute {
     pub fn is_value_str(&self) -> bool {
         self.value_str().is_some()
     }
+
+    pub fn is_scoped(&self) -> bool {
+        self.path.segments.len() > 1
+    }
 }
 
 impl MetaItem {
+    pub fn name(&self) -> Name {
+        name_from_path(&self.ident)
+    }
+
     pub fn value_str(&self) -> Option<Symbol> {
         match self.node {
             MetaItemKind::NameValue(ref v) => {
@@ -279,7 +298,7 @@ impl MetaItem {
     pub fn span(&self) -> Span { self.span }
 
     pub fn check_name(&self, name: &str) -> bool {
-        self.ident.name == name
+        self.name() == name
     }
 
     pub fn is_value_str(&self) -> bool {
@@ -296,10 +315,7 @@ impl Attribute {
     pub fn meta(&self) -> Option<MetaItem> {
         let mut tokens = self.tokens.trees().peekable();
         Some(MetaItem {
-            ident: match self.path.segments.len() {
-                1 => self.path.segments[0].ident,
-                _ => return None,
-            },
+            ident: self.path.clone(),
             node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
                 if tokens.peek().is_some() {
                     return None;
@@ -344,12 +360,8 @@ impl Attribute {
     }
 
     pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
-        if self.path.segments.len() > 1 {
-            sess.span_diagnostic.span_err(self.path.span, "expected ident, found path");
-        }
-
         Ok(MetaItem {
-            ident: self.path.segments.last().unwrap().ident,
+            ident: self.path.clone(),
             node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
             span: self.span,
         })
@@ -387,16 +399,17 @@ pub fn mk_name_value_item_str(ident: Ident, value: Spanned<Symbol>) -> MetaItem
 }
 
 pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem {
-    MetaItem { ident, span, node: MetaItemKind::NameValue(value) }
+    MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) }
 }
 
 pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
-    MetaItem { ident, span, node: MetaItemKind::List(items) }
+    MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::List(items) }
 }
 
 pub fn mk_word_item(ident: Ident) -> MetaItem {
-    MetaItem { ident, span: ident.span, node: MetaItemKind::Word }
+    MetaItem { ident: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word }
 }
+
 pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
     respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident)))
 }
@@ -422,7 +435,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute
     Attribute {
         id,
         style: ast::AttrStyle::Inner,
-        path: ast::Path::from_ident(item.ident),
+        path: item.ident,
         tokens: item.node.tokens(item.span),
         is_sugared_doc: false,
         span: sp,
@@ -440,7 +453,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute
     Attribute {
         id,
         style: ast::AttrStyle::Outer,
-        path: ast::Path::from_ident(item.ident),
+        path: item.ident,
         tokens: item.node.tokens(item.span),
         is_sugared_doc: false,
         span: sp,
@@ -453,7 +466,7 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute {
     Attribute {
         id,
         style,
-        path: ast::Path::from_ident(Ident::from_str("doc").with_span_pos(span)),
+        path: Path::from_ident(Ident::from_str("doc").with_span_pos(span)),
         tokens: MetaItemKind::NameValue(lit).tokens(span),
         is_sugared_doc: true,
         span,
@@ -489,7 +502,7 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
         item.check_name("feature") &&
         item.meta_item_list().map(|list| {
             list.iter().any(|mi| {
-                mi.word().map(|w| w.ident.name == feature_name)
+                mi.word().map(|w| w.name() == feature_name)
                          .unwrap_or(false)
             })
         }).unwrap_or(false)
@@ -562,7 +575,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
         if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
             gated_cfg.check_and_emit(sess, feats);
         }
-        sess.config.contains(&(cfg.ident.name, cfg.value_str()))
+        sess.config.contains(&(cfg.name(), cfg.value_str()))
     })
 }
 
@@ -583,7 +596,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
 
             // The unwraps below may look dangerous, but we've already asserted
             // that they won't fail with the loop above.
-            match &*cfg.ident.name.as_str() {
+            match &*cfg.name().as_str() {
                 "any" => mis.iter().any(|mi| {
                     eval_condition(mi.meta_item().unwrap(), sess, eval)
                 }),
@@ -676,7 +689,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
             let meta = meta.as_ref().unwrap();
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
-                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
@@ -695,14 +708,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     )+
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.ident.name.as_str() {
+                            match &*mi.name().as_str() {
                                 $(
                                     stringify!($name)
                                         => if !get(mi, &mut $name) { continue 'outer },
                                 )+
                                 _ => {
                                     handle_errors(diagnostic, mi.span,
-                                                  AttrError::UnknownMetaItem(mi.ident.name));
+                                                  AttrError::UnknownMetaItem(mi.name()));
                                     continue 'outer
                                 }
                             }
@@ -714,7 +727,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                 }
             }
 
-            match &*meta.ident.name.as_str() {
+            match &*meta.name().as_str() {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
                         span_err!(diagnostic, item_sp, E0540,
@@ -769,13 +782,13 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     let mut issue = None;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.ident.name.as_str() {
+                            match &*mi.name().as_str() {
                                 "feature" => if !get(mi, &mut feature) { continue 'outer },
                                 "reason" => if !get(mi, &mut reason) { continue 'outer },
                                 "issue" => if !get(mi, &mut issue) { continue 'outer },
                                 _ => {
                                     handle_errors(diagnostic, meta.span,
-                                                  AttrError::UnknownMetaItem(mi.ident.name));
+                                                  AttrError::UnknownMetaItem(mi.name()));
                                     continue 'outer
                                 }
                             }
@@ -825,12 +838,12 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     let mut since = None;
                     for meta in metas {
                         if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                            match &*mi.ident.name.as_str() {
+                            match &*mi.name().as_str() {
                                 "feature" => if !get(mi, &mut feature) { continue 'outer },
                                 "since" => if !get(mi, &mut since) { continue 'outer },
                                 _ => {
                                     handle_errors(diagnostic, meta.span,
-                                                  AttrError::UnknownMetaItem(mi.ident.name));
+                                                  AttrError::UnknownMetaItem(mi.name()));
                                     continue 'outer
                                 }
                             }
@@ -917,7 +930,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
         depr = if let Some(metas) = attr.meta_item_list() {
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
-                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
@@ -933,12 +946,12 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
             let mut note = None;
             for meta in metas {
                 if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                    match &*mi.ident.name.as_str() {
+                    match &*mi.name().as_str() {
                         "since" => if !get(mi, &mut since) { continue 'outer },
                         "note" => if !get(mi, &mut note) { continue 'outer },
                         _ => {
                             handle_errors(diagnostic, meta.span,
-                                          AttrError::UnknownMetaItem(mi.ident.name));
+                                          AttrError::UnknownMetaItem(mi.name()));
                             continue 'outer
                         }
                     }
@@ -990,7 +1003,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
 
                 let mut recognised = false;
                 if let Some(mi) = item.word() {
-                    let word = &*mi.ident.name.as_str();
+                    let word = &*mi.name().as_str();
                     let hint = match word {
                         "C" => Some(ReprC),
                         "packed" => Some(ReprPacked(1)),
@@ -1012,11 +1025,11 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                     let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> {
                         if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
                             if literal.is_power_of_two() {
-                                // rustc::ty::layout::Align restricts align to <= 2147483647
-                                if *literal <= 2147483647 {
+                                // rustc::ty::layout::Align restricts align to <= 2^29
+                                if *literal <= 1 << 29 {
                                     Ok(*literal as u32)
                                 } else {
-                                    Err("larger than 2147483647")
+                                    Err("larger than 2^29")
                                 }
                             } else {
                                 Err("not a power of two")
@@ -1045,6 +1058,30 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                         span_err!(diagnostic, item.span, E0589,
                                   "invalid `repr(align)` attribute: {}", literal_error);
                     }
+                } else {
+                    if let Some(meta_item) = item.meta_item() {
+                        if meta_item.name() == "align" {
+                            if let MetaItemKind::NameValue(ref value) = meta_item.node {
+                                recognised = true;
+                                let mut err = struct_span_err!(diagnostic, item.span, E0693,
+                                    "incorrect `repr(align)` attribute format");
+                                match value.node {
+                                    ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
+                                        err.span_suggestion(item.span,
+                                                            "use parentheses instead",
+                                                            format!("align({})", int));
+                                    }
+                                    ast::LitKind::Str(s, _) => {
+                                        err.span_suggestion(item.span,
+                                                            "use parentheses instead",
+                                                            format!("align({})", s));
+                                    }
+                                    _ => {}
+                                }
+                                err.emit();
+                            }
+                        }
+                    }
                 }
                 if !recognised {
                     // Not a word we recognize
@@ -1103,18 +1140,56 @@ impl IntType {
 
 impl MetaItem {
     fn tokens(&self) -> TokenStream {
-        let ident = TokenTree::Token(self.span, Token::from_ast_ident(self.ident));
-        TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)])
+        let mut idents = vec![];
+        let mut last_pos = BytePos(0 as u32);
+        for (i, segment) in self.ident.segments.iter().enumerate() {
+            let is_first = i == 0;
+            if !is_first {
+                let mod_sep_span = Span::new(last_pos,
+                                             segment.ident.span.lo(),
+                                             segment.ident.span.ctxt());
+                idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into());
+            }
+            idents.push(TokenTree::Token(segment.ident.span,
+                                         Token::from_ast_ident(segment.ident)).into());
+            last_pos = segment.ident.span.hi();
+        }
+        idents.push(self.node.tokens(self.span));
+        TokenStream::concat(idents)
     }
 
     fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
         where I: Iterator<Item = TokenTree>,
     {
-        let (span, ident) = match tokens.next() {
-            Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident),
+        // FIXME: Share code with `parse_path`.
+        let ident = match tokens.next() {
+            Some(TokenTree::Token(span, Token::Ident(ident, _))) => {
+                if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
+                    let mut segments = vec![PathSegment::from_ident(ident.with_span_pos(span))];
+                    tokens.next();
+                    loop {
+                        if let Some(TokenTree::Token(span,
+                                                     Token::Ident(ident, _))) = tokens.next() {
+                            segments.push(PathSegment::from_ident(ident.with_span_pos(span)));
+                        } else {
+                            return None;
+                        }
+                        if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
+                            tokens.next();
+                        } else {
+                            break;
+                        }
+                    }
+                    let span = span.with_hi(segments.last().unwrap().ident.span.hi());
+                    Path { span, segments }
+                } else {
+                    Path::from_ident(ident.with_span_pos(span))
+                }
+            }
             Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 {
-                token::Nonterminal::NtIdent(ident, _) => (ident.span, ident),
+                token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident),
                 token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
+                token::Nonterminal::NtPath(ref path) => path.clone(),
                 _ => return None,
             },
             _ => return None,
@@ -1123,10 +1198,11 @@ impl MetaItem {
         let node = MetaItemKind::from_tokens(tokens)?;
         let hi = match node {
             MetaItemKind::NameValue(ref lit) => lit.span.hi(),
-            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi()),
-            _ => span.hi(),
+            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(ident.span.hi()),
+            _ => ident.span.hi(),
         };
-        Some(MetaItem { ident, node, span: span.with_hi(hi) })
+        let span = ident.span.with_hi(hi);
+        Some(MetaItem { ident, node, span })
     }
 }
 
@@ -1228,10 +1304,7 @@ impl LitKind {
 
         match *self {
             LitKind::Str(string, ast::StrStyle::Cooked) => {
-                let mut escaped = String::new();
-                for ch in string.as_str().chars() {
-                    escaped.extend(ch.escape_unicode());
-                }
+                let escaped = string.as_str().escape_default();
                 Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None)
             }
             LitKind::Str(string, ast::StrStyle::Raw(n)) => {
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index bb7988e64bc..5f940437ab3 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -244,6 +244,18 @@ fn main() {
 ```
 "##,
 
+E0589: r##"
+The value of `N` that was specified for `repr(align(N))` was not a power
+of two, or was greater than 2^29.
+
+```compile_fail,E0589
+#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two
+enum Foo {
+    Bar(u64),
+}
+```
+"##,
+
 E0658: r##"
 An unstable feature was used.
 
@@ -321,7 +333,8 @@ register_diagnostics! {
     E0555, // malformed feature attribute, expected #![feature(...)]
     E0556, // malformed feature, expected just one word
     E0584, // file for module `..` found at both .. and ..
-    E0589, // invalid `repr(align)` attribute
     E0629, // missing 'feature' (rustc_const_unstable)
     E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
+    E0693, // incorrect `repr(align)` attribute format
+    E0694, // an unknown tool name found in scoped attributes
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 0c313ab1489..3b76084f2fb 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -118,6 +118,20 @@ impl Annotatable {
         }
     }
 
+    pub fn expect_stmt(self) -> ast::Stmt {
+        match self {
+            Annotatable::Stmt(stmt) => stmt.into_inner(),
+            _ => panic!("expected statement"),
+        }
+    }
+
+    pub fn expect_expr(self) -> P<ast::Expr> {
+        match self {
+            Annotatable::Expr(expr) => expr,
+            _ => panic!("expected expression"),
+        }
+    }
+
     pub fn derive_allowed(&self) -> bool {
         match *self {
             Annotatable::Item(ref item) => match item.node {
@@ -661,7 +675,9 @@ pub trait Resolver {
 
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
-    fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
+    fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool)
+                              -> Option<Attribute>;
+
     fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
                      -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
@@ -687,7 +703,8 @@ impl Resolver for DummyResolver {
     fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
 
     fn resolve_imports(&mut self) {}
-    fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
+    fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
+                              -> Option<Attribute> { None }
     fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool)
                      -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
         Err(Determinacy::Determined)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1434e5fddea..584b9455a93 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -143,7 +143,7 @@ impl ExpansionKind {
     }
 
     fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
-        let items = items.into_iter();
+        let mut items = items.into_iter();
         match self {
             ExpansionKind::Items =>
                 Expansion::Items(items.map(Annotatable::expect_item).collect()),
@@ -153,7 +153,14 @@ impl ExpansionKind {
                 Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
             ExpansionKind::ForeignItems =>
                 Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
-            _ => unreachable!(),
+            ExpansionKind::Stmts => Expansion::Stmts(items.map(Annotatable::expect_stmt).collect()),
+            ExpansionKind::Expr => Expansion::Expr(
+                items.next().expect("expected exactly one expression").expect_expr()
+            ),
+            ExpansionKind::OptExpr =>
+                Expansion::OptExpr(items.next().map(Annotatable::expect_expr)),
+            ExpansionKind::Pat | ExpansionKind::Ty =>
+                panic!("patterns and types aren't annotatable"),
         }
     }
 }
@@ -803,7 +810,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = span.with_ctxt(self.cx.backtrace());
                 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
-                    ident: keywords::Invalid.ident(),
+                    ident: Path::from_ident(keywords::Invalid.ident()),
                     span: DUMMY_SP,
                     node: ast::MetaItemKind::Word,
                 };
@@ -956,14 +963,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         self.collect(kind, InvocationKind::Attr { attr, traits, item })
     }
 
-    // If `item` is an attr invocation, remove and return the macro attribute.
+    /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
     fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path>, T)
         where T: HasAttrs,
     {
         let (mut attr, mut traits) = (None, Vec::new());
 
         item = item.map_attrs(|mut attrs| {
-            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs) {
+            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
+                                                                                     true) {
                 attr = Some(legacy_attr_invoc);
                 return attrs;
             }
@@ -978,6 +986,28 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         (attr, traits, item)
     }
 
+    /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough
+    /// to the unused-attributes lint (making it an error on statements and expressions
+    /// is a breaking change)
+    fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T) -> (Option<ast::Attribute>, T) {
+        let mut attr = None;
+
+        item = item.map_attrs(|mut attrs| {
+            if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
+                                                                                     false) {
+                attr = Some(legacy_attr_invoc);
+                return attrs;
+            }
+
+            if self.cx.ecfg.proc_macro_enabled() {
+                attr = find_attr_invoc(&mut attrs);
+            }
+            attrs
+        });
+
+        (attr, item)
+    }
+
     fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
         self.cfg.configure(node)
     }
@@ -987,12 +1017,23 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
         let features = self.cx.ecfg.features.unwrap();
         for attr in attrs.iter() {
-            feature_gate::check_attribute(attr, self.cx.parse_sess, features);
+            self.check_attribute_inner(attr, features);
+
+            // macros are expanded before any lint passes so this warning has to be hardcoded
+            if attr.path == "derive" {
+                self.cx.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations")
+                    .note("this may become a hard error in a future release")
+                    .emit();
+            }
         }
     }
 
     fn check_attribute(&mut self, at: &ast::Attribute) {
         let features = self.cx.ecfg.features.unwrap();
+        self.check_attribute_inner(at, features);
+    }
+
+    fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) {
         feature_gate::check_attribute(at, self.cx.parse_sess, features);
     }
 }
@@ -1008,15 +1049,16 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
         let mut expr = self.cfg.configure_expr(expr).into_inner();
         expr.node = self.cfg.configure_expr_kind(expr.node);
 
-        let (attr, derives, expr) = self.classify_item(expr);
+        // ignore derives so they remain unused
+        let (attr, expr) = self.classify_nonitem(expr);
 
-        if attr.is_some() || !derives.is_empty() {
+        if attr.is_some() {
             // collect the invoc regardless of whether or not attributes are permitted here
             // expansion will eat the attribute so it won't error later
             attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
 
             // ExpansionKind::Expr requires the macro to emit an expression
-            return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)), ExpansionKind::Expr)
+            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), ExpansionKind::Expr)
                 .make_expr();
         }
 
@@ -1032,12 +1074,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
         let mut expr = configure!(self, expr).into_inner();
         expr.node = self.cfg.configure_expr_kind(expr.node);
 
-        let (attr, derives, expr) = self.classify_item(expr);
+        // ignore derives so they remain unused
+        let (attr, expr) = self.classify_nonitem(expr);
 
-        if attr.is_some() || !derives.is_empty() {
+        if attr.is_some() {
             attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
 
-            return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)),
+            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
                                      ExpansionKind::OptExpr)
                 .make_opt_expr();
         }
@@ -1071,7 +1114,14 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
 
         // we'll expand attributes on expressions separately
         if !stmt.is_expr() {
-            let (attr, derives, stmt_) = self.classify_item(stmt);
+            let (attr, derives, stmt_) = if stmt.is_item() {
+                self.classify_item(stmt)
+            } else {
+                // ignore derives on non-item statements so it falls through
+                // to the unused-attributes lint
+                let (attr, stmt) = self.classify_nonitem(stmt);
+                (attr, vec![], stmt)
+            };
 
             if attr.is_some() || !derives.is_empty() {
                 return self.collect_attr(attr, derives,
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index d9c3deb30da..71634ada894 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -835,7 +835,13 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
-        "lifetime" => token::NtLifetime(p.expect_lifetime().ident),
+        "lifetime" => if p.check_lifetime() {
+            token::NtLifetime(p.expect_lifetime().ident)
+        } else {
+            let token_str = pprust::token_to_string(&p.token);
+            p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit();
+            FatalError.raise();
+        }
         // this is not supposed to happen, since it has been checked
         // when compiling the macro.
         _ => p.span_bug(sp, "invalid fragment specifier"),
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 0331e90164f..d8db76a95ff 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -90,24 +90,24 @@ macro_rules! declare_features {
         }
     };
 
-    ($((removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
+    ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => {
         /// Represents unstable features which have since been removed (it was once Active)
-        const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
-            $((stringify!($feature), $ver, $issue)),+
+        const REMOVED_FEATURES: &[(&str, &str, Option<u32>, Option<&str>)] = &[
+            $((stringify!($feature), $ver, $issue, $reason)),+
         ];
     };
 
     ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
         /// Represents stable features which have since been removed (it was once Accepted)
-        const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
-            $((stringify!($feature), $ver, $issue)),+
+        const STABLE_REMOVED_FEATURES: &[(&str, &str, Option<u32>, Option<&str>)] = &[
+            $((stringify!($feature), $ver, $issue, None)),+
         ];
     };
 
     ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => {
         /// Those language feature has since been Accepted (it was once Active)
-        const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
-            $((stringify!($feature), $ver, $issue)),+
+        const ACCEPTED_FEATURES: &[(&str, &str, Option<u32>, Option<&str>)] = &[
+            $((stringify!($feature), $ver, $issue, None)),+
         ];
     }
 }
@@ -162,9 +162,6 @@ declare_features! (
     // OIBIT specific features
     (active, optin_builtin_traits, "1.0.0", Some(13231), None),
 
-    // macro re-export needs more discussion and stabilization
-    (active, macro_reexport, "1.0.0", Some(29638), None),
-
     // Allows use of #[staged_api]
     // rustc internal
     (active, staged_api, "1.0.0", None, None),
@@ -369,15 +366,9 @@ declare_features! (
     // #[doc(include="some-file")]
     (active, external_doc, "1.22.0", Some(44732), None),
 
-    // allow `#[must_use]` on functions and comparison operators (RFC 1940)
-    (active, fn_must_use, "1.21.0", Some(43302), None),
-
     // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
     (active, non_exhaustive, "1.22.0", Some(44109), None),
 
-    // Trait object syntax with `dyn` prefix
-    (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)),
-
     // `crate` as visibility modifier, synonymous to `pub(crate)`
     (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)),
 
@@ -397,7 +388,7 @@ declare_features! (
     (active, generic_associated_types, "1.23.0", Some(44265), None),
 
     // Resolve absolute paths as paths from other crates
-    (active, extern_absolute_paths, "1.24.0", Some(44660), None),
+    (active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)),
 
     // `foo.rs` as an alternative to `foo/mod.rs`
     (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
@@ -466,30 +457,38 @@ declare_features! (
 
     // #[doc(alias = "...")]
     (active, doc_alias, "1.27.0", Some(50146), None),
+
+    // Access to crate names passed via `--extern` through prelude
+    (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)),
+
+    // Scoped attributes
+    (active, tool_attributes, "1.25.0", Some(44690), None),
 );
 
 declare_features! (
-    (removed, import_shadowing, "1.0.0", None, None),
-    (removed, managed_boxes, "1.0.0", None, None),
+    (removed, import_shadowing, "1.0.0", None, None, None),
+    (removed, managed_boxes, "1.0.0", None, None, None),
     // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
-    (removed, negate_unsigned, "1.0.0", Some(29645), None),
-    (removed, reflect, "1.0.0", Some(27749), None),
+    (removed, negate_unsigned, "1.0.0", Some(29645), None, None),
+    (removed, reflect, "1.0.0", Some(27749), None, None),
     // A way to temporarily opt out of opt in copy. This will *never* be accepted.
-    (removed, opt_out_copy, "1.0.0", None, None),
-    (removed, quad_precision_float, "1.0.0", None, None),
-    (removed, struct_inherit, "1.0.0", None, None),
-    (removed, test_removed_feature, "1.0.0", None, None),
-    (removed, visible_private_types, "1.0.0", None, None),
-    (removed, unsafe_no_drop_flag, "1.0.0", None, None),
+    (removed, opt_out_copy, "1.0.0", None, None, None),
+    (removed, quad_precision_float, "1.0.0", None, None, None),
+    (removed, struct_inherit, "1.0.0", None, None, None),
+    (removed, test_removed_feature, "1.0.0", None, None, None),
+    (removed, visible_private_types, "1.0.0", None, None, None),
+    (removed, unsafe_no_drop_flag, "1.0.0", None, None, None),
     // Allows using items which are missing stability attributes
     // rustc internal
-    (removed, unmarked_api, "1.0.0", None, None),
-    (removed, pushpop_unsafe, "1.2.0", None, None),
-    (removed, allocator, "1.0.0", None, None),
-    // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
-    (removed, simd, "1.0.0", Some(27731), None),
-    // Merged into `slice_patterns`
-    (removed, advanced_slice_patterns, "1.0.0", Some(23121), None),
+    (removed, unmarked_api, "1.0.0", None, None, None),
+    (removed, pushpop_unsafe, "1.2.0", None, None, None),
+    (removed, allocator, "1.0.0", None, None, None),
+    (removed, simd, "1.0.0", Some(27731), None,
+     Some("removed in favor of `#[repr(simd)]`")),
+    (removed, advanced_slice_patterns, "1.0.0", Some(23121), None,
+     Some("merged into `#![feature(slice_patterns)]`")),
+    (removed, macro_reexport, "1.0.0", Some(29638), None,
+     Some("subsumed by `#![feature(use_extern_macros)]` and `pub use`")),
 );
 
 declare_features! (
@@ -592,6 +591,10 @@ declare_features! (
     (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
     // Allows #[target_feature(...)]
     (accepted, target_feature, "1.27.0", None, None),
+    // Trait object syntax with `dyn` prefix
+    (accepted, dyn_trait, "1.27.0", Some(44662), None),
+    // allow `#[must_use]` on functions; and, must-use operators (RFC 1940)
+    (accepted, fn_must_use, "1.27.0", Some(43302), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -675,7 +678,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
     ("forbid", Normal, Ungated),
     ("deny", Normal, Ungated),
 
-    ("macro_reexport", Normal, Ungated),
     ("macro_use", Normal, Ungated),
     ("macro_export", Normal, Ungated),
     ("plugin_registrar", Normal, Ungated),
@@ -1080,7 +1082,7 @@ pub struct GatedCfg {
 
 impl GatedCfg {
     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
-        let name = cfg.ident.name.as_str();
+        let name = cfg.name().as_str();
         GATED_CFGS.iter()
                   .position(|info| info.0 == name)
                   .map(|idx| {
@@ -1133,7 +1135,7 @@ macro_rules! gate_feature {
 impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
-        let name = unwrap_or!(attr.name(), return).as_str();
+        let name = attr.name().as_str();
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if name == n {
                 if let Gated(_, name, desc, ref has_feature) = *gateage {
@@ -1173,12 +1175,28 @@ impl<'a> Context<'a> {
             // before the plugin attributes are registered
             // so we skip this then
             if !is_macro {
-                gate_feature!(self, custom_attribute, attr.span,
-                              &format!("The attribute `{}` is currently \
-                                        unknown to the compiler and \
-                                        may have meaning \
-                                        added to it in the future",
-                                       attr.path));
+                if attr.is_scoped() {
+                    gate_feature!(self, tool_attributes, attr.span,
+                                  &format!("scoped attribute `{}` is experimental", attr.path));
+                    if attr::is_known_tool(attr) {
+                        attr::mark_used(attr);
+                    } else {
+                        span_err!(
+                            self.parse_sess.span_diagnostic,
+                            attr.span,
+                            E0694,
+                            "an unknown tool name found in scoped attribute: `{}`.",
+                            attr.path
+                        );
+                    }
+                } else {
+                    gate_feature!(self, custom_attribute, attr.span,
+                                  &format!("The attribute `{}` is currently \
+                                            unknown to the compiler and \
+                                            may have meaning \
+                                            added to it in the future",
+                                           attr.path));
+                }
             }
         }
     }
@@ -1204,7 +1222,7 @@ fn find_lang_feature_issue(feature: &str) -> Option<u32> {
         let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
             .find(|t| t.0 == feature);
         match found {
-            Some(&(_, _, issue)) => issue,
+            Some(&(_, _, issue, _)) => issue,
             None => panic!("Feature `{}` is not declared anywhere", feature),
         }
     }
@@ -1518,11 +1536,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     gate_feature_post!(&self, underscore_imports, i.span,
                                        "renaming extern crates with `_` is unstable");
                 }
-                if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") {
-                    gate_feature_post!(&self, macro_reexport, attr.span,
-                                       "macros re-exports are experimental \
-                                        and possibly buggy");
-                }
             }
 
             ast::ItemKind::ForeignMod(ref foreign_module) => {
@@ -1546,11 +1559,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                         function may change over time, for now \
                                         a top-level `fn main()` is required");
                 }
-                if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") {
-                    gate_feature_post!(&self, fn_must_use, attr.span,
-                                       "`#[must_use]` on functions is experimental",
-                                       GateStrength::Soft);
-                }
             }
 
             ast::ItemKind::Struct(..) => {
@@ -1582,7 +1590,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                    "trait aliases are not yet fully implemented");
             }
 
-            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
+            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(&self, optin_builtin_traits,
                                        i.span,
@@ -1595,16 +1603,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                        i.span,
                                        "specialization is unstable");
                 }
-
-                for impl_item in impl_items {
-                    if let ast::ImplItemKind::Method(..) = impl_item.node {
-                        if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") {
-                            gate_feature_post!(&self, fn_must_use, attr.span,
-                                               "`#[must_use]` on methods is experimental",
-                                               GateStrength::Soft);
-                        }
-                    }
-                }
             }
 
             ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
@@ -1657,10 +1655,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, never_type, ty.span,
                                    "The `!` type is experimental");
             }
-            ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
-                gate_feature_post!(&self, dyn_trait, ty.span,
-                                   "`dyn Trait` syntax is unstable");
-            }
             _ => {}
         }
         visit::walk_ty(self, ty)
@@ -1842,8 +1836,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
                     crate_edition: Edition) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span) {
-        span_err!(span_handler, span, E0557, "feature has been removed");
+    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
+        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
+        if let Some(reason) = reason {
+            err.span_note(span, reason);
+        }
+        err.emit();
     }
 
     let mut features = Features::new();
@@ -1864,7 +1862,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
                 for mi in list {
 
                     let name = if let Some(word) = mi.word() {
-                        word.ident.name
+                        word.name()
                     } else {
                         span_err!(span_handler, mi.span, E0556,
                                   "malformed feature, expected just one word");
@@ -1876,19 +1874,19 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
                         set(&mut features, mi.span);
                         feature_checker.collect(&features, mi.span);
                     }
-                    else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
-                            .find(|& &(n, _, _)| name == n)
+                    else if let Some(&(.., reason)) = REMOVED_FEATURES.iter()
+                            .find(|& &(n, ..)| name == n)
                         .or_else(|| STABLE_REMOVED_FEATURES.iter()
-                            .find(|& &(n, _, _)| name == n)) {
-                        feature_removed(span_handler, mi.span);
+                            .find(|& &(n, ..)| name == n)) {
+                        feature_removed(span_handler, mi.span, reason);
                     }
-                    else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()
-                        .find(|& &(n, _, _)| name == n) {
+                    else if let Some(&(..)) = ACCEPTED_FEATURES.iter()
+                        .find(|& &(n, ..)| name == n) {
                         features.declared_stable_lang_features.push((name, mi.span));
                     } else if let Some(&edition) = ALL_EDITIONS.iter()
                                                               .find(|e| name == e.feature_name()) {
                         if edition <= crate_edition {
-                            feature_removed(span_handler, mi.span);
+                            feature_removed(span_handler, mi.span, None);
                         } else {
                             for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
                                 if let Some(f_edition) = f_edition {
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index b4f34fb12e3..2f15e75093b 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -23,7 +23,7 @@ use codemap::{CodeMap, FilePathMapping};
 use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
 use errors::registry::Registry;
 use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, CodeMapper};
-use errors::DiagnosticId;
+use errors::{DiagnosticId, Applicability};
 use errors::emitter::{Emitter, EmitterWriter};
 
 use rustc_data_structures::sync::{self, Lrc};
@@ -39,7 +39,7 @@ pub struct JsonEmitter {
     cm: Lrc<CodeMapper + sync::Send + sync::Sync>,
     pretty: bool,
     /// Whether "approximate suggestions" are enabled in the config
-    approximate_suggestions: bool,
+    suggestion_applicability: bool,
     ui_testing: bool,
 }
 
@@ -47,13 +47,13 @@ impl JsonEmitter {
     pub fn stderr(registry: Option<Registry>,
                   code_map: Lrc<CodeMap>,
                   pretty: bool,
-                  approximate_suggestions: bool) -> JsonEmitter {
+                  suggestion_applicability: bool) -> JsonEmitter {
         JsonEmitter {
             dst: Box::new(io::stderr()),
             registry,
             cm: code_map,
             pretty,
-            approximate_suggestions,
+            suggestion_applicability,
             ui_testing: false,
         }
     }
@@ -68,13 +68,13 @@ impl JsonEmitter {
                registry: Option<Registry>,
                code_map: Lrc<CodeMap>,
                pretty: bool,
-               approximate_suggestions: bool) -> JsonEmitter {
+               suggestion_applicability: bool) -> JsonEmitter {
         JsonEmitter {
             dst,
             registry,
             cm: code_map,
             pretty,
-            approximate_suggestions,
+            suggestion_applicability,
             ui_testing: false,
         }
     }
@@ -138,7 +138,7 @@ struct DiagnosticSpan {
     suggested_replacement: Option<String>,
     /// If the suggestion is approximate
     #[rustc_serialize_exclude_null]
-    suggestion_approximate: Option<bool>,
+    suggestion_applicability: Option<Applicability>,
     /// Macro invocations that created the code at this span, if any.
     expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
 }
@@ -239,7 +239,7 @@ impl Diagnostic {
 
 impl DiagnosticSpan {
     fn from_span_label(span: SpanLabel,
-                       suggestion: Option<(&String, bool)>,
+                       suggestion: Option<(&String, Applicability)>,
                        je: &JsonEmitter)
                        -> DiagnosticSpan {
         Self::from_span_etc(span.span,
@@ -252,7 +252,7 @@ impl DiagnosticSpan {
     fn from_span_etc(span: Span,
                      is_primary: bool,
                      label: Option<String>,
-                     suggestion: Option<(&String, bool)>,
+                     suggestion: Option<(&String, Applicability)>,
                      je: &JsonEmitter)
                      -> DiagnosticSpan {
         // obtain the full backtrace from the `macro_backtrace`
@@ -272,7 +272,7 @@ impl DiagnosticSpan {
     fn from_span_full(span: Span,
                       is_primary: bool,
                       label: Option<String>,
-                      suggestion: Option<(&String, bool)>,
+                      suggestion: Option<(&String, Applicability)>,
                       mut backtrace: vec::IntoIter<MacroBacktrace>,
                       je: &JsonEmitter)
                       -> DiagnosticSpan {
@@ -301,7 +301,7 @@ impl DiagnosticSpan {
             })
         });
 
-        let suggestion_approximate = if je.approximate_suggestions {
+        let suggestion_applicability = if je.suggestion_applicability {
              suggestion.map(|x| x.1)
         } else {
             None
@@ -318,7 +318,7 @@ impl DiagnosticSpan {
             is_primary,
             text: DiagnosticSpanLine::from_span(span, je),
             suggested_replacement: suggestion.map(|x| x.0.clone()),
-            suggestion_approximate,
+            suggestion_applicability,
             expansion: backtrace_step,
             label,
         }
@@ -344,7 +344,7 @@ impl DiagnosticSpan {
                               };
                               DiagnosticSpan::from_span_label(span_label,
                                                               Some((&suggestion_inner.snippet,
-                                                                   suggestion.approximate)),
+                                                                   suggestion.applicability)),
                                                               je)
                           })
                       })
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 870ce1926ad..f148aaf7267 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -25,6 +25,7 @@
 #![feature(non_exhaustive)]
 #![feature(const_atomic_usize_new)]
 #![feature(rustc_attrs)]
+#![feature(str_escape)]
 
 #![recursion_limit="256"]
 
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 90f08ab1468..cceed589212 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -149,7 +149,7 @@ impl<'a> Parser<'a> {
         };
         Ok(if let Some(meta) = meta {
             self.bump();
-            (ast::Path::from_ident(meta.ident), meta.node.tokens(meta.span))
+            (meta.ident, meta.node.tokens(meta.span))
         } else {
             (self.parse_path(PathStyle::Mod)?, self.parse_tokens())
         })
@@ -225,9 +225,10 @@ impl<'a> Parser<'a> {
         }
 
         let lo = self.span;
-        let ident = self.parse_ident()?;
+        let ident = self.parse_path(PathStyle::Mod)?;
         let node = self.parse_meta_item_kind()?;
-        Ok(ast::MetaItem { ident, node: node, span: lo.to(self.prev_span) })
+        let span = lo.to(self.prev_span);
+        Ok(ast::MetaItem { ident, node, span })
     }
 
     pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ff09c6aa2f0..f252020bc31 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -298,14 +298,10 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) {
     }
 }
 
-pub fn escape_default(s: &str) -> String {
-    s.chars().map(char::escape_default).flat_map(|x| x).collect()
-}
-
 /// Parse a string representing a string literal into its final form. Does
 /// unescaping.
 pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
-    debug!("parse_str_lit: given {}", escape_default(lit));
+    debug!("str_lit: given {}", lit.escape_default());
     let mut res = String::with_capacity(lit.len());
 
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
@@ -374,7 +370,7 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
 /// Parse a string representing a raw string literal into its final form. The
 /// only operation this does is convert embedded CRLF into a single LF.
 pub fn raw_str_lit(lit: &str) -> String {
-    debug!("raw_str_lit: given {}", escape_default(lit));
+    debug!("raw_str_lit: given {}", lit.escape_default());
     let mut res = String::with_capacity(lit.len());
 
     let mut chars = lit.chars().peekable();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 324cadc84e8..bf4a68679df 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1958,16 +1958,16 @@ impl<'a> Parser<'a> {
         let meta_ident = match self.token {
             token::Interpolated(ref nt) => match nt.0 {
                 token::NtMeta(ref meta) => match meta.node {
-                    ast::MetaItemKind::Word => Some(meta.ident),
+                    ast::MetaItemKind::Word => Some(meta.ident.clone()),
                     _ => None,
                 },
                 _ => None,
             },
             _ => None,
         };
-        if let Some(ident) = meta_ident {
+        if let Some(path) = meta_ident {
             self.bump();
-            return Ok(ast::Path::from_ident(ident));
+            return Ok(path);
         }
         self.parse_path(style)
     }
@@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn check_lifetime(&mut self) -> bool {
+    pub fn check_lifetime(&mut self) -> bool {
         self.expected_tokens.push(TokenType::Lifetime);
         self.token.is_lifetime()
     }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 44394384c7a..938711ca1d4 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -277,9 +277,10 @@ impl Token {
             DotDot | DotDotDot | DotDotEq     | // range notation
             Lt | BinOp(Shl)                   | // associated path
             ModSep                            | // global path
+            Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
             Interpolated(ref nt) => match nt.0 {
-                NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true,
+                NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) | NtLifetime(..) => true,
                 _ => false,
             },
             _ => false,
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 5c4bf47a6db..e7bd369053c 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -247,12 +247,14 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
     debug!("mk_printer {}", linewidth);
     Printer {
         out,
-        buf_len: n,
+        buf_max_len: n,
         margin: linewidth as isize,
         space: linewidth as isize,
         left: 0,
         right: 0,
-        buf: vec![BufEntry { token: Token::Eof, size: 0 }; n],
+        // Initialize a single entry; advance_right() will extend it on demand
+        // up to `buf_max_len` elements.
+        buf: vec![BufEntry::default()],
         left_total: 0,
         right_total: 0,
         scan_stack: VecDeque::new(),
@@ -263,7 +265,7 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
 
 pub struct Printer<'a> {
     out: Box<io::Write+'a>,
-    buf_len: usize,
+    buf_max_len: usize,
     /// Width of lines we're constrained to
     margin: isize,
     /// Number of spaces left on line
@@ -297,6 +299,12 @@ struct BufEntry {
     size: isize,
 }
 
+impl Default for BufEntry {
+    fn default() -> Self {
+        BufEntry { token: Token::Eof, size: 0 }
+    }
+}
+
 impl<'a> Printer<'a> {
     pub fn last_token(&mut self) -> Token {
         self.buf[self.right].token.clone()
@@ -322,7 +330,9 @@ impl<'a> Printer<'a> {
                 self.right_total = 1;
                 self.left = 0;
                 self.right = 0;
-            } else { self.advance_right(); }
+            } else {
+                self.advance_right();
+            }
             debug!("pp Begin({})/buffer Vec<{},{}>",
                    b.offset, self.left, self.right);
             self.buf[self.right] = BufEntry { token: token, size: -self.right_total };
@@ -349,7 +359,9 @@ impl<'a> Printer<'a> {
                 self.right_total = 1;
                 self.left = 0;
                 self.right = 0;
-            } else { self.advance_right(); }
+            } else {
+                self.advance_right();
+            }
             debug!("pp Break({})/buffer Vec<{},{}>",
                    b.offset, self.left, self.right);
             self.check_stack(0);
@@ -408,7 +420,11 @@ impl<'a> Printer<'a> {
     }
     pub fn advance_right(&mut self) {
         self.right += 1;
-        self.right %= self.buf_len;
+        self.right %= self.buf_max_len;
+        // Extend the buf if necessary.
+        if self.right == self.buf.len() {
+            self.buf.push(BufEntry::default());
+        }
         assert_ne!(self.right, self.left);
     }
     pub fn advance_left(&mut self) -> io::Result<()> {
@@ -438,7 +454,7 @@ impl<'a> Printer<'a> {
             }
 
             self.left += 1;
-            self.left %= self.buf_len;
+            self.left %= self.buf_max_len;
 
             left_size = self.buf[self.left].size;
         }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 88860df10e2..d8228e2b28b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -656,7 +656,7 @@ pub trait PrintState<'a> {
                     style: ast::StrStyle) -> io::Result<()> {
         let st = match style {
             ast::StrStyle::Cooked => {
-                (format!("\"{}\"", parse::escape_default(st)))
+                (format!("\"{}\"", st.escape_default()))
             }
             ast::StrStyle::Raw(n) => {
                 (format!("r{delim}\"{string}\"{delim}",
@@ -714,6 +714,22 @@ pub trait PrintState<'a> {
         Ok(())
     }
 
+    fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> {
+        for (i, segment) in path.segments.iter().enumerate() {
+            if i > 0 {
+                self.writer().word("::")?
+            }
+            if segment.ident.name != keywords::CrateRoot.name() &&
+               segment.ident.name != keywords::DollarCrate.name()
+            {
+                self.writer().word(&segment.ident.name.as_str())?;
+            } else if segment.ident.name == keywords::DollarCrate.name() {
+                self.print_dollar_crate(segment.ident.span.ctxt())?;
+            }
+        }
+        Ok(())
+    }
+
     fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
         self.print_attribute_inline(attr, false)
     }
@@ -735,17 +751,7 @@ pub trait PrintState<'a> {
             if let Some(mi) = attr.meta() {
                 self.print_meta_item(&mi)?
             } else {
-                for (i, segment) in attr.path.segments.iter().enumerate() {
-                    if i > 0 {
-                        self.writer().word("::")?
-                    }
-                    if segment.ident.name != keywords::CrateRoot.name() &&
-                       segment.ident.name != keywords::DollarCrate.name() {
-                        self.writer().word(&segment.ident.name.as_str())?;
-                    } else if segment.ident.name == keywords::DollarCrate.name() {
-                        self.print_dollar_crate(segment.ident.span.ctxt())?;
-                    }
-                }
+                self.print_attribute_path(&attr.path)?;
                 self.writer().space()?;
                 self.print_tts(attr.tokens.clone())?;
             }
@@ -767,16 +773,15 @@ pub trait PrintState<'a> {
     fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
         self.ibox(INDENT_UNIT)?;
         match item.node {
-            ast::MetaItemKind::Word => {
-                self.writer().word(&item.ident.name.as_str())?;
-            }
+            ast::MetaItemKind::Word => self.print_attribute_path(&item.ident)?,
             ast::MetaItemKind::NameValue(ref value) => {
-                self.word_space(&item.ident.name.as_str())?;
+                self.print_attribute_path(&item.ident)?;
+                self.writer().space()?;
                 self.word_space("=")?;
                 self.print_literal(value)?;
             }
             ast::MetaItemKind::List(ref items) => {
-                self.writer().word(&item.ident.name.as_str())?;
+                self.print_attribute_path(&item.ident)?;
                 self.popen()?;
                 self.commasep(Consistent,
                               &items[..],
diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs
index 544b1410d3d..b8345e7cf40 100644
--- a/src/libsyntax_ext/concat_idents.rs
+++ b/src/libsyntax_ext/concat_idents.rs
@@ -31,6 +31,11 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
         return base::DummyResult::expr(sp);
     }
 
+    if tts.is_empty() {
+        cx.span_err(sp, "concat_idents! takes 1 or more arguments.");
+        return DummyResult::expr(sp);
+    }
+
     let mut res_str = String::new();
     for (i, e) in tts.iter().enumerate() {
         if i & 1 == 1 {
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index 5fd5e299488..76da1746a03 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -22,11 +22,9 @@ struct MarkAttrs<'a>(&'a [ast::Name]);
 
 impl<'a> Visitor<'a> for MarkAttrs<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
-        if let Some(name) = attr.name() {
-            if self.0.contains(&name) {
-                mark_used(attr);
-                mark_known(attr);
-            }
+        if self.0.contains(&attr.name()) {
+            mark_used(attr);
+            mark_known(attr);
         }
     }
 
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index becd70149fd..80f65957c39 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -472,7 +472,7 @@ impl<'a> TraitDef<'a> {
                 attrs.extend(item.attrs
                     .iter()
                     .filter(|a| {
-                        a.name().is_some() && match &*a.name().unwrap().as_str() {
+                        match &*a.name().as_str() {
                             "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
                             _ => false,
                         }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 5e96b5ce673..658408519b9 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -21,6 +21,7 @@ use symbol::{Ident, Symbol};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use std::collections::HashMap;
+use rustc_data_structures::fx::FxHashSet;
 use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
@@ -117,6 +118,32 @@ impl Mark {
             true
         })
     }
+
+    /// Computes a mark such that both input marks are descendants of (or equal to) the returned
+    /// mark. That is, the following holds:
+    ///
+    /// ```rust
+    /// let la = least_ancestor(a, b);
+    /// assert!(a.is_descendant_of(la))
+    /// assert!(b.is_descendant_of(la))
+    /// ```
+    pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
+        HygieneData::with(|data| {
+            // Compute the path from a to the root
+            let mut a_path = FxHashSet::<Mark>();
+            while a != Mark::root() {
+                a_path.insert(a);
+                a = data.marks[a.0 as usize].parent;
+            }
+
+            // While the path from b to the root hasn't intersected, move up the tree
+            while !a_path.contains(&b) {
+                b = data.marks[b.0 as usize].parent;
+            }
+
+            b
+        })
+    }
 }
 
 pub struct HygieneData {
@@ -238,6 +265,22 @@ impl SyntaxContext {
         })
     }
 
+    /// Pulls a single mark off of the syntax context. This effectively moves the
+    /// context up one macro definition level. That is, if we have a nested macro
+    /// definition as follows:
+    ///
+    /// ```rust
+    /// macro_rules! f {
+    ///    macro_rules! g {
+    ///        ...
+    ///    }
+    /// }
+    /// ```
+    ///
+    /// and we have a SyntaxContext that is referring to something declared by an invocation
+    /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
+    /// invocation of f that created g1.
+    /// Returns the mark that was removed.
     pub fn remove_mark(&mut self) -> Mark {
         HygieneData::with(|data| {
             let outer_mark = data.syntax_contexts[self.0 as usize].outer_mark;
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9a7d1fd8ee6..8b4a3ea26a1 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -291,6 +291,12 @@ impl Span {
         self.ctxt().outer().expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self)
     }
 
+    /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
+    /// if any
+    pub fn parent(self) -> Option<Span> {
+        self.ctxt().outer().expn_info().map(|i| i.call_site)
+    }
+
     /// Return the source callee.
     ///
     /// Returns None if the supplied span has no expansion trace,
@@ -1144,13 +1150,17 @@ pub struct CharPos(pub usize);
 // have been unsuccessful
 
 impl Pos for BytePos {
+    #[inline(always)]
     fn from_usize(n: usize) -> BytePos { BytePos(n as u32) }
+
+    #[inline(always)]
     fn to_usize(&self) -> usize { let BytePos(n) = *self; n as usize }
 }
 
 impl Add for BytePos {
     type Output = BytePos;
 
+    #[inline(always)]
     fn add(self, rhs: BytePos) -> BytePos {
         BytePos((self.to_usize() + rhs.to_usize()) as u32)
     }
@@ -1159,6 +1169,7 @@ impl Add for BytePos {
 impl Sub for BytePos {
     type Output = BytePos;
 
+    #[inline(always)]
     fn sub(self, rhs: BytePos) -> BytePos {
         BytePos((self.to_usize() - rhs.to_usize()) as u32)
     }
@@ -1177,13 +1188,17 @@ impl Decodable for BytePos {
 }
 
 impl Pos for CharPos {
+    #[inline(always)]
     fn from_usize(n: usize) -> CharPos { CharPos(n) }
+
+    #[inline(always)]
     fn to_usize(&self) -> usize { let CharPos(n) = *self; n }
 }
 
 impl Add for CharPos {
     type Output = CharPos;
 
+    #[inline(always)]
     fn add(self, rhs: CharPos) -> CharPos {
         CharPos(self.to_usize() + rhs.to_usize())
     }
@@ -1192,6 +1207,7 @@ impl Add for CharPos {
 impl Sub for CharPos {
     type Output = CharPos;
 
+    #[inline(always)]
     fn sub(self, rhs: CharPos) -> CharPos {
         CharPos(self.to_usize() - rhs.to_usize())
     }
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 556ee162c6e..4a8b1e8b1c1 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -18,6 +18,7 @@ use {Span, DUMMY_SP, GLOBALS};
 use rustc_data_structures::fx::FxHashMap;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
+use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::hash::{Hash, Hasher};
 
 #[derive(Copy, Clone, Eq)]
@@ -36,6 +37,11 @@ impl Ident {
         Ident::new(name, DUMMY_SP)
     }
 
+    /// Maps an interned string to an identifier with an empty syntax context.
+    pub fn from_interned_str(string: InternedString) -> Ident {
+        Ident::with_empty_ctxt(string.as_symbol())
+    }
+
     /// Maps a string to an identifier with an empty syntax context.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_empty_ctxt(Symbol::intern(string))
@@ -138,14 +144,20 @@ impl Symbol {
         with_interner(|interner| interner.gensymed(self))
     }
 
-    pub fn as_str(self) -> InternedString {
+    pub fn as_str(self) -> LocalInternedString {
         with_interner(|interner| unsafe {
-            InternedString {
+            LocalInternedString {
                 string: ::std::mem::transmute::<&str, &str>(interner.get(self))
             }
         })
     }
 
+    pub fn as_interned_str(self) -> InternedString {
+        with_interner(|interner| InternedString {
+            symbol: interner.interned(self)
+        })
+    }
+
     pub fn as_u32(self) -> u32 {
         self.0
     }
@@ -365,84 +377,208 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
     GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
 }
 
-/// Represents a string stored in the thread-local interner. Because the
-/// interner lives for the life of the thread, this can be safely treated as an
-/// immortal string, as long as it never crosses between threads.
-///
-/// FIXME(pcwalton): You must be careful about what you do in the destructors
-/// of objects stored in TLS, because they may run after the interner is
-/// destroyed. In particular, they must not access string contents. This can
-/// be fixed in the future by just leaking all strings until thread death
-/// somehow.
+/// Represents a string stored in the interner. Because the interner outlives any thread
+/// which uses this type, we can safely treat `string` which points to interner data,
+/// as an immortal string, as long as this type never crosses between threads.
+// FIXME: Ensure that the interner outlives any thread which uses LocalInternedString,
+//        by creating a new thread right after constructing the interner
 #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
-pub struct InternedString {
+pub struct LocalInternedString {
     string: &'static str,
 }
 
-impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
+impl LocalInternedString {
+    pub fn as_interned_str(self) -> InternedString {
+        InternedString {
+            symbol: Symbol::intern(self.string)
+        }
+    }
+}
+
+impl<U: ?Sized> ::std::convert::AsRef<U> for LocalInternedString
+where
+    str: ::std::convert::AsRef<U>
+{
     fn as_ref(&self) -> &U {
         self.string.as_ref()
     }
 }
 
-impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
+impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for LocalInternedString {
     fn eq(&self, other: &T) -> bool {
         self.string == other.deref()
     }
 }
 
-impl ::std::cmp::PartialEq<InternedString> for str {
-    fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for str {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         self == other.string
     }
 }
 
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
-    fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a str {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         *self == other.string
     }
 }
 
-impl ::std::cmp::PartialEq<InternedString> for String {
-    fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for String {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         self == other.string
     }
 }
 
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
-    fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a String {
+    fn eq(&self, other: &LocalInternedString) -> bool {
         *self == other.string
     }
 }
 
-impl !Send for InternedString { }
+impl !Send for LocalInternedString {}
+impl !Sync for LocalInternedString {}
 
-impl ::std::ops::Deref for InternedString {
+impl ::std::ops::Deref for LocalInternedString {
     type Target = str;
     fn deref(&self) -> &str { self.string }
 }
 
-impl fmt::Debug for InternedString {
+impl fmt::Debug for LocalInternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(self.string, f)
     }
 }
 
-impl fmt::Display for InternedString {
+impl fmt::Display for LocalInternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(self.string, f)
     }
 }
 
+impl Decodable for LocalInternedString {
+    fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
+        Ok(Symbol::intern(&d.read_str()?).as_str())
+    }
+}
+
+impl Encodable for LocalInternedString {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(self.string)
+    }
+}
+
+/// Represents a string stored in the string interner
+#[derive(Clone, Copy, Eq)]
+pub struct InternedString {
+    symbol: Symbol,
+}
+
+impl InternedString {
+    pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
+        let str = with_interner(|interner| {
+            interner.get(self.symbol) as *const str
+        });
+        // This is safe because the interner keeps string alive until it is dropped.
+        // We can access it because we know the interner is still alive since we use a
+        // scoped thread local to access it, and it was alive at the begining of this scope
+        unsafe { f(&*str) }
+    }
+
+    pub fn as_symbol(self) -> Symbol {
+        self.symbol
+    }
+
+    pub fn as_str(self) -> LocalInternedString {
+        self.symbol.as_str()
+    }
+}
+
+impl Hash for InternedString {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.with(|str| str.hash(state))
+    }
+}
+
+impl PartialOrd<InternedString> for InternedString {
+    fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
+        if self.symbol == other.symbol {
+            return Some(Ordering::Equal);
+        }
+        self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str)))
+    }
+}
+
+impl Ord for InternedString {
+    fn cmp(&self, other: &InternedString) -> Ordering {
+        if self.symbol == other.symbol {
+            return Ordering::Equal;
+        }
+        self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str)))
+    }
+}
+
+impl<T: ::std::ops::Deref<Target = str>> PartialEq<T> for InternedString {
+    fn eq(&self, other: &T) -> bool {
+        self.with(|string| string == other.deref())
+    }
+}
+
+impl PartialEq<InternedString> for InternedString {
+    fn eq(&self, other: &InternedString) -> bool {
+        self.symbol == other.symbol
+    }
+}
+
+impl PartialEq<InternedString> for str {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| self == string)
+    }
+}
+
+impl<'a> PartialEq<InternedString> for &'a str {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| *self == string)
+    }
+}
+
+impl PartialEq<InternedString> for String {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| self == string)
+    }
+}
+
+impl<'a> PartialEq<InternedString> for &'a String {
+    fn eq(&self, other: &InternedString) -> bool {
+        other.with(|string| *self == string)
+    }
+}
+
+impl ::std::convert::From<InternedString> for String {
+    fn from(val: InternedString) -> String {
+        val.as_symbol().to_string()
+    }
+}
+
+impl fmt::Debug for InternedString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.with(|str| fmt::Debug::fmt(&str, f))
+    }
+}
+
+impl fmt::Display for InternedString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.with(|str| fmt::Display::fmt(&str, f))
+    }
+}
+
 impl Decodable for InternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
-        Ok(Symbol::intern(&d.read_str()?).as_str())
+        Ok(Symbol::intern(&d.read_str()?).as_interned_str())
     }
 }
 
 impl Encodable for InternedString {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self.string)
+        self.with(|string| s.emit_str(string))
     }
 }
 
diff --git a/src/stage0.txt b/src/stage0.txt
index e8db3358cf0..a5ad2b315a1 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-04-04
+date: 2018-04-24
 rustc: beta
 cargo: beta
 
diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs
index 155319cb154..f306608f432 100644
--- a/src/test/codegen/align-struct.rs
+++ b/src/test/codegen/align-struct.rs
@@ -29,7 +29,6 @@ pub enum Enum4 {
     A(i32),
     B(i32),
 }
-// CHECK: %Enum4 = type { [0 x i32], i32, [1 x i32] }
 // CHECK: %"Enum4::A" = type { [1 x i32], i32, [0 x i32] }
 
 pub enum Enum64 {
@@ -59,7 +58,7 @@ pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 {
 // CHECK-LABEL: @enum4
 #[no_mangle]
 pub fn enum4(a: i32) -> Enum4 {
-// CHECK: %e4 = alloca %Enum4, align 4
+// CHECK: %e4 = alloca { i32, i32 }, align 4
     let e4 = Enum4::A(a);
     e4
 }
diff --git a/src/test/codegen/call-metadata.rs b/src/test/codegen/call-metadata.rs
new file mode 100644
index 00000000000..20d42ed852d
--- /dev/null
+++ b/src/test/codegen/call-metadata.rs
@@ -0,0 +1,29 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks that range metadata gets emitted on calls to functions returning a
+// scalar value.
+
+// compile-flags: -C no-prepopulate-passes
+// min-llvm-version 4.0
+
+
+#![crate_type = "lib"]
+
+pub fn test() {
+    // CHECK: call i8 @some_true(), !range [[R0:![0-9]+]]
+    // CHECK: [[R0]] = !{i8 0, i8 3}
+    some_true();
+}
+
+#[no_mangle]
+fn some_true() -> Option<bool> {
+    Some(true)
+}
diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/codegen/force-frame-pointers.rs
index 5f741d010de..f70e3667198 100644
--- a/src/test/compile-fail/macro-reexport-malformed-2.rs
+++ b/src/test/codegen/force-frame-pointers.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -7,10 +7,10 @@
 // <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: -C no-prepopulate-passes -C force-frame-pointers=y
 
-#![no_std]
-#![feature(macro_reexport)]
+#![crate_type="lib"]
 
-#[allow(unused_extern_crates)]
-#[macro_reexport="foo"]  //~ ERROR bad macro re-export
-extern crate std;
+// CHECK: attributes #{{.*}} "no-frame-pointer-elim"="true"
+pub fn foo() {}
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index de302c69056..40a9ea5a181 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -145,6 +145,18 @@ pub fn return_slice(x: &[u16]) -> &[u16] {
   x
 }
 
+// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1)
+#[no_mangle]
+pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
+  x
+}
+
+// CHECK: i16 @enum_id_2(i16)
+#[no_mangle]
+pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
+  x
+}
+
 // CHECK: noalias i8* @allocator()
 #[no_mangle]
 #[allocator]
diff --git a/src/test/codegen/lifetime_start_end.rs b/src/test/codegen/lifetime_start_end.rs
index 62aa93398ac..ea3f0de5d08 100644
--- a/src/test/codegen/lifetime_start_end.rs
+++ b/src/test/codegen/lifetime_start_end.rs
@@ -25,16 +25,16 @@ pub fn test() {
         let b = &Some(a);
         &b; // keep variable in an alloca
 
-// CHECK: [[S_b:%[0-9]+]] = bitcast %"core::option::Option<i32>"** %b to i8*
+// CHECK: [[S_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8*
 // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S_b]])
 
-// CHECK: [[S__4:%[0-9]+]] = bitcast %"core::option::Option<i32>"* %_4 to i8*
+// CHECK: [[S__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8*
 // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S__4]])
 
-// CHECK: [[E_b:%[0-9]+]] = bitcast %"core::option::Option<i32>"** %b to i8*
+// CHECK: [[E_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8*
 // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E_b]])
 
-// CHECK: [[E__4:%[0-9]+]] = bitcast %"core::option::Option<i32>"* %_4 to i8*
+// CHECK: [[E__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8*
 // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E__4]])
     }
 
diff --git a/src/test/codegen/noreturnflag.rs b/src/test/codegen/noreturnflag.rs
index 24a5a4e44cb..7239223ca20 100644
--- a/src/test/codegen/noreturnflag.rs
+++ b/src/test/codegen/noreturnflag.rs
@@ -8,17 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -g -C no-prepopulate-passes
 // ignore-tidy-linelength
 // min-llvm-version 4.0
 
-// compile-flags: -g -C no-prepopulate-passes
-
-// CHECK: {{.*}}DISubprogram{{.*}}name: "foo"{{.*}}DIFlagNoReturn
+#![crate_type = "lib"]
 
-fn foo() -> ! {
+#[no_mangle]
+pub fn foo() -> ! {
+// CHECK: @foo() unnamed_addr #0
     loop {}
 }
 
-pub fn main() {
-    foo();
+pub enum EmptyEnum {}
+
+#[no_mangle]
+pub fn bar() -> EmptyEnum {
+// CHECK: @bar() unnamed_addr #0
+    loop {}
 }
+
+// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}}
+
+// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn
+// CHECK: DISubprogram(name: "bar", {{.*}} DIFlagNoReturn
diff --git a/src/test/codegen/target-feature-on-functions.rs b/src/test/codegen/target-feature-on-functions.rs
new file mode 100644
index 00000000000..e3cc2c753e5
--- /dev/null
+++ b/src/test/codegen/target-feature-on-functions.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.
+
+// only-x86_64
+// compile-flags: -C target-feature=+avx
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn foo() {
+    // CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} }
+}
diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
index 040f0b661be..fb0f9105b0d 100644
--- a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
+++ b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
@@ -117,7 +117,7 @@ fn expand_duplicate(cx: &mut ExtCtxt,
     let copy_name = match mi.node {
         ast::MetaItemKind::List(ref xs) => {
             if let Some(word) = xs[0].word() {
-                word.ident
+                word.ident.segments.last().unwrap().ident
             } else {
                 cx.span_err(mi.span, "Expected word");
                 return;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
index 0dc1c2ab2da..fff433b90ce 100644
--- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
+++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
@@ -24,9 +24,17 @@ use foo::*;
 #[foo::a] //~ ERROR: paths of length greater than one
 fn _test() {}
 
+fn _test_inner() {
+    #![a] // OK
+}
+
 #[a] //~ ERROR: custom attributes cannot be applied to modules
 mod _test2 {}
 
+mod _test2_inner {
+    #![a] //~ ERROR: custom attributes cannot be applied to modules
+}
+
 #[a = y] //~ ERROR: must only be followed by a delimiter token
 fn _test3() {}
 
@@ -36,19 +44,40 @@ fn _test4() {}
 #[a () = ] //~ ERROR: must only be followed by a delimiter token
 fn _test5() {}
 
-fn main() {
+fn attrs() {
+    // Statement, item
+    #[a] // OK
+    struct S;
+
+    // Statement, macro
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    println!();
+
+    // Statement, semi
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    S;
+
+    // Statement, local
     #[a] //~ ERROR: custom attributes cannot be applied to statements
     let _x = 2;
-    let _x = #[a] 2;
-    //~^ ERROR: custom attributes cannot be applied to expressions
-
-    let _x: m!(u32) = 3;
-    //~^ ERROR: procedural macros cannot be expanded to types
-    if let m!(Some(_x)) = Some(3) {
-    //~^ ERROR: procedural macros cannot be expanded to patterns
-    }
-    let _x = m!(3);
-    //~^ ERROR: procedural macros cannot be expanded to expressions
-    m!(let _x = 3;);
-    //~^ ERROR: procedural macros cannot be expanded to statements
+
+    // Expr
+    let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions
+
+    // Opt expr
+    let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions
+
+    // Expr macro
+    let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions
+}
+
+fn main() {
+    let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types
+    if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns
+
+    m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements
+    m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements
+
+    let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions
+    let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions
 }
diff --git a/src/test/compile-fail/attr-usage-inline.rs b/src/test/compile-fail/attr-usage-inline.rs
index c6b9b016331..250905dbdcd 100644
--- a/src/test/compile-fail/attr-usage-inline.rs
+++ b/src/test/compile-fail/attr-usage-inline.rs
@@ -13,7 +13,7 @@
 #[inline]
 fn f() {}
 
-#[inline] //~ ERROR: attribute should be applied to function
+#[inline] //~ ERROR: attribute should be applied to function or closure
 struct S;
 
 fn main() {}
diff --git a/src/test/compile-fail/auxiliary/macro_non_reexport_2.rs b/src/test/compile-fail/auxiliary/macro_non_reexport_2.rs
deleted file mode 100644
index 910fcd2e367..00000000000
--- a/src/test/compile-fail/auxiliary/macro_non_reexport_2.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_type = "dylib"]
-
-// Since we load a serialized macro with all its attributes, accidentally
-// re-exporting a `#[macro_export] macro_rules!` is something of a concern!
-//
-// We avoid it at the moment only because of the order in which we do things.
-
-#[macro_use] #[no_link]
-extern crate macro_reexport_1;
diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
index 1333167b780..1e86603c19e 100644
--- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
+++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs
@@ -10,7 +10,7 @@
 
 // ignore-tidy-linelength
 
-// revisions: nll_beyond nll_target
+// revisions: nll_target
 
 // The following revisions are disabled due to missing support from two-phase beyond autorefs
 //[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
diff --git a/src/test/compile-fail/extern-macro.rs b/src/test/compile-fail/extern-macro.rs
index 08269ce5c7e..4267103ab9a 100644
--- a/src/test/compile-fail/extern-macro.rs
+++ b/src/test/compile-fail/extern-macro.rs
@@ -10,7 +10,7 @@
 
 // #41719
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 fn main() {
     enum Foo {}
diff --git a/src/test/compile-fail/feature-gate-tool_attributes.rs b/src/test/compile-fail/feature-gate-tool_attributes.rs
new file mode 100644
index 00000000000..5a7536ca330
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-tool_attributes.rs
@@ -0,0 +1,15 @@
+// Copyright 2018 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() {
+    #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+    let x =
+        3;
+}
diff --git a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
index eea7ca20957..d6707f59011 100644
--- a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
+++ b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
@@ -28,4 +28,15 @@ impl Bar for () {
     //~^ Error method `bar` has incompatible signature for trait
 }
 
+// With non-local trait (#49841):
+
+use std::hash::{Hash, Hasher};
+
+struct X;
+
+impl Hash for X {
+    fn hash(&self, hasher: &mut impl Hasher) {}
+    //~^ Error method `hash` has incompatible signature for trait
+}
+
 fn main() {}
diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs
index 038eacaf110..2891cd59e3e 100644
--- a/src/test/compile-fail/impl-trait/where-allowed.rs
+++ b/src/test/compile-fail/impl-trait/where-allowed.rs
@@ -10,7 +10,6 @@
 
 //! A simple test for testing many permutations of allowedness of
 //! impl Trait
-#![feature(dyn_trait)]
 use std::fmt::Debug;
 
 // Allowed
diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs
index 2aa87f8424b..fc365a4b9aa 100644
--- a/src/test/compile-fail/issue-23080-2.rs
+++ b/src/test/compile-fail/issue-23080-2.rs
@@ -10,6 +10,8 @@
 
 // ignore-tidy-linelength
 
+//~^^^^^^^^^^^^ ERROR
+
 #![feature(optin_builtin_traits)]
 
 unsafe auto trait Trait {
@@ -22,5 +24,4 @@ fn call_method<T: Trait>(x: T) {}
 fn main() {
     // ICE
     call_method(());
-    //~^ ERROR
 }
diff --git a/src/test/compile-fail/issue-31769.rs b/src/test/compile-fail/issue-31769.rs
index 7f73d9076ec..2bd45deeab4 100644
--- a/src/test/compile-fail/issue-31769.rs
+++ b/src/test/compile-fail/issue-31769.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    #[inline] struct Foo;  //~ ERROR attribute should be applied to function
+    #[inline] struct Foo;  //~ ERROR attribute should be applied to function or closure
     #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum or union
 }
diff --git a/src/test/compile-fail/issue-43988.rs b/src/test/compile-fail/issue-43988.rs
index ff1fdaef416..0dfa9f6f0d3 100644
--- a/src/test/compile-fail/issue-43988.rs
+++ b/src/test/compile-fail/issue-43988.rs
@@ -14,12 +14,12 @@ fn main() {
 
     #[inline]
     let _a = 4;
-    //~^^ ERROR attribute should be applied to function
+    //~^^ ERROR attribute should be applied to function or closure
 
 
     #[inline(XYZ)]
     let _b = 4;
-    //~^^ ERROR attribute should be applied to function
+    //~^^ ERROR attribute should be applied to function or closure
 
     #[repr(nothing)]
     let _x = 0;
@@ -40,7 +40,7 @@ fn main() {
 
     #[inline(ABC)]
     foo();
-    //~^^ ERROR attribute should be applied to function
+    //~^^ ERROR attribute should be applied to function or closure
 
     let _z = #[repr] 1;
     //~^ ERROR attribute should not be applied to an expression
diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs
index 3c76740d2b5..14d836074dc 100644
--- a/src/test/compile-fail/lint-unused-mut-variables.rs
+++ b/src/test/compile-fail/lint-unused-mut-variables.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: lexical nll
+#![cfg_attr(nll, feature(nll))]
+
 // Exercise the unused_mut attribute in some positive and negative cases
 
 #![allow(unused_assignments)]
@@ -18,15 +21,22 @@
 
 fn main() {
     // negative cases
-    let mut a = 3; //~ ERROR: variable does not need to be mutable
-    let mut a = 2; //~ ERROR: variable does not need to be mutable
-    let mut b = 3; //~ ERROR: variable does not need to be mutable
-    let mut a = vec![3]; //~ ERROR: variable does not need to be mutable
-    let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable
-    let mut a; //~ ERROR: variable does not need to be mutable
+    let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable
+                   //[nll]~^ ERROR: variable does not need to be mutable
+    let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable
+                   //[nll]~^ ERROR: variable does not need to be mutable
+    let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable
+                   //[nll]~^ ERROR: variable does not need to be mutable
+    let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable
+                         //[nll]~^ ERROR: variable does not need to be mutable
+    let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable
+                             //[nll]~^ ERROR: variable does not need to be mutable
+    let mut a; //[lexical]~ ERROR: variable does not need to be mutable
+               //[nll]~^ ERROR: variable does not need to be mutable
     a = 3;
 
-    let mut b; //~ ERROR: variable does not need to be mutable
+    let mut b; //[lexical]~ ERROR: variable does not need to be mutable
+               //[nll]~^ ERROR: variable does not need to be mutable
     if true {
         b = 3;
     } else {
@@ -34,37 +44,45 @@ fn main() {
     }
 
     match 30 {
-        mut x => {} //~ ERROR: variable does not need to be mutable
+        mut x => {} //[lexical]~ ERROR: variable does not need to be mutable
+                    //[nll]~^ ERROR: variable does not need to be mutable
     }
     match (30, 2) {
-      (mut x, 1) | //~ ERROR: variable does not need to be mutable
+      (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable
+                   //[nll]~^ ERROR: variable does not need to be mutable
       (mut x, 2) |
       (mut x, 3) => {
       }
       _ => {}
     }
 
-    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 x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable
+                               //[nll]~^ ERROR: variable does not need to be mutable
+    fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable
+                               //[nll]~^ ERROR: variable does not need to be mutable
 
-    let mut a = &mut 5; //~ ERROR: variable does not need to be mutable
+    let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable
+                        //[nll]~^ 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 b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable
+    *b.0 = 4;              //[nll]~^ ERROR: variable does not need to be mutable
 
-    let mut x = &mut 1; //~ ERROR: variable does not need to be mutable
+    let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable
+                        //[nll]~^ 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
+        &mut arg[..] //[lexical]~^ ERROR: variable does not need to be mutable
+                     //[nll]~^^ ERROR: variable does not need to be mutable
     }
 
-    let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable
+    let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable
+                                            //[nll]~^ ERROR: variable does not need to be mutable
     v.push(());
 
     // positive cases
@@ -76,6 +94,12 @@ fn main() {
     callback(|| {
         a.push(3);
     });
+    let mut a = Vec::new();
+    callback(|| {
+        callback(|| {
+            a.push(3);
+        });
+    });
     let (mut a, b) = (1, 2);
     a = 34;
 
@@ -116,5 +140,6 @@ fn foo(mut a: isize) {
 fn bar() {
     #[allow(unused_mut)]
     let mut a = 3;
-    let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
+    let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable
+                         //[nll]~^ ERROR: variable does not need to be mutable
 }
diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-non-lifetime.rs
index 54a74b0e134..a2706e83229 100644
--- a/src/test/compile-fail/macro-reexport-not-locally-visible.rs
+++ b/src/test/compile-fail/macro-non-lifetime.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,15 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:macro_reexport_1.rs
+// Test for issue #50381: non-lifetime passed to :lifetime.
 
-#![feature(macro_reexport)]
+#![feature(macro_lifetime_matcher)]
 
-#[macro_reexport(reexported)]
-#[no_link]
-extern crate macro_reexport_1;
+macro_rules! m { ($x:lifetime) => { } }
 
 fn main() {
-    assert_eq!(reexported!(), 3);
-    //~^ ERROR cannot find macro
+    m!(a);
+    //~^ ERROR expected a lifetime, found `a`
 }
diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs
index 40412087cef..7046ee12b50 100644
--- a/src/test/compile-fail/macros-nonfatal-errors.rs
+++ b/src/test/compile-fail/macros-nonfatal-errors.rs
@@ -13,7 +13,6 @@
 
 #![feature(asm)]
 #![feature(trace_macros, concat_idents)]
-#![feature(proc_macro_path_invoc)]
 
 #[derive(Default)] //~ ERROR
 enum OrDeriveThis {}
diff --git a/src/test/compile-fail/mir_check_cast_unsize.rs b/src/test/compile-fail/mir_check_cast_unsize.rs
index e30bed61058..a2c840a7098 100644
--- a/src/test/compile-fail/mir_check_cast_unsize.rs
+++ b/src/test/compile-fail/mir_check_cast_unsize.rs
@@ -11,7 +11,6 @@
 // compile-flags: -Z borrowck=mir
 
 #![allow(dead_code)]
-#![feature(dyn_trait)]
 
 use std::fmt::Debug;
 
diff --git a/src/test/compile-fail/nll/match-guards-always-borrow.rs b/src/test/compile-fail/nll/match-guards-always-borrow.rs
new file mode 100644
index 00000000000..98553144627
--- /dev/null
+++ b/src/test/compile-fail/nll/match-guards-always-borrow.rs
@@ -0,0 +1,61 @@
+// Copyright 2012-2014 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.
+
+//revisions: ast mir
+//[mir] compile-flags: -Z borrowck=mir
+
+#![feature(rustc_attrs)]
+
+// Here is arielb1's basic example from rust-lang/rust#27282
+// that AST borrowck is flummoxed by:
+
+fn should_reject_destructive_mutate_in_guard() {
+    match Some(&4) {
+        None => {},
+        ref mut foo if {
+            (|| { let bar = foo; bar.take() })();
+            //[mir]~^ ERROR cannot move out of borrowed content [E0507]
+            false } => { },
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Here below is a case that needs to keep working: we only use the
+// binding via immutable-borrow in the guard, and we mutate in the arm
+// body.
+fn allow_mutate_in_arm_body() {
+    match Some(&4) {
+        None => {},
+        ref mut foo if foo.is_some() && false => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Here below is a case that needs to keep working: we only use the
+// binding via immutable-borrow in the guard, and we move into the arm
+// body.
+fn allow_move_into_arm_body() {
+    match Some(&4) {
+        None => {},
+        mut foo if foo.is_some() && false => { foo.take(); () }
+        Some(s) => std::process::exit(*s),
+    }
+}
+
+// Since this is a compile-fail test that is explicitly encoding the
+// different behavior of AST- vs MIR-borrowck where AST-borrowck does
+// not error, we need to use rustc_error to placate the test harness
+// that wants *some* error to occur.
+#[rustc_error]
+fn main() { //[ast]~ ERROR compilation successful
+    should_reject_destructive_mutate_in_guard();
+    allow_mutate_in_arm_body();
+    allow_move_into_arm_body();
+}
diff --git a/src/test/compile-fail/nll/unused-mut-issue-50343.rs b/src/test/compile-fail/nll/unused-mut-issue-50343.rs
new file mode 100644
index 00000000000..e9110b8114b
--- /dev/null
+++ b/src/test/compile-fail/nll/unused-mut-issue-50343.rs
@@ -0,0 +1,17 @@
+// Copyright 2012 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.
+
+#![feature(nll)]
+#![deny(unused_mut)]
+
+fn main() {
+    vec![(42, 22)].iter().map(|(mut x, _y)| ()).count();
+    //~^ ERROR: variable does not need to be mutable
+}
diff --git a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
index b64829edaa2..63cb6e82c25 100644
--- a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
+++ b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
@@ -10,7 +10,6 @@
 
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
-#![feature(proc_macro_path_invoc)]
 
 mod priv_nominal {
     pub struct Pub;
diff --git a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs
index 062dc533617..bdc0c680a92 100644
--- a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs
+++ b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs
@@ -10,7 +10,6 @@
 
 // ignore-tidy-linelength
 
-#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
diff --git a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
index 0dfa61a18ab..c25616c5435 100644
--- a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
+++ b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs
index 97d6b470d33..0c393f02323 100644
--- a/src/test/compile-fail/private-inferred-type-3.rs
+++ b/src/test/compile-fail/private-inferred-type-3.rs
@@ -18,7 +18,6 @@
 // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
 // error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
 
-#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro)]
 
 extern crate private_inferred_type as ext;
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
index dfc0107e075..5af8b063c16 100644
--- a/src/test/compile-fail/private-inferred-type.rs
+++ b/src/test/compile-fail/private-inferred-type.rs
@@ -11,7 +11,6 @@
 #![feature(associated_consts)]
 #![feature(decl_macro)]
 #![allow(private_in_public)]
-#![feature(proc_macro_path_invoc)]
 
 mod m {
     fn priv_fn() {}
diff --git a/src/test/compile-fail/repr-align.rs b/src/test/compile-fail/repr-align.rs
index 7c8eb6a2de9..9b0408de2a4 100644
--- a/src/test/compile-fail/repr-align.rs
+++ b/src/test/compile-fail/repr-align.rs
@@ -15,7 +15,10 @@ struct A(i32);
 #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
 struct B(i32);
 
-#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2147483647
+#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29
 struct C(i32);
 
+#[repr(align(536870912))] // ok: this is the largest accepted alignment
+struct D(i32);
+
 fn main() {}
diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs
index 0dd1a4e7d73..1b1a238a941 100644
--- a/src/test/compile-fail/trait-bounds-not-on-struct.rs
+++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(dyn_trait)]
 #![allow(bare_trait_object)]
 
 struct Foo;
diff --git a/src/test/compile-fail/unknown-tool-name.rs b/src/test/compile-fail/unknown-tool-name.rs
new file mode 100644
index 00000000000..c2192a21d90
--- /dev/null
+++ b/src/test/compile-fail/unknown-tool-name.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![feature(tool_attributes)]
+
+#![foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
+
+#[foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
+fn main() {}
diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/unknown_tool_attributes-1.rs
new file mode 100644
index 00000000000..ba38c297a11
--- /dev/null
+++ b/src/test/compile-fail/unknown_tool_attributes-1.rs
@@ -0,0 +1,18 @@
+// Copyright 2018 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.
+
+// Make sure that 'custom_attributes' feature does not allow scoped attributes.
+
+#![feature(custom_attributes)]
+
+#[foo::bar]
+//~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658]
+//~^^ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
+fn main() {}
diff --git a/src/test/compile-fail/used.rs b/src/test/compile-fail/used.rs
new file mode 100644
index 00000000000..f170d9c25f5
--- /dev/null
+++ b/src/test/compile-fail/used.rs
@@ -0,0 +1,28 @@
+// Copyright 2018 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.
+
+#![feature(used)]
+
+#[used]
+static FOO: u32 = 0; // OK
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+fn foo() {}
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+struct Foo {}
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+trait Bar {}
+
+#[used] //~ ERROR attribute must be applied to a `static` variable
+impl Bar for Foo {}
+
+fn main() {}
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
index 53f17861997..a31298a0f51 100644
--- a/src/test/mir-opt/match_false_edges.rs
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -54,17 +54,17 @@ fn main() {
 //      ...
 //      _2 = std::option::Option<i32>::Some(const 42i32,);
 //      _3 = discriminant(_2);
-//      _6 = discriminant(_2);
-//      switchInt(move _6) -> [0isize: bb6, 1isize: bb4, otherwise: bb8];
+//      _7 = discriminant(_2);
+//      switchInt(move _7) -> [0isize: bb6, 1isize: bb4, otherwise: bb8];
 //  }
 //  bb1: {
 //      resume;
 //  }
 //  bb2: {  // arm1
-//      StorageLive(_8);
-//      _8 = _4;
-//      _1 = (const 1i32, move _8);
-//      StorageDead(_8);
+//      StorageLive(_9);
+//      _9 = _4;
+//      _1 = (const 1i32, move _9);
+//      StorageDead(_9);
 //      goto -> bb13;
 //  }
 //  bb3: { // binding3(empty) and arm3
@@ -87,24 +87,26 @@ fn main() {
 //      unreachable;
 //  }
 //  bb9: { // binding1 and guard
-//      StorageLive(_4);
-//      _4 = ((_2 as Some).0: i32);
-//      StorageLive(_7);
-//      _7 = const guard() -> [return: bb10, unwind: bb1];
+//      StorageLive(_5);
+//      _5 = &((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = const guard() -> [return: bb10, unwind: bb1];
 //  }
 //  bb10: { // end of guard
-//      switchInt(move _7) -> [false: bb11, otherwise: bb2];
+//      StorageLive(_4);
+//      _4 = ((_2 as Some).0: i32);
+//      switchInt(move _8) -> [false: bb11, otherwise: bb2];
 //  }
 //  bb11: { // to pre_binding2
 //      falseEdges -> [real: bb5, imaginary: bb5];
 //  }
 //  bb12: { // bindingNoLandingPads.before.mir2 and arm2
-//      StorageLive(_5);
-//      _5 = ((_2 as Some).0: i32);
-//      StorageLive(_9);
-//      _9 = _5;
-//      _1 = (const 2i32, move _9);
-//      StorageDead(_9);
+//      StorageLive(_6);
+//      _6 = ((_2 as Some).0: i32);
+//      StorageLive(_10);
+//      _10 = _6;
+//      _1 = (const 2i32, move _10);
+//      StorageDead(_10);
 //      goto -> bb13;
 //  }
 //  bb13: {
@@ -118,17 +120,17 @@ fn main() {
 //      ...
 //      _2 = std::option::Option<i32>::Some(const 42i32,);
 //      _3 = discriminant(_2);
-//      _6 = discriminant(_2);
-//      switchInt(move _6) -> [0isize: bb5, 1isize: bb4, otherwise: bb8];
+//      _7 = discriminant(_2);
+//      switchInt(move _7) -> [0isize: bb5, 1isize: bb4, otherwise: bb8];
 //  }
 //  bb1: {
 //      resume;
 //  }
 //  bb2: { // arm1
-//      StorageLive(_8);
-//      _8 = _4;
-//      _1 = (const 1i32, move _8);
-//      StorageDead(_8);
+//      StorageLive(_9);
+//      _9 = _4;
+//      _1 = (const 1i32, move _9);
+//      StorageDead(_9);
 //      goto -> bb13;
 //  }
 //  bb3: { // binding3(empty) and arm3
@@ -151,24 +153,26 @@ fn main() {
 //      unreachable;
 //  }
 //  bb9: { // binding1 and guard
-//      StorageLive(_4);
-//      _4 = ((_2 as Some).0: i32);
-//      StorageLive(_7);
-//      _7 = const guard() -> [return: bb10, unwind: bb1];
+//      StorageLive(_5);
+//      _5 = &((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = const guard() -> [return: bb10, unwind: bb1];
 //  }
 //  bb10: { // end of guard
-//      switchInt(move _7) -> [false: bb11, otherwise: bb2];
+//      StorageLive(_4);
+//      _4 = ((_2 as Some).0: i32);
+//      switchInt(move _8) -> [false: bb11, otherwise: bb2];
 //  }
 //  bb11: { // to pre_binding2
 //      falseEdges -> [real: bb6, imaginary: bb5];
 //  }
 //  bb12: { // binding2 and arm2
-//      StorageLive(_5);
-//      _5 = ((_2 as Some).0: i32);
-//      StorageLive(_9);
-//      _9 = _5;
-//      _1 = (const 2i32, move _9);
-//      StorageDead(_9);
+//      StorageLive(_6);
+//      _6 = ((_2 as Some).0: i32);
+//      StorageLive(_10);
+//      _10 = _6;
+//      _1 = (const 2i32, move _10);
+//      StorageDead(_10);
 //      goto -> bb13;
 //  }
 //  bb13: {
@@ -182,8 +186,8 @@ fn main() {
 //     ...
 //     _2 = std::option::Option<i32>::Some(const 1i32,);
 //     _3 = discriminant(_2);
-//     _8 = discriminant(_2);
-//     switchInt(move _8) -> [1isize: bb4, otherwise: bb5];
+//     _10 = discriminant(_2);
+//     switchInt(move _10) -> [1isize: bb4, otherwise: bb5];
 // }
 // bb1: {
 //     resume;
@@ -213,41 +217,45 @@ fn main() {
 //     unreachable;
 // }
 // bb9: { // binding1: Some(w) if guard()
-//     StorageLive(_4);
-//     _4 = ((_2 as Some).0: i32);
-//     StorageLive(_9);
-//     _9 = const guard() -> [return: bb10, unwind: bb1];
+//     StorageLive(_5);
+//     _5 = &((_2 as Some).0: i32);
+//     StorageLive(_11);
+//     _11 = const guard() -> [return: bb10, unwind: bb1];
 // }
 // bb10: { //end of guard
-//    switchInt(move _9) -> [false: bb11, otherwise: bb2];
+//    StorageLive(_4);
+//    _4 = ((_2 as Some).0: i32);
+//    switchInt(move _11) -> [false: bb11, otherwise: bb2];
 // }
 // bb11: { // to pre_binding2
 //     falseEdges -> [real: bb5, imaginary: bb5];
 // }
 // bb12: { // binding2 & arm2
-//     StorageLive(_5);
-//     _5 = _2;
+//     StorageLive(_6);
+//     _6 = _2;
 //     _1 = const 2i32;
 //     goto -> bb17;
 // }
 // bb13: { // binding3: Some(y) if guard2(y)
-//     StorageLive(_6);
-//     _6 = ((_2 as Some).0: i32);
-//     StorageLive(_11);
-//     StorageLive(_12);
-//     _12 = _6;
-//     _11 = const guard2(move _12) -> [return: bb14, unwind: bb1];
+//     StorageLive(_8);
+//     _8 = &((_2 as Some).0: i32);
+//     StorageLive(_13);
+//     StorageLive(_14);
+//     _14 = (*_8);
+//     _13 = const guard2(move _14) -> [return: bb14, unwind: bb1];
 // }
 // bb14: { // end of guard2
-//     StorageDead(_12);
-//     switchInt(move _11) -> [false: bb15, otherwise: bb3];
+//     StorageDead(_14);
+//     StorageLive(_7);
+//     _7 = ((_2 as Some).0: i32);
+//     switchInt(move _13) -> [false: bb15, otherwise: bb3];
 // }
 // bb15: { // to pre_binding4
 //     falseEdges -> [real: bb7, imaginary: bb7];
 // }
 // bb16: { // binding4 & arm4
-//     StorageLive(_7);
-//     _7 = _2;
+//     StorageLive(_9);
+//     _9 = _2;
 //     _1 = const 4i32;
 //     goto -> bb17;
 // }
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
index 219eca6fd21..66a6e6afed3 100644
--- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
+++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
@@ -11,8 +11,6 @@
 // compile-pass
 // failure-status: 1
 
-#![feature(dyn_trait)]
-
 use std::error::Error;
 use std::io;
 
diff --git a/src/test/run-make-fulldeps/extern-prelude/Makefile b/src/test/run-make-fulldeps/extern-prelude/Makefile
new file mode 100644
index 00000000000..aa8158c6eb3
--- /dev/null
+++ b/src/test/run-make-fulldeps/extern-prelude/Makefile
@@ -0,0 +1,12 @@
+-include ../tools.mk
+
+all:
+	$(RUSTC) ep-lib.rs
+	$(RUSTC) ep-vec.rs
+
+	$(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
+	$(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib
+	$(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib
+	$(RUSTC) feature-gate.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "access to extern crates through prelude is experimental"
+	$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import"
+	$(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve"
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs b/src/test/run-make-fulldeps/extern-prelude/basic.rs
index cfaf913216a..b8d6a772e2a 100644
--- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs
+++ b/src/test/run-make-fulldeps/extern-prelude/basic.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test not a test, auxiliary
+#![feature(extern_prelude)]
 
-#![feature(macro_reexport)]
-
-#[macro_reexport(A)]
-extern crate derive_a;
+fn main() {
+    let s = ep_lib::S; // It works
+    s.external();
+}
diff --git a/src/test/compile-fail/auxiliary/macro_reexport_1.rs b/src/test/run-make-fulldeps/extern-prelude/ep-lib.rs
index aaeccc6e898..dac0a3ce760 100644
--- a/src/test/compile-fail/auxiliary/macro_reexport_1.rs
+++ b/src/test/run-make-fulldeps/extern-prelude/ep-lib.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_type = "dylib"]
-#[macro_export]
-macro_rules! reexported {
-    () => ( 3 )
+#![crate_type = "rlib"]
+
+pub struct S;
+
+impl S {
+    pub fn external(&self) {}
 }
diff --git a/src/test/run-make-fulldeps/extern-prelude/ep-vec.rs b/src/test/run-make-fulldeps/extern-prelude/ep-vec.rs
new file mode 100644
index 00000000000..f750a26f9e6
--- /dev/null
+++ b/src/test/run-make-fulldeps/extern-prelude/ep-vec.rs
@@ -0,0 +1,13 @@
+// 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.
+
+#![crate_type = "rlib"]
+
+pub fn new(arg1: f32, arg2: ()) {}
diff --git a/src/test/run-pass/auxiliary/macro_reexport_1.rs b/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs
index aaeccc6e898..49763f3ba6a 100644
--- a/src/test/run-pass/auxiliary/macro_reexport_1.rs
+++ b/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_type = "dylib"]
-#[macro_export]
-macro_rules! reexported {
-    () => ( 3 )
+fn main() {
+    let s = ep_lib::S; // Feature error
 }
diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/run-make-fulldeps/extern-prelude/relative-only.rs
index 36a6fce00a1..0cd56b93de6 100644
--- a/src/test/compile-fail/macro-reexport-malformed-1.rs
+++ b/src/test/run-make-fulldeps/extern-prelude/relative-only.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![no_std]
-#![feature(macro_reexport)]
+// Extern prelude names are not available by absolute paths
 
-#[allow(unused_extern_crates)]
-#[macro_reexport]  //~ ERROR bad macro re-export
-extern crate std;
+#![feature(extern_prelude)]
+
+use ep_lib::S;
+
+fn main() {
+    let s = ::ep_lib::S;
+}
diff --git a/src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs b/src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs
new file mode 100644
index 00000000000..52213c8d4f9
--- /dev/null
+++ b/src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 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.
+
+// Local module shadows `ep_lib` from extern prelude
+
+mod ep_lib {
+    pub struct S;
+
+    impl S {
+        pub fn internal(&self) {}
+    }
+}
+
+fn main() {
+    let s = ep_lib::S;
+    s.internal(); // OK
+}
diff --git a/src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs b/src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs
new file mode 100644
index 00000000000..de1c4d16d39
--- /dev/null
+++ b/src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 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.
+
+// Extern prelude shadows standard library prelude
+
+#![feature(extern_prelude)]
+
+fn main() {
+    let x = Vec::new(0f32, ()); // OK
+}
diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile
index ec91ddfb9f9..a0bc8cf6688 100644
--- a/src/test/run-make-fulldeps/libtest-json/Makefile
+++ b/src/test/run-make-fulldeps/libtest-json/Makefile
@@ -6,7 +6,7 @@ OUTPUT_FILE := $(TMPDIR)/libtest-json-output.json
 
 all:
 	$(RUSTC) --test f.rs
-	$(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true
+	RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true
 
 	cat $(OUTPUT_FILE) | "$(PYTHON)" validate_json.py
 
diff --git a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
index 2f80408ac1c..d698af50579 100644
--- a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
@@ -112,7 +112,7 @@ fn expand_duplicate(cx: &mut ExtCtxt,
     let copy_name = match mi.node {
         ast::MetaItemKind::List(ref xs) => {
             if let Some(word) = xs[0].word() {
-                word.ident
+                word.ident.segments.last().unwrap().ident
             } else {
                 cx.span_err(mi.span, "Expected word");
                 return;
diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs
index 9bb8f691915..f359735d2f7 100644
--- a/src/test/run-pass-fulldeps/macro-quote-test.rs
+++ b/src/test/run-pass-fulldeps/macro-quote-test.rs
@@ -13,7 +13,7 @@
 // aux-build:hello_macro.rs
 // ignore-stage1
 
-#![feature(proc_macro, proc_macro_path_invoc, proc_macro_non_items)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate hello_macro;
 
diff --git a/src/test/run-pass/auxiliary/issue-48984-aux.rs b/src/test/run-pass/auxiliary/issue-48984-aux.rs
new file mode 100644
index 00000000000..6290279701e
--- /dev/null
+++ b/src/test/run-pass/auxiliary/issue-48984-aux.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![crate_type = "lib"]
+#![crate_name = "issue48984aux"]
+
+pub trait Foo { type Item; }
+
+pub trait Bar: Foo<Item=[u8;1]> {  }
diff --git a/src/test/run-pass/auxiliary/macro_reexport_2.rs b/src/test/run-pass/auxiliary/macro_reexport_2.rs
deleted file mode 100644
index 3918be88d86..00000000000
--- a/src/test/run-pass/auxiliary/macro_reexport_2.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 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.
-
-#![crate_type = "dylib"]
-#![feature(macro_reexport)]
-
-#[macro_reexport(reexported)]
-#[macro_use] #[no_link]
-extern crate macro_reexport_1;
diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs
index 2b82a894363..7bcb4e5ec2d 100644
--- a/src/test/run-pass/backtrace-debuginfo.rs
+++ b/src/test/run-pass/backtrace-debuginfo.rs
@@ -16,6 +16,7 @@
 // "enable" to 0 instead.
 
 // compile-flags:-g -Cllvm-args=-enable-tail-merge=0 -Cllvm-args=-opt-bisect-limit=0
+// compile-flags:-Cforce-frame-pointers=yes
 // ignore-pretty issue #37195
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
diff --git a/src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs b/src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs
new file mode 100644
index 00000000000..7f1b6ed1701
--- /dev/null
+++ b/src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs
@@ -0,0 +1,56 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+#![deny(unused_mut)]
+
+#[derive(Debug)]
+struct A {}
+
+fn init_a() -> A {
+    A {}
+}
+
+#[derive(Debug)]
+struct B<'a> {
+    ed: &'a mut A,
+}
+
+fn init_b<'a>(ed: &'a mut A) -> B<'a> {
+    B { ed }
+}
+
+#[derive(Debug)]
+struct C<'a> {
+    pd: &'a mut B<'a>,
+}
+
+fn init_c<'a>(pd: &'a mut B<'a>) -> C<'a> {
+    C { pd }
+}
+
+#[derive(Debug)]
+struct D<'a> {
+    sd: &'a mut C<'a>,
+}
+
+fn init_d<'a>(sd: &'a mut C<'a>) -> D<'a> {
+    D { sd }
+}
+
+fn main() {
+    let mut a = init_a();
+    let mut b = init_b(&mut a);
+    let mut c = init_c(&mut b);
+
+    let d = init_d(&mut c);
+
+    println!("{:?}", d)
+}
diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs
index 399823ec92d..01066794242 100644
--- a/src/test/run-pass/dyn-trait.rs
+++ b/src/test/run-pass/dyn-trait.rs
@@ -10,8 +10,6 @@
 
 // ignore-pretty `dyn ::foo` parses differently in the current edition
 
-#![feature(dyn_trait)]
-
 use std::fmt::Display;
 
 static BYTE: u8 = 33;
diff --git a/src/test/run-pass/extern-prelude-no-speculative.rs b/src/test/run-pass/extern-prelude-no-speculative.rs
new file mode 100644
index 00000000000..ff3aec439aa
--- /dev/null
+++ b/src/test/run-pass/extern-prelude-no-speculative.rs
@@ -0,0 +1,21 @@
+// Copyright 2014 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: --extern LooksLikeExternCrate=/path/to/nowhere
+
+mod m {
+    pub struct LooksLikeExternCrate;
+}
+
+fn main() {
+    // OK, speculative resolution for `unused_qualifications` doesn't try
+    // to resolve this as an extern crate and load that crate
+    let s = m::LooksLikeExternCrate {};
+}
diff --git a/src/test/run-pass/hygiene/issue-47311.rs b/src/test/run-pass/hygiene/issue-47311.rs
index c4391ad0577..3b6890cdce6 100644
--- a/src/test/run-pass/hygiene/issue-47311.rs
+++ b/src/test/run-pass/hygiene/issue-47311.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #![allow(unused)]
 
 macro m($S:ident, $x:ident) {
diff --git a/src/test/run-pass/hygiene/issue-47312.rs b/src/test/run-pass/hygiene/issue-47312.rs
index 0cda0e7c7cc..5e83f3808d8 100644
--- a/src/test/run-pass/hygiene/issue-47312.rs
+++ b/src/test/run-pass/hygiene/issue-47312.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #![allow(unused)]
 
 mod foo {
diff --git a/src/test/run-pass/hygiene/legacy_interaction.rs b/src/test/run-pass/hygiene/legacy_interaction.rs
index 5395ef35882..683a15b99ae 100644
--- a/src/test/run-pass/hygiene/legacy_interaction.rs
+++ b/src/test/run-pass/hygiene/legacy_interaction.rs
@@ -12,7 +12,7 @@
 
 // aux-build:legacy_interaction.rs
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 #[allow(unused)]
 
 extern crate legacy_interaction;
diff --git a/src/test/run-pass/hygiene/lexical.rs b/src/test/run-pass/hygiene/lexical.rs
index 73deda0777e..cb02a17fec3 100644
--- a/src/test/run-pass/hygiene/lexical.rs
+++ b/src/test/run-pass/hygiene/lexical.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod bar {
     mod baz {
diff --git a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
index 66e83eb7cac..55206950214 100644
--- a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
+++ b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs
@@ -13,7 +13,7 @@
 // aux-build:my_crate.rs
 // aux-build:unhygienic_example.rs
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 extern crate unhygienic_example;
 extern crate my_crate; // (b)
diff --git a/src/test/run-pass/hygiene/xcrate.rs b/src/test/run-pass/hygiene/xcrate.rs
index 95d7ae6db60..6df3a34d3c8 100644
--- a/src/test/run-pass/hygiene/xcrate.rs
+++ b/src/test/run-pass/hygiene/xcrate.rs
@@ -12,7 +12,7 @@
 
 // aux-build:xcrate.rs
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 extern crate xcrate;
 
diff --git a/src/test/run-pass/issue-47703-tuple.rs b/src/test/run-pass/issue-47703-tuple.rs
new file mode 100644
index 00000000000..4fec3efc0a0
--- /dev/null
+++ b/src/test/run-pass/issue-47703-tuple.rs
@@ -0,0 +1,21 @@
+// Copyright 2012 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.
+
+#![feature(nll)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn consume(x: (&mut (), WithDrop)) -> &mut () { x.0 }
+
+fn main() {}
diff --git a/src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs b/src/test/run-pass/issue-48984.rs
index 1d3dc26b0b4..227ad4e58f1 100644
--- a/src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs
+++ b/src/test/run-pass/issue-48984.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_type = "dylib"]
-#![feature(macro_reexport)]
+// aux-build:issue-48984-aux.rs
+extern crate issue48984aux;
+use issue48984aux::Bar;
 
-#[macro_reexport(reexported)]
-#[no_link]
-extern crate macro_reexport_1;
+fn do_thing<T: Bar>() { }
+
+fn main() { }
diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/run-pass/issue-49632.rs
index 1a7e3b918cd..8cbb7d21af7 100644
--- a/src/test/compile-fail/macro-reexport-malformed-3.rs
+++ b/src/test/run-pass/issue-49632.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![no_std]
-#![feature(macro_reexport)]
+#![feature(stmt_expr_attributes)]
 
-#[allow(unused_extern_crates)]
-#[macro_reexport(foo="bar")]  //~ ERROR bad macro re-export
-extern crate std;
+pub fn main() {
+    let _x = #[inline(always)] || {};
+    let _y = #[inline(never)] || {};
+    let _z = #[inline] || {};
+}
diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/run-pass/issue-49685.rs
index 8b448e401bd..1e4e7955323 100644
--- a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs
+++ b/src/test/run-pass/issue-49685.rs
@@ -8,14 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that macro re-exports item are gated by `macro_reexport` feature gate.
+// Regression test for #49685: drop elaboration was not revealing the
+// value of `impl Trait` returns, leading to an ICE.
 
-// aux-build:macro_reexport_1.rs
-// gate-test-macro_reexport
+fn main() {
+    let _ = Some(())
+        .into_iter()
+        .flat_map(|_| Some(()).into_iter().flat_map(func));
+}
 
-#![crate_type = "dylib"]
-
-#[macro_reexport(reexported)]
-//~^ ERROR macros re-exports are experimental and possibly buggy
-#[macro_use] #[no_link]
-extern crate macro_reexport_1;
+fn func(_: ()) -> impl Iterator<Item = ()> {
+    Some(()).into_iter().flat_map(|_| vec![])
+}
diff --git a/src/test/run-pass/issue-50415.rs b/src/test/run-pass/issue-50415.rs
new file mode 100644
index 00000000000..aa493ce0321
--- /dev/null
+++ b/src/test/run-pass/issue-50415.rs
@@ -0,0 +1,27 @@
+// Copyright 2018 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() {
+    // -------- Simplified test case --------
+
+    let _ = || 0..=1;
+
+    // -------- Original test case --------
+
+    let full_length = 1024;
+    let range = {
+        // do some stuff, omit here
+        None
+    };
+
+    let range = range.map(|(s, t)| s..=t).unwrap_or(0..=(full_length-1));
+
+    assert_eq!(range, 0..=1023);
+}
diff --git a/src/test/run-pass/nll/issue-48623-closure.rs b/src/test/run-pass/nll/issue-48623-closure.rs
new file mode 100644
index 00000000000..08ff54a428e
--- /dev/null
+++ b/src/test/run-pass/nll/issue-48623-closure.rs
@@ -0,0 +1,24 @@
+// Copyright 2012 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.
+
+#![feature(nll)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn reborrow_from_closure(r: &mut ()) -> &mut () {
+    let d = WithDrop;
+    (move || { d; &mut *r })()
+}
+
+fn main() {}
diff --git a/src/test/run-pass/nll/issue-48623-generator.rs b/src/test/run-pass/nll/issue-48623-generator.rs
new file mode 100644
index 00000000000..524837c4ba9
--- /dev/null
+++ b/src/test/run-pass/nll/issue-48623-generator.rs
@@ -0,0 +1,25 @@
+// Copyright 2012 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.
+
+#![feature(nll)]
+#![feature(generators, generator_trait)]
+
+struct WithDrop;
+
+impl Drop for WithDrop {
+    fn drop(&mut self) {}
+}
+
+fn reborrow_from_generator(r: &mut ()) {
+    let d = WithDrop;
+    move || { d; yield; &mut *r };
+}
+
+fn main() {}
diff --git a/src/test/run-pass/nll/issue-50343.rs b/src/test/run-pass/nll/issue-50343.rs
new file mode 100644
index 00000000000..f01d99c68cc
--- /dev/null
+++ b/src/test/run-pass/nll/issue-50343.rs
@@ -0,0 +1,17 @@
+// Copyright 2012 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.
+
+#![feature(nll)]
+#![deny(unused_mut)]
+
+fn main() {
+    vec![42].iter().map(|_| ()).count();
+    vec![(42, 22)].iter().map(|(_x, _y)| ()).count();
+}
diff --git a/src/test/run-pass/paths-in-macro-invocations.rs b/src/test/run-pass/paths-in-macro-invocations.rs
index 2e87809a84e..69f8906778a 100644
--- a/src/test/run-pass/paths-in-macro-invocations.rs
+++ b/src/test/run-pass/paths-in-macro-invocations.rs
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 extern crate two_macros;
 
diff --git a/src/test/run-pass/repr_c_int_align.rs b/src/test/run-pass/repr_c_int_align.rs
new file mode 100644
index 00000000000..af4eb615302
--- /dev/null
+++ b/src/test/run-pass/repr_c_int_align.rs
@@ -0,0 +1,55 @@
+// Copyright 2018 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: -O
+
+#![allow(dead_code)]
+
+#[repr(C, u8)]
+enum ReprCu8 {
+    A(u16),
+    B,
+}
+
+#[repr(u8)]
+enum Repru8 {
+    A(u16),
+    B,
+}
+
+#[repr(C)]
+struct ReprC {
+    tag: u8,
+    padding: u8,
+    payload: u16,
+}
+
+fn main() {
+    // Test `repr(C, u8)`.
+    let r1 = ReprC { tag: 0, padding: 0, payload: 0 };
+    let r2 = ReprC { tag: 0, padding: 1, payload: 1 };
+
+    let t1: &ReprCu8 = unsafe { std::mem::transmute(&r1) };
+    let t2: &ReprCu8 = unsafe { std::mem::transmute(&r2) };
+
+    match (t1, t2) {
+        (ReprCu8::A(_), ReprCu8::A(_)) => (),
+        _ => assert!(false)
+    };
+
+    // Test `repr(u8)`.
+    let t1: &Repru8 = unsafe { std::mem::transmute(&r1) };
+    let t2: &Repru8 = unsafe { std::mem::transmute(&r2) };
+
+    match (t1, t2) {
+        (Repru8::A(_), Repru8::A(_)) => (),
+        _ => assert!(false)
+    };
+}
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
index 24c30a5abc2..183bb553530 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(dyn_trait)]
-
 use std::error::Error;
 
 fn main() -> Result<(), Box<dyn Error>> {
diff --git a/src/test/run-pass/sync-send-in-std.rs b/src/test/run-pass/sync-send-in-std.rs
index f03387957bc..335a9c0d8be 100644
--- a/src/test/run-pass/sync-send-in-std.rs
+++ b/src/test/run-pass/sync-send-in-std.rs
@@ -11,9 +11,7 @@
 // ignore-cloudabi networking not available
 // ignore-wasm32-bare networking not available
 
-#![feature(lookup_host)]
-
-use std::net::lookup_host;
+use std::net::ToSocketAddrs;
 
 fn is_sync<T>(_: T) where T: Sync {}
 fn is_send<T>(_: T) where T: Send {}
@@ -30,5 +28,5 @@ macro_rules! all_sync_send {
 }
 
 fn main() {
-    all_sync_send!(lookup_host("localhost").unwrap(), next);
+    all_sync_send!("localhost:80".to_socket_addrs().unwrap(), next);
 }
diff --git a/src/test/run-pass/tool_attributes.rs b/src/test/run-pass/tool_attributes.rs
new file mode 100644
index 00000000000..eb13930de40
--- /dev/null
+++ b/src/test/run-pass/tool_attributes.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+// Scoped attributes should not trigger an unused attributes lint.
+
+#![feature(tool_attributes)]
+#![deny(unused_attributes)]
+
+fn main() {
+    #[rustfmt::skip]
+    foo ();
+}
+
+fn foo() {
+    assert!(true);
+}
diff --git a/src/test/run-pass/vec-const-new.rs b/src/test/run-pass/vec-const-new.rs
new file mode 100644
index 00000000000..62e2a36d7cc
--- /dev/null
+++ b/src/test/run-pass/vec-const-new.rs
@@ -0,0 +1,17 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that Vec::new() can be used for constants
+
+#![feature(const_vec_new)]
+
+const MY_VEC: Vec<usize> = Vec::new();
+
+pub fn main() {}
diff --git a/src/test/rustdoc-js/alias-2.js b/src/test/rustdoc-js/alias-2.js
index f31786df67c..0c5ec4fccbc 100644
--- a/src/test/rustdoc-js/alias-2.js
+++ b/src/test/rustdoc-js/alias-2.js
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-order
+
 const QUERY = '+';
 
 const EXPECTED = {
     'others': [
-        { 'path': 'std::ops::AddAssign', 'name': 'AddAssign' },
-        { 'path': 'std::ops::Add', 'name': 'Add' },
+        { 'path': 'std::ops', 'name': 'AddAssign' },
+        { 'path': 'std::ops', 'name': 'Add' },
     ],
 };
diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js/alias.js
index a0500f24c17..e7aafe3b9e2 100644
--- a/src/test/rustdoc-js/alias.js
+++ b/src/test/rustdoc-js/alias.js
@@ -8,12 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-order
+
 const QUERY = '[';
 
 const EXPECTED = {
     'others': [
         { 'path': 'std', 'name': 'slice' },
-        { 'path': 'std::ops::IndexMut', 'name': 'IndexMut' },
-        { 'path': 'std::ops::Index', 'name': 'Index' },
+        { 'path': 'std::ops', 'name': 'IndexMut' },
+        { 'path': 'std::ops', 'name': 'Index' },
     ],
 };
diff --git a/src/test/rustdoc-js/basic.js b/src/test/rustdoc-js/basic.js
index 863437cac91..d7ba1253eab 100644
--- a/src/test/rustdoc-js/basic.js
+++ b/src/test/rustdoc-js/basic.js
@@ -13,8 +13,8 @@ const QUERY = 'String';
 const EXPECTED = {
     'others': [
         { 'path': 'std::string', 'name': 'String' },
-        { 'path': 'std::ffi', 'name': 'OsString' },
         { 'path': 'std::ffi', 'name': 'CString' },
+        { 'path': 'std::ffi', 'name': 'OsString' },
     ],
     'in_args': [
         { 'path': 'std::str', 'name': 'eq' },
diff --git a/src/test/rustdoc/auxiliary/all-item-types.rs b/src/test/rustdoc/auxiliary/all-item-types.rs
new file mode 100644
index 00000000000..19a0b88ce7d
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/all-item-types.rs
@@ -0,0 +1,32 @@
+// Copyright 2018 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.
+
+#![feature(extern_types)]
+
+pub mod foo_mod {}
+extern "C" {
+    pub fn foo_ffn();
+    pub static FOO_FSTATIC: FooStruct;
+    pub type FooFType;
+}
+pub fn foo_fn() {}
+pub trait FooTrait {}
+pub struct FooStruct;
+pub enum FooEnum {}
+pub union FooUnion {
+    x: (),
+}
+pub type FooType = FooStruct;
+pub static FOO_STATIC: FooStruct = FooStruct;
+pub const FOO_CONSTANT: FooStruct = FooStruct;
+#[macro_export]
+macro_rules! foo_macro {
+    () => ();
+}
diff --git a/src/test/rustdoc/cross-crate-links.rs b/src/test/rustdoc/cross-crate-links.rs
new file mode 100644
index 00000000000..6078352fc0e
--- /dev/null
+++ b/src/test/rustdoc/cross-crate-links.rs
@@ -0,0 +1,71 @@
+// Copyright 2018 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.
+
+// aux-build:all-item-types.rs
+// build-aux-docs
+
+#![feature(use_extern_macros)]
+
+#![crate_name = "foo"]
+
+#[macro_use]
+extern crate all_item_types;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/foo_mod/index.html"]' 'foo_mod'
+#[doc(no_inline)]
+pub use all_item_types::foo_mod;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/fn.foo_ffn.html"]' 'foo_ffn'
+#[doc(no_inline)]
+pub use all_item_types::foo_ffn;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/static.FOO_FSTATIC.html"]' 'FOO_FSTATIC'
+#[doc(no_inline)]
+pub use all_item_types::FOO_FSTATIC;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/foreigntype.FooFType.html"]' 'FooFType'
+#[doc(no_inline)]
+pub use all_item_types::FooFType;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/fn.foo_fn.html"]' 'foo_fn'
+#[doc(no_inline)]
+pub use all_item_types::foo_fn;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/trait.FooTrait.html"]' 'FooTrait'
+#[doc(no_inline)]
+pub use all_item_types::FooTrait;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/struct.FooStruct.html"]' 'FooStruct'
+#[doc(no_inline)]
+pub use all_item_types::FooStruct;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/enum.FooEnum.html"]' 'FooEnum'
+#[doc(no_inline)]
+pub use all_item_types::FooEnum;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/union.FooUnion.html"]' 'FooUnion'
+#[doc(no_inline)]
+pub use all_item_types::FooUnion;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/type.FooType.html"]' 'FooType'
+#[doc(no_inline)]
+pub use all_item_types::FooType;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/static.FOO_STATIC.html"]' 'FOO_STATIC'
+#[doc(no_inline)]
+pub use all_item_types::FOO_STATIC;
+
+// @has 'foo/index.html' '//a[@href="../all_item_types/constant.FOO_CONSTANT.html"]' 'FOO_CONSTANT'
+#[doc(no_inline)]
+pub use all_item_types::FOO_CONSTANT;
+
+// @has 'foo/index.html' '//a[@href="../foo/macro.foo_macro.html"]' 'foo_macro'
+#[doc(no_inline)]
+pub use all_item_types::foo_macro;
diff --git a/src/test/rustdoc/pub-use-extern-macros.rs b/src/test/rustdoc/pub-use-extern-macros.rs
index 3f8f6f9544e..57d54585d84 100644
--- a/src/test/rustdoc/pub-use-extern-macros.rs
+++ b/src/test/rustdoc/pub-use-extern-macros.rs
@@ -10,14 +10,11 @@
 
 // aux-build:pub-use-extern-macros.rs
 
-#![feature(use_extern_macros, macro_reexport)]
+#![feature(use_extern_macros)]
 
-// @has pub_use_extern_macros/macro.foo.html
-// @!has pub_use_extern_macros/index.html 'pub use macros::foo;'
-#[macro_reexport(foo)] extern crate macros;
+extern crate macros;
 
-// @has pub_use_extern_macros/index.html 'pub use macros::bar;'
-// @!has pub_use_extern_macros/macro.bar.html
+// @has pub_use_extern_macros/macro.bar.html
 pub use macros::bar;
 
 // @has pub_use_extern_macros/macro.baz.html
@@ -25,7 +22,7 @@ pub use macros::bar;
 #[doc(inline)]
 pub use macros::baz;
 
-// @!has pub_use_extern_macros/macro.quux.html
+// @has pub_use_extern_macros/macro.quux.html
 // @!has pub_use_extern_macros/index.html 'pub use macros::quux;'
 #[doc(hidden)]
 pub use macros::quux;
diff --git a/src/test/rustdoc/universal-impl-trait.rs b/src/test/rustdoc/universal-impl-trait.rs
index 4cf99562c52..af51ff3d941 100644
--- a/src/test/rustdoc/universal-impl-trait.rs
+++ b/src/test/rustdoc/universal-impl-trait.rs
@@ -11,6 +11,8 @@
 #![feature(universal_impl_trait)]
 #![crate_name = "foo"]
 
+use std::io::Read;
+
 // @has foo/fn.foo.html
 // @has - //pre 'foo('
 // @matches - '_x: impl <a class="trait" href="[^"]+/trait\.Clone\.html"'
@@ -39,6 +41,11 @@ impl<T> S<T> {
     // @matches - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html'
     pub fn baz(_baz: S<impl Clone>) {
     }
+
+    // @has - 'qux</a>('
+    // @matches - 'trait\.Read\.html'
+    pub fn qux(_qux: impl IntoIterator<Item = S<impl Read>>) {
+    }
 }
 
 // @has - 'method</a>('
diff --git a/src/test/run-pass/macro-reexport.rs b/src/test/rustfix/closure-immutable-outer-variable.fixed
index b8926eca9e9..bddc2eab16d 100644
--- a/src/test/run-pass/macro-reexport.rs
+++ b/src/test/rustfix/closure-immutable-outer-variable.fixed
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:macro_reexport_1.rs
-// aux-build:macro_reexport_2.rs
+// Point at the captured immutable outer variable
 
-#[macro_use] #[no_link]
-extern crate macro_reexport_2;
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
 
 fn main() {
-    assert_eq!(reexported!(), 3_usize);
+    let mut y = true;
+    foo(Box::new(move || y = false) as Box<_>);
 }
diff --git a/src/test/run-pass/macro-reexport-no-intermediate-use.rs b/src/test/rustfix/closure-immutable-outer-variable.rs
index de7df1ec021..fe8e2bc6c8e 100644
--- a/src/test/run-pass/macro-reexport-no-intermediate-use.rs
+++ b/src/test/rustfix/closure-immutable-outer-variable.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:macro_reexport_1.rs
-// aux-build:macro_reexport_2_no_use.rs
+// Point at the captured immutable outer variable
 
-#[macro_use] #[no_link]
-extern crate macro_reexport_2_no_use;
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
 
 fn main() {
-    assert_eq!(reexported!(), 3_usize);
+    let y = true;
+    foo(Box::new(move || y = false) as Box<_>);
 }
diff --git a/src/test/rustfix/empty-no-fixes.fixed b/src/test/rustfix/empty-no-fixes.fixed
new file mode 100644
index 00000000000..39e19566d76
--- /dev/null
+++ b/src/test/rustfix/empty-no-fixes.fixed
@@ -0,0 +1,11 @@
+// Copyright 2018 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:--crate-type lib
diff --git a/src/test/rustfix/empty-no-fixes.rs b/src/test/rustfix/empty-no-fixes.rs
new file mode 100644
index 00000000000..39e19566d76
--- /dev/null
+++ b/src/test/rustfix/empty-no-fixes.rs
@@ -0,0 +1,11 @@
+// Copyright 2018 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:--crate-type lib
diff --git a/src/test/rustfix/empty-no-fixes.rs.fixed b/src/test/rustfix/empty-no-fixes.rs.fixed
new file mode 100644
index 00000000000..ee58e778253
--- /dev/null
+++ b/src/test/rustfix/empty-no-fixes.rs.fixed
@@ -0,0 +1,12 @@
+// Copyright 2018 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:--crate-type lib
+fn foo() {}
diff --git a/src/test/rustfix/issue-45562.fixed b/src/test/rustfix/issue-45562.fixed
new file mode 100644
index 00000000000..d7a27a11fc0
--- /dev/null
+++ b/src/test/rustfix/issue-45562.fixed
@@ -0,0 +1,13 @@
+// Copyright 2018 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.
+
+#[no_mangle] pub static RAH: usize = 5;
+
+fn main() {}
diff --git a/src/test/rustfix/issue-45562.rs b/src/test/rustfix/issue-45562.rs
new file mode 100644
index 00000000000..39576e9c845
--- /dev/null
+++ b/src/test/rustfix/issue-45562.rs
@@ -0,0 +1,13 @@
+// Copyright 2018 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.
+
+#[no_mangle] pub const RAH: usize = 5;
+
+fn main() {}
diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
new file mode 100644
index 00000000000..d931f90cd04
--- /dev/null
+++ b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
@@ -0,0 +1,12 @@
+// 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.
+
+extern crate std as other_std;
+fn main() {}
diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
new file mode 100644
index 00000000000..7c55f9c4eb9
--- /dev/null
+++ b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
@@ -0,0 +1,12 @@
+// 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.
+
+extern crate std;
+fn main() {}
diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed
index 1c04199c05f..aaa04ef4004 100644
--- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs
+++ b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: --cap-lints allow
+#![allow(unused)]
 
-// This tests that the fn_must_use feature-gate warning respects the lint
-// cap. (See discussion in Issue #44213.)
+fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+    and_yet + 1
+}
 
-#![feature(rustc_attrs)]
-
-#[must_use] // (no feature-gate warning because of the lint cap!)
-fn need_to_use_it() -> bool { true }
-
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() {
+    let behold: isize = 2;
+    let with_tears: usize = 3;
+    light_flows_our_war_of_mocking_words(&(behold as usize));
+    light_flows_our_war_of_mocking_words(&(with_tears + 4));
+}
diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs
new file mode 100644
index 00000000000..d21681747e9
--- /dev/null
+++ b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs
@@ -0,0 +1,22 @@
+// 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)]
+
+fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+    and_yet + 1
+}
+
+fn main() {
+    let behold: isize = 2;
+    let with_tears: usize = 3;
+    light_flows_our_war_of_mocking_words(behold as usize);
+    light_flows_our_war_of_mocking_words(with_tears + 4);
+}
diff --git a/src/test/rustfix/main-no-fixes.fixed b/src/test/rustfix/main-no-fixes.fixed
new file mode 100644
index 00000000000..3f07b46791d
--- /dev/null
+++ b/src/test/rustfix/main-no-fixes.fixed
@@ -0,0 +1,11 @@
+// Copyright 2018 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() {}
diff --git a/src/test/rustfix/main-no-fixes.rs b/src/test/rustfix/main-no-fixes.rs
new file mode 100644
index 00000000000..3f07b46791d
--- /dev/null
+++ b/src/test/rustfix/main-no-fixes.rs
@@ -0,0 +1,11 @@
+// Copyright 2018 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() {}
diff --git a/src/test/rustfix/main-no-fixes.rs.fixed b/src/test/rustfix/main-no-fixes.rs.fixed
new file mode 100644
index 00000000000..3f07b46791d
--- /dev/null
+++ b/src/test/rustfix/main-no-fixes.rs.fixed
@@ -0,0 +1,11 @@
+// Copyright 2018 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() {}
diff --git a/src/test/rustfix/missing-comma-in-match.fixed b/src/test/rustfix/missing-comma-in-match.fixed
new file mode 100644
index 00000000000..621a4127bc2
--- /dev/null
+++ b/src/test/rustfix/missing-comma-in-match.fixed
@@ -0,0 +1,17 @@
+// Copyright 2018 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() {
+    match &Some(3) {
+        &None => 1,
+        &Some(2) => { 3 }
+        _ => 2
+    };
+}
diff --git a/src/test/rustfix/missing-comma-in-match.rs b/src/test/rustfix/missing-comma-in-match.rs
new file mode 100644
index 00000000000..8ccad7b9c94
--- /dev/null
+++ b/src/test/rustfix/missing-comma-in-match.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 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() {
+    match &Some(3) {
+        &None => 1
+        &Some(2) => { 3 }
+        _ => 2
+    };
+}
diff --git a/src/test/rustfix/str-as-char.fixed b/src/test/rustfix/str-as-char.fixed
new file mode 100644
index 00000000000..0ace6d96613
--- /dev/null
+++ b/src/test/rustfix/str-as-char.fixed
@@ -0,0 +1,13 @@
+// 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!("●●");
+}
diff --git a/src/test/rustfix/str-as-char.rs b/src/test/rustfix/str-as-char.rs
new file mode 100644
index 00000000000..fa0e474fc7f
--- /dev/null
+++ b/src/test/rustfix/str-as-char.rs
@@ -0,0 +1,13 @@
+// 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!('●●');
+}
diff --git a/src/test/rustfix/tuple-float-index.fixed b/src/test/rustfix/tuple-float-index.fixed
new file mode 100644
index 00000000000..9cb7537b428
--- /dev/null
+++ b/src/test/rustfix/tuple-float-index.fixed
@@ -0,0 +1,15 @@
+// Copyright 2012 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 parse-only
+
+fn main () {
+    ((1, (2, 3)).1).1;
+}
diff --git a/src/test/rustfix/tuple-float-index.rs b/src/test/rustfix/tuple-float-index.rs
new file mode 100644
index 00000000000..8bfbd0e74db
--- /dev/null
+++ b/src/test/rustfix/tuple-float-index.rs
@@ -0,0 +1,15 @@
+// Copyright 2012 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 parse-only
+
+fn main () {
+    (1, (2, 3)).1.1;
+}
diff --git a/src/test/rustfix/update-all-references.sh b/src/test/rustfix/update-all-references.sh
new file mode 100755
index 00000000000..c3f615066bb
--- /dev/null
+++ b/src/test/rustfix/update-all-references.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+#
+# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+# A script to update the references for all tests. The idea is that
+# you do a run, which will generate files in the build directory
+# containing the (normalized) actual output of the compiler. You then
+# run this script, which will copy those files over. If you find
+# yourself manually editing a foo.stderr file, you're doing it wrong.
+#
+# See all `update-references.sh`, if you just want to update a single test.
+
+if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" != "" ]]; then
+    echo "usage: $0 <build-directory>"
+    echo ""
+    echo "For example:"
+    echo "   $0 ../../../build/x86_64-apple-darwin/test/rustfix"
+fi
+
+BUILD_DIR=$PWD/$1
+MY_DIR=$(dirname $0)
+cd $MY_DIR
+find . -name '*.rs' | xargs ./update-references.sh $BUILD_DIR
diff --git a/src/test/rustfix/update-references.sh b/src/test/rustfix/update-references.sh
new file mode 100755
index 00000000000..bcca2fec10d
--- /dev/null
+++ b/src/test/rustfix/update-references.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+#
+# Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+# A script to update the references for particular tests. The idea is
+# that you do a run, which will generate files in the build directory
+# containing the (normalized) actual output of the compiler. This
+# script will then copy that output and replace the "expected output"
+# files. You can then commit the changes.
+#
+# If you find yourself manually editing a foo.stderr file, you're
+# doing it wrong.
+
+if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
+    echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
+    echo ""
+    echo "For example:"
+    echo "   $0 ../../../build/x86_64-apple-darwin/test/rustfix *.rs */*.rs"
+fi
+
+MYDIR=$(dirname $0)
+
+BUILD_DIR="$1"
+shift
+
+shopt -s nullglob
+
+while [[ "$1" != "" ]]; do
+    for OUT_NAME in $BUILD_DIR/${1%.rs}.*fixed; do
+        OUT_BASE=`basename "$OUT_NAME"`
+        if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then
+            echo updating $MYDIR/$OUT_BASE
+            cp $OUT_NAME $MYDIR
+        fi
+    done
+    shift
+done
diff --git a/src/test/ui/const-eval/ice-packed.rs b/src/test/ui/const-eval/ice-packed.rs
new file mode 100644
index 00000000000..1db12a06b03
--- /dev/null
+++ b/src/test/ui/const-eval/ice-packed.rs
@@ -0,0 +1,28 @@
+// Copyright 2018 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-pass
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[repr(packed)]
+pub struct Num(u64);
+
+impl Num {
+    pub const ZERO: Self = Num(0);
+}
+
+pub fn decrement(a: Num) -> Num {
+    match a {
+        Num::ZERO => Num::ZERO,
+        a => Num(a.0 - 1)
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/const-eval/index_out_of_bound.stderr b/src/test/ui/const-eval/index_out_of_bound.stderr
index 793e0a7ace8..d16231c72b9 100644
--- a/src/test/ui/const-eval/index_out_of_bound.stderr
+++ b/src/test/ui/const-eval/index_out_of_bound.stderr
@@ -2,7 +2,7 @@ error[E0080]: constant evaluation error
   --> $DIR/index_out_of_bound.rs:11:19
    |
 LL | static FOO: i32 = [][0];
-   |                   ^^^^^ index out of bounds: the len is 0 but the index is 0 at $DIR/index_out_of_bound.rs:11:19: 11:24
+   |                   ^^^^^ index out of bounds: the len is 0 but the index is 0
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr
index a5db8cc9083..7761f192fdb 100644
--- a/src/test/ui/const-eval/promoted_errors.stderr
+++ b/src/test/ui/const-eval/promoted_errors.stderr
@@ -2,7 +2,7 @@ warning: constant evaluation error
   --> $DIR/promoted_errors.rs:14:20
    |
 LL |     println!("{}", 0u32 - 1);
-   |                    ^^^^^^^^ attempted to do overflowing math
+   |                    ^^^^^^^^ attempt to subtract with overflow
    |
    = note: #[warn(const_err)] on by default
 
@@ -10,13 +10,13 @@ warning: constant evaluation error
   --> $DIR/promoted_errors.rs:14:20
    |
 LL |     println!("{}", 0u32 - 1);
-   |                    ^^^^^^^^ attempted to do overflowing math
+   |                    ^^^^^^^^ attempt to subtract with overflow
 
 warning: constant evaluation error
   --> $DIR/promoted_errors.rs:17:14
    |
 LL |     let _x = 0u32 - 1;
-   |              ^^^^^^^^ attempted to do overflowing math
+   |              ^^^^^^^^ attempt to subtract with overflow
 
 warning: attempt to divide by zero
   --> $DIR/promoted_errors.rs:19:20
@@ -28,7 +28,7 @@ warning: constant evaluation error
   --> $DIR/promoted_errors.rs:19:20
    |
 LL |     println!("{}", 1/(1-1));
-   |                    ^^^^^^^ attempted to do overflowing math
+   |                    ^^^^^^^ attempt to divide by zero
 
 warning: attempt to divide by zero
   --> $DIR/promoted_errors.rs:22:14
@@ -40,11 +40,11 @@ warning: constant evaluation error
   --> $DIR/promoted_errors.rs:22:14
    |
 LL |     let _x = 1/(1-1);
-   |              ^^^^^^^ attempted to do overflowing math
+   |              ^^^^^^^ attempt to divide by zero
 
 warning: constant evaluation error
   --> $DIR/promoted_errors.rs:25:20
    |
 LL |     println!("{}", 1/(false as u32));
-   |                    ^^^^^^^^^^^^^^^^ attempted to do overflowing math
+   |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
 
diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs
index c8e42571128..7f3e6eaad9b 100644
--- a/src/test/ui/error-codes/E0080.rs
+++ b/src/test/ui/error-codes/E0080.rs
@@ -15,7 +15,6 @@ enum Enum {
     //~| const_err
     //~| const_err
     //~| const_err
-    //~| divide by zero
 }
 
 fn main() {
diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr
index 500e0e83a55..5e401bd6c79 100644
--- a/src/test/ui/error-codes/E0080.stderr
+++ b/src/test/ui/error-codes/E0080.stderr
@@ -24,7 +24,7 @@ warning: constant evaluation error
   --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
-   |         ^^^^^^^ attempted to do overflowing math
+   |         ^^^^^^^ attempt to divide by zero
 
 error[E0080]: constant evaluation error
   --> $DIR/E0080.rs:14:9
diff --git a/src/test/ui/error-codes/E0518.stderr b/src/test/ui/error-codes/E0518.stderr
index d8feec99140..27d5d3645fd 100644
--- a/src/test/ui/error-codes/E0518.stderr
+++ b/src/test/ui/error-codes/E0518.stderr
@@ -1,19 +1,19 @@
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/E0518.rs:11:1
    |
 LL | #[inline(always)] //~ ERROR: E0518
    | ^^^^^^^^^^^^^^^^^
 LL | struct Foo;
-   | ----------- not a function
+   | ----------- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/E0518.rs:14:1
    |
 LL |   #[inline(never)] //~ ERROR: E0518
    |   ^^^^^^^^^^^^^^^^
 LL | / impl Foo {
 LL | | }
-   | |_- not a function
+   | |_- not a function or closure
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr
deleted file mode 100644
index 6e6bdf1cbf0..00000000000
--- a/src/test/ui/feature-gate-dyn-trait.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: `dyn Trait` syntax is unstable (see issue #44662)
-  --> $DIR/feature-gate-dyn-trait.rs:12:14
-   |
-LL | type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
-   |              ^^^^^^^^^
-   |
-   = help: add #![feature(dyn_trait)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-extern_prelude.rs b/src/test/ui/feature-gate-extern_prelude.rs
new file mode 100644
index 00000000000..8d3a30305bd
--- /dev/null
+++ b/src/test/ui/feature-gate-extern_prelude.rs
@@ -0,0 +1,11 @@
+// Copyright 2018 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.
+
+can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
diff --git a/src/test/ui/feature-gate-extern_prelude.stderr b/src/test/ui/feature-gate-extern_prelude.stderr
new file mode 100644
index 00000000000..5abf369baf9
--- /dev/null
+++ b/src/test/ui/feature-gate-extern_prelude.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `-`
+  --> $DIR/feature-gate-extern_prelude.rs:11:4
+   |
+LL | can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-`
+   |    ^ expected one of `!` or `::` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
deleted file mode 100644
index a2c1dedff38..00000000000
--- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: compilation successful
-  --> $DIR/feature-gate-fn_must_use-cap-lints-allow.rs:22:1
-   |
-LL | fn main() {} //~ ERROR compilation successful
-   | ^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/feature-gate-fn_must_use.rs b/src/test/ui/feature-gate-fn_must_use.rs
deleted file mode 100644
index 72fdcc76cf4..00000000000
--- a/src/test/ui/feature-gate-fn_must_use.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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.
-
-#![feature(rustc_attrs)]
-
-struct MyStruct;
-
-impl MyStruct {
-    #[must_use] //~ WARN `#[must_use]` on methods is experimental
-    fn need_to_use_method() -> bool { true }
-}
-
-#[must_use] //~ WARN `#[must_use]` on functions is experimental
-fn need_to_use_it() -> bool { true }
-
-
-// Feature gates are tidy-required to have a specially named (or
-// comment-annotated) compile-fail test (which MUST fail), but for
-// backwards-compatibility reasons, we want `#[must_use]` on functions to be
-// compilable even if the `fn_must_use` feature is absent, thus necessitating
-// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this
-// dilemma until a superior solution can be devised.
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr
deleted file mode 100644
index 431c57abd26..00000000000
--- a/src/test/ui/feature-gate-fn_must_use.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-warning: `#[must_use]` on methods is experimental (see issue #43302)
-  --> $DIR/feature-gate-fn_must_use.rs:16:5
-   |
-LL |     #[must_use] //~ WARN `#[must_use]` on methods is experimental
-   |     ^^^^^^^^^^^
-   |
-   = help: add #![feature(fn_must_use)] to the crate attributes to enable
-
-warning: `#[must_use]` on functions is experimental (see issue #43302)
-  --> $DIR/feature-gate-fn_must_use.rs:20:1
-   |
-LL | #[must_use] //~ WARN `#[must_use]` on functions is experimental
-   | ^^^^^^^^^^^
-   |
-   = help: add #![feature(fn_must_use)] to the crate attributes to enable
-
-error: compilation successful
-  --> $DIR/feature-gate-fn_must_use.rs:31:1
-   |
-LL | fn main() {} //~ ERROR compilation successful
-   | ^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/feature-gate-tool_attributes.rs b/src/test/ui/feature-gate-tool_attributes.rs
new file mode 100644
index 00000000000..2b7cf56d938
--- /dev/null
+++ b/src/test/ui/feature-gate-tool_attributes.rs
@@ -0,0 +1,15 @@
+// Copyright 2018 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() {
+    #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+    let x = 3
+        ;
+}
diff --git a/src/test/ui/feature-gate-tool_attributes.stderr b/src/test/ui/feature-gate-tool_attributes.stderr
new file mode 100644
index 00000000000..da89c4a5ef6
--- /dev/null
+++ b/src/test/ui/feature-gate-tool_attributes.stderr
@@ -0,0 +1,11 @@
+error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690)
+  --> $DIR/feature-gate-tool_attributes.rs:12:5
+   |
+LL |     #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(tool_attributes)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index 21950402c8c..76fb09f27be 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -50,7 +50,6 @@
 #![allow                       (x5300)] //~ WARN unknown lint: `x5300`
 #![forbid                      (x5200)] //~ WARN unknown lint: `x5200`
 #![deny                        (x5100)] //~ WARN unknown lint: `x5100`
-#![macro_reexport             = "5000"] //~ WARN unused attribute
 #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs)
 #![macro_export               = "4800"] //~ WARN unused attribute
 #![plugin_registrar           = "4700"] //~ WARN unused attribute
@@ -186,25 +185,6 @@ mod deny {
     //~^ WARN unknown lint: `x5100`
 }
 
-#[macro_reexport = "5000"]
-//~^ WARN unused attribute
-mod macro_reexport {
-    mod inner { #![macro_reexport="5000"] }
-    //~^ WARN unused attribute
-
-    #[macro_reexport = "5000"] fn f() { }
-    //~^ WARN unused attribute
-
-    #[macro_reexport = "5000"] struct S;
-    //~^ WARN unused attribute
-
-    #[macro_reexport = "5000"] type T = S;
-    //~^ WARN unused attribute
-
-    #[macro_reexport = "5000"] impl S { }
-    //~^ WARN unused attribute
-}
-
 #[macro_use]
 mod macro_use {
     mod inner { #![macro_use] }
@@ -661,7 +641,6 @@ mod must_use {
     mod inner { #![must_use="1400"] }
 
     #[must_use = "1400"] fn f() { }
-    //~^ WARN `#[must_use]` on functions is experimental
 
     #[must_use = "1400"] struct S;
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
index 0beed627987..f8e5f58ca0e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,25 +1,17 @@
 warning: macro_escape is a deprecated synonym for macro_use
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
 
 warning: macro_escape is a deprecated synonym for macro_use
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
    |
    = help: consider an outer attribute, #[macro_use] mod ...
 
-warning: `#[must_use]` on functions is experimental (see issue #43302)
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
-   |
-LL |     #[must_use = "1400"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(fn_must_use)] to the crate attributes to enable
-
 warning: unknown lint: `x5400`
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33
    |
@@ -51,154 +43,154 @@ LL | #![deny                        (x5100)] //~ WARN unknown lint: `x5100`
    |                                 ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:8
    |
 LL | #[warn(x5400)]
    |        ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:25
    |
 LL |     mod inner { #![warn(x5400)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:12
    |
 LL |     #[warn(x5400)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:121:12
    |
 LL |     #[warn(x5400)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:12
    |
 LL |     #[warn(x5400)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5400`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:12
    |
 LL |     #[warn(x5400)] impl S { }
    |            ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:9
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:131:9
    |
 LL | #[allow(x5300)]
    |         ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:26
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:26
    |
 LL |     mod inner { #![allow(x5300)] }
    |                          ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:13
    |
 LL |     #[allow(x5300)] fn f() { }
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:140:13
    |
 LL |     #[allow(x5300)] struct S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:13
    |
 LL |     #[allow(x5300)] type T = S;
    |             ^^^^^
 
 warning: unknown lint: `x5300`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:13
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:13
    |
 LL |     #[allow(x5300)] impl S { }
    |             ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:10
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:150:10
    |
 LL | #[forbid(x5200)]
    |          ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:27
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:27
    |
 LL |     mod inner { #![forbid(x5200)] }
    |                           ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:14
    |
 LL |     #[forbid(x5200)] fn f() { }
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:159:14
    |
 LL |     #[forbid(x5200)] struct S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:14
    |
 LL |     #[forbid(x5200)] type T = S;
    |              ^^^^^
 
 warning: unknown lint: `x5200`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:14
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:14
    |
 LL |     #[forbid(x5200)] impl S { }
    |              ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:8
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:169:8
    |
 LL | #[deny(x5100)]
    |        ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:25
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:172:25
    |
 LL |     mod inner { #![deny(x5100)] }
    |                         ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:175:12
    |
 LL |     #[deny(x5100)] fn f() { }
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:178:12
    |
 LL |     #[deny(x5100)] struct S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:181:12
    |
 LL |     #[deny(x5100)] type T = S;
    |            ^^^^^
 
 warning: unknown lint: `x5100`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:12
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:12
    |
 LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:5
    |
-LL |     mod inner { #![macro_reexport="5000"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[macro_use] fn f() { }
+   |     ^^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:9
@@ -209,311 +201,275 @@ LL | #![warn(unused_attributes, unknown_lints)]
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5
    |
-LL |     #[macro_reexport = "5000"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5
-   |
-LL |     #[macro_reexport = "5000"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5
-   |
-LL |     #[macro_reexport = "5000"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5
-   |
-LL |     #[macro_reexport = "5000"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1
-   |
-LL | #[macro_reexport = "5000"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5
-   |
-LL |     #[macro_use] fn f() { }
-   |     ^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:215:5
-   |
 LL |     #[macro_use] struct S;
    |     ^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:218:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5
    |
 LL |     #[macro_use] type T = S;
    |     ^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5
    |
 LL |     #[macro_use] impl S { }
    |     ^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:208:17
    |
 LL |     mod inner { #![macro_export="4800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:211:5
    |
 LL |     #[macro_export = "4800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:214:5
    |
 LL |     #[macro_export = "4800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:217:5
    |
 LL |     #[macro_export = "4800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:220:5
    |
 LL |     #[macro_export = "4800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:225:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:1
    |
 LL | #[macro_export = "4800"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:17
    |
 LL |     mod inner { #![plugin_registrar="4700"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5
    |
 LL |     #[plugin_registrar = "4700"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
    |
 LL |     #[plugin_registrar = "4700"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5
    |
 LL |     #[plugin_registrar = "4700"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:1
    |
 LL | #[plugin_registrar = "4700"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:17
    |
 LL |     mod inner { #![main="4300"] }
    |                 ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:250:5
    |
 LL |     #[main = "4400"] struct S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5
    |
 LL |     #[main = "4400"] type T = S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5
    |
 LL |     #[main = "4400"] impl S { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:242:1
    |
 LL | #[main = "4400"]
    | ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:17
    |
 LL |     mod inner { #![start="4300"] }
    |                 ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:5
    |
 LL |     #[start = "4300"] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:291:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
    |
 LL |     #[start = "4300"] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
    |
 LL |     #[start = "4300"] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:1
    |
 LL | #[start = "4300"]
    | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:17
    |
 LL |     mod inner { #![repr="3900"] }
    |                 ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:5
    |
 LL |     #[repr = "3900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:321:5
    |
 LL |     #[repr = "3900"] type T = S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:5
    |
 LL |     #[repr = "3900"] impl S { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:1
    |
 LL | #[repr = "3900"]
    | ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5
    |
 LL |     #[path = "3800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5
    |
 LL |     #[path = "3800"]  struct S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5
    |
 LL |     #[path = "3800"] type T = S;
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5
    |
 LL |     #[path = "3800"] impl S { }
    |     ^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:348:17
    |
 LL |     mod inner { #![abi="3700"] }
    |                 ^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:5
    |
 LL |     #[abi = "3700"] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:5
    |
 LL |     #[abi = "3700"] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:357:5
    |
 LL |     #[abi = "3700"] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5
    |
 LL |     #[abi = "3700"] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:1
    |
 LL | #[abi = "3700"]
    | ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:17
    |
 LL |     mod inner { #![automatically_derived="3600"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5
    |
 LL |     #[automatically_derived = "3600"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5
    |
 LL |     #[automatically_derived = "3600"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5
    |
 LL |     #[automatically_derived = "3600"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5
    |
 LL |     #[automatically_derived = "3600"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:1
    |
 LL | #[automatically_derived = "3600"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: function is marked #[no_mangle], but not exported
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:27
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:27
    |
 LL |     #[no_mangle = "3500"] fn f() { }
    |                           -^^^^^^^^^
@@ -523,793 +479,787 @@ LL |     #[no_mangle = "3500"] fn f() { }
    = note: #[warn(private_no_mangle_fns)] on by default
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:17
    |
 LL |     mod inner { #![no_link="3400"] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5
    |
 LL |     #[no_link = "3400"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:5
    |
 LL |     #[no_link = "3400"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5
    |
 LL |     #[no_link = "3400"]type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5
    |
 LL |     #[no_link = "3400"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:1
    |
 LL | #[no_link = "3400"]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:17
    |
 LL |     mod inner { #![should_panic="3200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:5
    |
 LL |     #[should_panic = "3200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5
    |
 LL |     #[should_panic = "3200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428:5
    |
 LL |     #[should_panic = "3200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:431:5
    |
 LL |     #[should_panic = "3200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:1
    |
 LL | #[should_panic = "3200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:17
    |
 LL |     mod inner { #![ignore="3100"] }
    |                 ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:5
    |
 LL |     #[ignore = "3100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:5
    |
 LL |     #[ignore = "3100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:447:5
    |
 LL |     #[ignore = "3100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:5
    |
 LL |     #[ignore = "3100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:435:1
    |
 LL | #[ignore = "3100"]
    | ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:17
    |
 LL |     mod inner { #![no_implicit_prelude="3000"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:5
    |
 LL |     #[no_implicit_prelude = "3000"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:5
    |
 LL |     #[no_implicit_prelude = "3000"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5
    |
 LL |     #[no_implicit_prelude = "3000"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5
    |
 LL |     #[no_implicit_prelude = "3000"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:1
    |
 LL | #[no_implicit_prelude = "3000"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:482:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17
    |
 LL |     mod inner { #![no_std="2600"] }
    |                 ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17
    |
 LL |     mod inner { #![no_std="2600"] }
    |                 ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:5
    |
 LL |     #[no_std = "2600"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:5
    |
 LL |     #[no_std = "2600"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5
    |
 LL |     #[no_std = "2600"] struct S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5
    |
 LL |     #[no_std = "2600"] struct S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
    |
 LL |     #[no_std = "2600"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
    |
 LL |     #[no_std = "2600"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5
    |
 LL |     #[no_std = "2600"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5
    |
 LL |     #[no_std = "2600"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
    |
 LL | #[no_std = "2600"]
    | ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
    |
 LL | #[no_std = "2600"]
    | ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:17
    |
 LL |     mod inner { #![no_main="0400"] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:17
    |
 LL |     mod inner { #![no_main="0400"] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5
    |
 LL |     #[no_main = "0400"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5
    |
 LL |     #[no_main = "0400"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5
    |
 LL |     #[no_main = "0400"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5
    |
 LL |     #[no_main = "0400"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
    |
 LL |     #[no_main = "0400"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
    |
 LL |     #[no_main = "0400"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5
    |
 LL |     #[no_main = "0400"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5
    |
 LL |     #[no_main = "0400"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:1
    |
 LL | #[no_main = "0400"]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:1
    |
 LL | #[no_main = "0400"]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
-   |
-LL | #![macro_reexport             = "5000"] //~ WARN unused attribute
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1
    |
 LL | #![macro_export               = "4800"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1
    |
 LL | #![plugin_registrar           = "4700"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:58:1
    |
 LL | #![main                      = "x4400"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
    |
 LL | #![start                     = "x4300"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
    |
 LL | #![repr                       = "3900"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
    |
 LL | #![path                       = "3800"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
 LL | #![abi                        = "3700"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
    |
 LL | #![automatically_derived      = "3600"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
    |
 LL | #![no_link                    = "3400"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
    |
 LL | #![should_panic               = "3200"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
    |
 LL | #![ignore                     = "3100"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:76:1
    |
 LL | #![proc_macro_derive          = "2500"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: compilation successful
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:1
    |
 LL | / fn main() { //~ ERROR compilation successful
 LL | |     println!("Hello World");
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
index 410f960e655..b03faad988e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
@@ -19,21 +19,21 @@
 #![inline                     = "2100"]
 
 #[inline = "2100"]
-//~^ ERROR attribute should be applied to function
+//~^ ERROR attribute should be applied to function or closure
 mod inline {
     mod inner { #![inline="2100"] }
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 
     #[inline = "2100"] fn f() { }
 
     #[inline = "2100"] struct S;
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 
     #[inline = "2100"] type T = S;
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 
     #[inline = "2100"] impl S { }
-    //~^ ERROR attribute should be applied to function
+    //~^ ERROR attribute should be applied to function or closure
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
index d67d78e31a9..4d63c3f5012 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
@@ -1,41 +1,41 @@
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:21:1
    |
 LL |   #[inline = "2100"]
    |   ^^^^^^^^^^^^^^^^^^
-LL |   //~^ ERROR attribute should be applied to function
+LL |   //~^ ERROR attribute should be applied to function or closure
 LL | / mod inline {
 LL | |     mod inner { #![inline="2100"] }
-LL | |     //~^ ERROR attribute should be applied to function
+LL | |     //~^ ERROR attribute should be applied to function or closure
 LL | |
 ...  |
-LL | |     //~^ ERROR attribute should be applied to function
+LL | |     //~^ ERROR attribute should be applied to function or closure
 LL | | }
-   | |_- not a function
+   | |_- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:24:17
    |
 LL |     mod inner { #![inline="2100"] }
-   |     ------------^^^^^^^^^^^^^^^^^-- not a function
+   |     ------------^^^^^^^^^^^^^^^^^-- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:29:5
    |
 LL |     #[inline = "2100"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^ --------- not a function
+   |     ^^^^^^^^^^^^^^^^^^ --------- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:32:5
    |
 LL |     #[inline = "2100"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^ ----------- not a function
+   |     ^^^^^^^^^^^^^^^^^^ ----------- not a function or closure
 
-error[E0518]: attribute should be applied to function
+error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-inline.rs:35:5
    |
 LL |     #[inline = "2100"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^ ---------- not a function
+   |     ^^^^^^^^^^^^^^^^^^ ---------- not a function or closure
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs b/src/test/ui/fn_must_use.rs
index d20ebf0b740..def23046db2 100644
--- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs
+++ b/src/test/ui/fn_must_use.rs
@@ -10,7 +10,6 @@
 
 // compile-pass
 
-#![feature(fn_must_use)]
 #![warn(unused_must_use)]
 
 #[derive(PartialEq, Eq)]
diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr b/src/test/ui/fn_must_use.stderr
index d0a8bb525b6..5026dac0a94 100644
--- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr
+++ b/src/test/ui/fn_must_use.stderr
@@ -1,47 +1,47 @@
 warning: unused return value of `need_to_use_this_value` which must be used: it's important
-  --> $DIR/fn_must_use.rs:61:5
+  --> $DIR/fn_must_use.rs:60:5
    |
 LL |     need_to_use_this_value(); //~ WARN unused return value
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/fn_must_use.rs:14:9
+  --> $DIR/fn_must_use.rs:13:9
    |
 LL | #![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:66:5
+  --> $DIR/fn_must_use.rs:65:5
    |
 LL |     m.need_to_use_this_method_value(); //~ WARN unused return value
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused return value of `EvenNature::is_even` which must be used: no side effects
-  --> $DIR/fn_must_use.rs:67:5
+  --> $DIR/fn_must_use.rs:66:5
    |
 LL |     m.is_even(); // trait method!
    |     ^^^^^^^^^^^^
 
 warning: unused return value of `std::cmp::PartialEq::eq` which must be used
-  --> $DIR/fn_must_use.rs:73:5
+  --> $DIR/fn_must_use.rs:72:5
    |
 LL |     2.eq(&3); //~ WARN unused return value
    |     ^^^^^^^^^
 
 warning: unused return value of `std::cmp::PartialEq::eq` which must be used
-  --> $DIR/fn_must_use.rs:74:5
+  --> $DIR/fn_must_use.rs:73:5
    |
 LL |     m.eq(&n); //~ WARN unused return value
    |     ^^^^^^^^^
 
 warning: unused comparison which must be used
-  --> $DIR/fn_must_use.rs:77:5
+  --> $DIR/fn_must_use.rs:76:5
    |
 LL |     2 == 3; //~ WARN unused comparison
    |     ^^^^^^
 
 warning: unused comparison which must be used
-  --> $DIR/fn_must_use.rs:78:5
+  --> $DIR/fn_must_use.rs:77:5
    |
 LL |     m == n; //~ WARN unused comparison
    |     ^^^^^^
diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr
index 1801da6c8b2..243e9018585 100644
--- a/src/test/ui/generator/borrowing.nll.stderr
+++ b/src/test/ui/generator/borrowing.nll.stderr
@@ -1,14 +1,30 @@
-error: compilation successful
-  --> $DIR/borrowing.rs:15:1
+error[E0597]: `a` does not live long enough
+  --> $DIR/borrowing.rs:18:18
    |
-LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
-LL | |     let _b = {
-LL | |         let a = 3;
-LL | |         unsafe { (|| yield &a).resume() }
-...  |
-LL | |     };
-LL | | }
-   | |_^
+LL |         unsafe { (|| yield &a).resume() }
+   |                  ^^^^^^^^^^^^^
+   |                  |
+   |                  borrowed value does not live long enough
+   |                  borrow may end up in a temporary, created here
+LL |         //~^ ERROR: `a` does not live long enough
+LL |     };
+   |     -- temporary later dropped here, potentially using the reference
+   |     |
+   |     borrowed value only lives until here
 
-error: aborting due to previous error
+error[E0597]: `a` does not live long enough
+  --> $DIR/borrowing.rs:24:9
+   |
+LL | /         || {
+LL | |             yield &a
+LL | |             //~^ ERROR: `a` does not live long enough
+LL | |         }
+   | |_________^ borrowed value does not live long enough
+LL |       };
+   |       - borrowed value only lives until here
+LL |   }
+   |   - borrow later used here, when `_b` is dropped
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs
index f80aca9fb00..e56927d8182 100644
--- a/src/test/ui/generator/borrowing.rs
+++ b/src/test/ui/generator/borrowing.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generators, generator_trait, rustc_attrs)]
+#![feature(generators, generator_trait)]
 
 use std::ops::Generator;
 
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
     let _b = {
         let a = 3;
         unsafe { (|| yield &a).resume() }
diff --git a/src/test/ui/generator/dropck.nll.stderr b/src/test/ui/generator/dropck.nll.stderr
index 72ebaab3278..c352fd6a62f 100644
--- a/src/test/ui/generator/dropck.nll.stderr
+++ b/src/test/ui/generator/dropck.nll.stderr
@@ -1,14 +1,20 @@
-error: compilation successful
-  --> $DIR/dropck.rs:16:1
+error[E0597]: `ref_` does not live long enough
+  --> $DIR/dropck.rs:22:11
    |
-LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
-LL | |     let (cell, mut gen);
-LL | |     cell = Box::new(RefCell::new(0));
-LL | |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
-...  |
-LL | |     // drops the RefCell and then the Ref, leading to use-after-free
-LL | | }
-   | |_^
+LL |       gen = || {
+   |  ___________^
+LL | |         // but the generator can use it to drop a `Ref<'a, i32>`.
+LL | |         let _d = ref_.take(); //~ ERROR `ref_` does not live long enough
+LL | |         yield;
+LL | |     };
+   | |_____^ borrowed value does not live long enough
+...
+LL |   }
+   |   -
+   |   |
+   |   borrowed value only lives until here
+   |   borrow later used here, when `gen` is dropped
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs
index 8f4ba64fd57..857288818c6 100644
--- a/src/test/ui/generator/dropck.rs
+++ b/src/test/ui/generator/dropck.rs
@@ -8,15 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generators, generator_trait, box_leak, rustc_attrs)]
+#![feature(generators, generator_trait, box_leak)]
 
 use std::cell::RefCell;
 use std::ops::Generator;
 
-fn main() { #![rustc_error] // rust-lang/rust#49855
+fn main() {
     let (cell, mut gen);
     cell = Box::new(RefCell::new(0));
     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+    //~^ ERROR `*cell` does not live long enough [E0597]
     // the upvar is the non-dropck `&mut Option<Ref<'a, i32>>`.
     gen = || {
         // but the generator can use it to drop a `Ref<'a, i32>`.
diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr
index 4a22d299701..1a6fed2dd35 100644
--- a/src/test/ui/generator/dropck.stderr
+++ b/src/test/ui/generator/dropck.stderr
@@ -1,5 +1,16 @@
+error[E0597]: `*cell` does not live long enough
+  --> $DIR/dropck.rs:19:40
+   |
+LL |     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
+   |                                        ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*cell` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
 error[E0597]: `ref_` does not live long enough
-  --> $DIR/dropck.rs:23:18
+  --> $DIR/dropck.rs:24:18
    |
 LL |     gen = || {
    |           -- capture occurs here
@@ -12,6 +23,6 @@ LL | }
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
index 08839c23c37..70870b98365 100644
--- a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
@@ -1,11 +1,19 @@
 error[E0597]: `b` does not live long enough
   --> $DIR/ref-escapes-but-not-over-yield.rs:24:13
    |
-LL |         a = &b;
-   |             ^^ borrowed value does not live long enough
-LL |         //~^ ERROR `b` does not live long enough
-LL |     };
-   |     - borrowed value only lives until here
+LL |       let mut b = move || {
+   |  _________________-
+LL | |         yield();
+LL | |         let b = 5;
+LL | |         a = &b;
+   | |             ^^ borrowed value does not live long enough
+LL | |         //~^ ERROR `b` does not live long enough
+LL | |     };
+   | |     -
+   | |     |
+   | |     borrowed value only lives until here
+   | |_____temporary later dropped here, potentially using the reference
+   |       borrow may end up in a temporary, created here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr
index be4852aaf06..af79eb7ac05 100644
--- a/src/test/ui/generator/yield-while-iterating.nll.stderr
+++ b/src/test/ui/generator/yield-while-iterating.nll.stderr
@@ -6,20 +6,6 @@ LL |         for p in &x { //~ ERROR
 LL |             yield();
    |             ------- possible yield occurs here
 
-error[E0597]: borrowed value does not live long enough
-  --> $DIR/yield-while-iterating.rs:50:17
-   |
-LL |       let mut b = || {
-   |  _________________^
-LL | |         for p in &mut x {
-LL | |             yield p;
-LL | |         }
-LL | |     };
-   | |     ^
-   | |     |
-   | |_____temporary value only lives until here
-   |       temporary value does not live long enough
-
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/yield-while-iterating.rs:67:20
    |
@@ -35,21 +21,7 @@ LL |       println!("{}", x[0]); //~ ERROR
 LL |       b.resume();
    |       - borrow later used here
 
-error[E0597]: borrowed value does not live long enough
-  --> $DIR/yield-while-iterating.rs:62:17
-   |
-LL |       let mut b = || {
-   |  _________________^
-LL | |         for p in &mut x {
-LL | |             yield p;
-LL | |         }
-LL | |     };
-   | |     ^
-   | |     |
-   | |_____temporary value only lives until here
-   |       temporary value does not live long enough
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0502, E0597, E0626.
+Some errors occurred: E0502, E0626.
 For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/hygiene/fields.rs b/src/test/ui/hygiene/fields.rs
index ed155b28037..64217770b13 100644
--- a/src/test/ui/hygiene/fields.rs
+++ b/src/test/ui/hygiene/fields.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     struct S { x: u32 }
diff --git a/src/test/ui/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs
index f3f400aafeb..7ba217061c6 100644
--- a/src/test/ui/hygiene/globs.rs
+++ b/src/test/ui/hygiene/globs.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     pub fn f() {}
diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs
index 4f997a790e6..cdba559445d 100644
--- a/src/test/ui/hygiene/impl_items.rs
+++ b/src/test/ui/hygiene/impl_items.rs
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     struct S;
diff --git a/src/test/ui/hygiene/intercrate.rs b/src/test/ui/hygiene/intercrate.rs
index 20ca918f026..50fc985ba34 100644
--- a/src/test/ui/hygiene/intercrate.rs
+++ b/src/test/ui/hygiene/intercrate.rs
@@ -14,7 +14,7 @@
 
 // error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 extern crate intercrate;
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
index ea6a45fba6a..c90c7b3093c 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     pub macro m() { Vec::new(); ().clone() }
diff --git a/src/test/ui/hygiene/privacy.rs b/src/test/ui/hygiene/privacy.rs
index 8a392db92f9..987cad187d4 100644
--- a/src/test/ui/hygiene/privacy.rs
+++ b/src/test/ui/hygiene/privacy.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     fn f() {}
diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
index d0da6254b9b..3bd19cbc0ac 100644
--- a/src/test/ui/hygiene/trait_items.rs
+++ b/src/test/ui/hygiene/trait_items.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro, proc_macro_path_invoc)]
+#![feature(decl_macro)]
 
 mod foo {
     pub trait T {
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 3b20451b102..efa9a58d633 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -34,6 +34,7 @@ error[E0391]: cycle detected when processing `cycle1`
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle2::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:49:16
    |
@@ -44,6 +45,7 @@ note: ...which requires processing `cycle2`...
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires processing `cycle1::{{impl-Trait}}`...
   --> $DIR/auto-trait-leak.rs:42:16
    |
diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs
index 6a727942271..57a0040600a 100644
--- a/src/test/ui/impl_trait_projections.rs
+++ b/src/test/ui/impl_trait_projections.rs
@@ -7,8 +7,6 @@
 // <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.
-#![feature(dyn_trait)]
-
 use std::fmt::Debug;
 use std::option;
 
diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr
index 9b38de614fc..f6d58984ece 100644
--- a/src/test/ui/impl_trait_projections.stderr
+++ b/src/test/ui/impl_trait_projections.stderr
@@ -1,29 +1,29 @@
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:23:51
+  --> $DIR/impl_trait_projections.rs:21:51
    |
 LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
    |                                                   ^^^^^^^^^^^^^
 
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:30:9
+  --> $DIR/impl_trait_projections.rs:28:9
    |
 LL |     -> <impl Iterator as Iterator>::Item
    |         ^^^^^^^^^^^^^
 
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:37:27
+  --> $DIR/impl_trait_projections.rs:35:27
    |
 LL |     -> <::std::ops::Range<impl Debug> as Iterator>::Item
    |                           ^^^^^^^^^^
 
 error[E0667]: `impl Trait` is not allowed in path parameters
-  --> $DIR/impl_trait_projections.rs:44:29
+  --> $DIR/impl_trait_projections.rs:42:29
    |
 LL |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
    |                             ^^^^^^^^^^
 
 error[E0223]: ambiguous associated type
-  --> $DIR/impl_trait_projections.rs:23:50
+  --> $DIR/impl_trait_projections.rs:21:50
    |
 LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
    |                                                  ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
diff --git a/src/test/ui/imports/macro-paths.rs b/src/test/ui/imports/macro-paths.rs
index 51e5257be1b..e709eeee14a 100644
--- a/src/test/ui/imports/macro-paths.rs
+++ b/src/test/ui/imports/macro-paths.rs
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 extern crate two_macros;
 
diff --git a/src/test/ui/imports/shadow_builtin_macros.rs b/src/test/ui/imports/shadow_builtin_macros.rs
index aad0a43be26..93de136c405 100644
--- a/src/test/ui/imports/shadow_builtin_macros.rs
+++ b/src/test/ui/imports/shadow_builtin_macros.rs
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros, proc_macro_path_invoc)]
+#![feature(use_extern_macros)]
 
 mod foo {
     extern crate two_macros;
diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
index ec8c4ecf102..4cf7feddd46 100644
--- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
@@ -1,11 +1,11 @@
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait.rs:33:16
+  --> $DIR/dyn-trait.rs:32:16
    |
 LL |     static_val(x); //~ ERROR cannot infer
    |                ^
 
 error: free region `'a` does not outlive free region `'static`
-  --> $DIR/dyn-trait.rs:33:5
+  --> $DIR/dyn-trait.rs:32:5
    |
 LL |     static_val(x); //~ ERROR cannot infer
    |     ^^^^^^^^^^^^^
diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
index a504bae2e60..c27bbe77fbf 100644
--- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs
@@ -13,7 +13,6 @@
 
 #![allow(warnings)]
 
-#![feature(dyn_trait)]
 #![feature(in_band_lifetimes)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
index 9d6a318c075..201470abe67 100644
--- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr
@@ -1,11 +1,11 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/dyn-trait.rs:33:16
+  --> $DIR/dyn-trait.rs:32:16
    |
 LL |     static_val(x); //~ ERROR cannot infer
    |                ^
    |
-note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 32:1...
-  --> $DIR/dyn-trait.rs:32:1
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 31:1...
+  --> $DIR/dyn-trait.rs:31:1
    |
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/inference_unstable.rs b/src/test/ui/inference_unstable.rs
index 816c443a06c..5a70dffd4c8 100644
--- a/src/test/ui/inference_unstable.rs
+++ b/src/test/ui/inference_unstable.rs
@@ -25,5 +25,5 @@ use inference_unstable_itertools::IpuItertools;
 fn main() {
     assert_eq!('x'.ipu_flatten(), 1);
     //~^ WARN a method with this name may be added to the standard library in the future
-    //~^^ WARN once this method is added to the standard library, there will be ambiguity here
+    //~^^ WARN once this method is added to the standard library, the ambiguity may cause an error
 }
diff --git a/src/test/ui/inference_unstable.stderr b/src/test/ui/inference_unstable.stderr
index 9c614d659d3..a217bc57b36 100644
--- a/src/test/ui/inference_unstable.stderr
+++ b/src/test/ui/inference_unstable.stderr
@@ -5,7 +5,7 @@ LL |     assert_eq!('x'.ipu_flatten(), 1);
    |                    ^^^^^^^^^^^
    |
    = note: #[warn(unstable_name_collision)] on by default
-   = warning: once this method is added to the standard library, there will be ambiguity here, which will cause a hard error!
+   = warning: once this method is added to the standard library, the ambiguity may cause an error or change in behavior!
    = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
    = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method
    = note: add #![feature(ipu_flatten)] to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten`
diff --git a/src/test/ui/issue-49934.rs b/src/test/ui/issue-49934.rs
new file mode 100644
index 00000000000..3e30e7a6450
--- /dev/null
+++ b/src/test/ui/issue-49934.rs
@@ -0,0 +1,52 @@
+// Copyright 2018 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-pass
+
+#![feature(stmt_expr_attributes)]
+#![warn(unused_attributes)] //~ NOTE lint level defined here
+
+fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute
+    match 0 {
+        #[derive(Debug)] //~ WARN unused attribute
+        _ => (),
+    }
+}
+
+fn main() {
+    // fold_stmt (Item)
+    #[allow(dead_code)]
+    #[derive(Debug)] // should not warn
+    struct Foo;
+
+    // fold_stmt (Mac)
+    #[derive(Debug)]
+    //~^ WARN `#[derive]` does nothing on macro invocations
+    //~| NOTE this may become a hard error in a future release
+    println!("Hello, world!");
+
+    // fold_stmt (Semi)
+    #[derive(Debug)] //~ WARN unused attribute
+    "Hello, world!";
+
+    // fold_stmt (Local)
+    #[derive(Debug)] //~ WARN unused attribute
+    let _ = "Hello, world!";
+
+    // fold_expr
+    let _ = #[derive(Debug)] "Hello, world!";
+    //~^ WARN unused attribute
+
+    let _ = [
+        // fold_opt_expr
+        #[derive(Debug)] //~ WARN unused attribute
+        "Hello, world!"
+    ];
+}
diff --git a/src/test/ui/issue-49934.stderr b/src/test/ui/issue-49934.stderr
new file mode 100644
index 00000000000..298230b8b29
--- /dev/null
+++ b/src/test/ui/issue-49934.stderr
@@ -0,0 +1,50 @@
+warning: `#[derive]` does nothing on macro invocations
+  --> $DIR/issue-49934.rs:30:5
+   |
+LL |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: this may become a hard error in a future release
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:16:8
+   |
+LL | fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute
+   |        ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-49934.rs:14:9
+   |
+LL | #![warn(unused_attributes)] //~ NOTE lint level defined here
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:18:9
+   |
+LL |         #[derive(Debug)] //~ WARN unused attribute
+   |         ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:36:5
+   |
+LL |     #[derive(Debug)] //~ WARN unused attribute
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:40:5
+   |
+LL |     #[derive(Debug)] //~ WARN unused attribute
+   |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:44:13
+   |
+LL |     let _ = #[derive(Debug)] "Hello, world!";
+   |             ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-49934.rs:49:9
+   |
+LL |         #[derive(Debug)] //~ WARN unused attribute
+   |         ^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/issue-50187.rs b/src/test/ui/issue-50187.rs
new file mode 100644
index 00000000000..87acf106393
--- /dev/null
+++ b/src/test/ui/issue-50187.rs
@@ -0,0 +1,49 @@
+// Copyright 2018 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-pass
+
+#![feature(use_extern_macros, decl_macro)]
+
+mod type_ns {
+    pub type A = u8;
+}
+mod value_ns {
+    pub const A: u8 = 0;
+}
+mod macro_ns {
+    pub macro A() {}
+}
+
+mod merge2 {
+    pub use type_ns::A;
+    pub use value_ns::A;
+}
+mod merge3 {
+    pub use type_ns::A;
+    pub use value_ns::A;
+    pub use macro_ns::A;
+}
+
+mod use2 {
+    pub use merge2::A;
+}
+mod use3 {
+    pub use merge3::A;
+}
+
+fn main() {
+    type B2 = use2::A;
+    let a2 = use2::A;
+
+    type B3 = use3::A;
+    let a3 = use3::A;
+    use3::A!();
+}
diff --git a/src/test/ui/feature-gate-dyn-trait.rs b/src/test/ui/issue-50403.rs
index 4b3803d019b..8d4c6c5140f 100644
--- a/src/test/ui/feature-gate-dyn-trait.rs
+++ b/src/test/ui/issue-50403.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Trait {}
-type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
+#![feature(concat_idents)]
 
-fn main() {}
+fn main() {
+    let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments
+}
diff --git a/src/test/ui/issue-50403.stderr b/src/test/ui/issue-50403.stderr
new file mode 100644
index 00000000000..f2871c72e25
--- /dev/null
+++ b/src/test/ui/issue-50403.stderr
@@ -0,0 +1,8 @@
+error: concat_idents! takes 1 or more arguments.
+  --> $DIR/issue-50403.rs:14:13
+   |
+LL |     let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments
+   |             ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime_starts_expressions.rs b/src/test/ui/lifetime_starts_expressions.rs
new file mode 100644
index 00000000000..ffe1d7c353b
--- /dev/null
+++ b/src/test/ui/lifetime_starts_expressions.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 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 foo() -> u32 {
+    return 'label: loop { break 'label 42; };
+}
+
+fn bar() -> u32 {
+    loop { break 'label: loop { break 'label 42; }; }
+    //~^ ERROR expected identifier, found keyword `loop`
+    //~| ERROR expected type, found keyword `loop`
+}
+
+pub fn main() {
+    foo();
+}
diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr
new file mode 100644
index 00000000000..de42f1daa1e
--- /dev/null
+++ b/src/test/ui/lifetime_starts_expressions.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found keyword `loop`
+  --> $DIR/lifetime_starts_expressions.rs:16:26
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |                          ^^^^ expected identifier, found keyword
+
+error: expected type, found keyword `loop`
+  --> $DIR/lifetime_starts_expressions.rs:16:26
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |                          ^^^^ expecting a type here because of type ascription
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
index 18b83370355..6994a377a06 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
@@ -10,6 +10,8 @@
 
 // compile-pass
 
+#![feature(box_syntax)]
+#![feature(box_patterns)]
 #![warn(unused)] // UI tests pass `-A unused` (#43896)
 
 struct SoulHistory {
@@ -18,6 +20,13 @@ struct SoulHistory {
     endless_and_singing: bool
 }
 
+#[derive(Clone, Copy)]
+enum Large {
+    Suit { case: () }
+}
+
+struct Tuple(Large, ());
+
 fn main() {
     let i_think_continually = 2;
     let who_from_the_womb_remembered = SoulHistory {
@@ -31,4 +40,38 @@ fn main() {
                          endless_and_singing: true } = who_from_the_womb_remembered {
         hours_are_suns = false;
     }
+
+    let bag = Large::Suit {
+        case: ()
+    };
+
+    // Plain struct
+    match bag {
+        Large::Suit { case } => {}
+    };
+
+    // Referenced struct
+    match &bag {
+        &Large::Suit { case } => {}
+    };
+
+    // Boxed struct
+    match box bag {
+        box Large::Suit { case } => {}
+    };
+
+    // Tuple with struct
+    match (bag,) {
+        (Large::Suit { case },) => {}
+    };
+
+    // Slice with struct
+    match [bag] {
+        [Large::Suit { case }] => {}
+    };
+
+    // Tuple struct with struct
+    match Tuple(bag, ()) {
+        Tuple(Large::Suit { case }, ()) => {}
+    };
 }
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
index 35fe5479406..7bfe2c9162e 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -1,24 +1,24 @@
 warning: unused variable: `i_think_continually`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:31:9
    |
 LL |     let i_think_continually = 2;
    |         ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead
    |
 note: lint level defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9
    |
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_variables)] implied by #[warn(unused)]
 
 warning: unused variable: `corridors_of_light`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:26
    |
 LL |     if let SoulHistory { corridors_of_light,
    |                          ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
 
 warning: variable `hours_are_suns` is assigned to, but never used
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26
    |
 LL |                          mut hours_are_suns,
    |                          ^^^^^^^^^^^^^^^^^^
@@ -26,15 +26,51 @@ LL |                          mut hours_are_suns,
    = note: consider using `_hours_are_suns` instead
 
 warning: value assigned to `hours_are_suns` is never read
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9
    |
 LL |         hours_are_suns = false;
    |         ^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9
    |
 LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    |         ^^^^^^
    = note: #[warn(unused_assignments)] implied by #[warn(unused)]
 
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:23
+   |
+LL |         Large::Suit { case } => {}
+   |                       ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:55:24
+   |
+LL |         &Large::Suit { case } => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:60:27
+   |
+LL |         box Large::Suit { case } => {}
+   |                           ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:65:24
+   |
+LL |         (Large::Suit { case },) => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:70:24
+   |
+LL |         [Large::Suit { case }] => {}
+   |                        ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:75:29
+   |
+LL |         Tuple(Large::Suit { case }, ()) => {}
+   |                             ^^^^ help: try ignoring the field: `case: _`
+
diff --git a/src/test/ui/lint/must-use-ops.rs b/src/test/ui/lint/must-use-ops.rs
new file mode 100644
index 00000000000..c0575f817c8
--- /dev/null
+++ b/src/test/ui/lint/must-use-ops.rs
@@ -0,0 +1,51 @@
+// Copyright 2018 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.
+
+// Issue #50124 - Test warning for unused operator expressions
+
+// compile-pass
+
+#![warn(unused_must_use)]
+
+fn main() {
+    let val = 1;
+    let val_pointer = &val;
+
+// Comparison Operators
+    val == 1;
+    val < 1;
+    val <= 1;
+    val != 1;
+    val >= 1;
+    val > 1;
+
+// Arithmetic Operators
+    val + 2;
+    val - 2;
+    val / 2;
+    val * 2;
+    val % 2;
+
+// Logical Operators
+    true && true;
+    false || true;
+
+// Bitwise Operators
+    5 ^ val;
+    5 & val;
+    5 | val;
+    5 << val;
+    5 >> val;
+
+// Unary Operators
+    !val;
+    -val;
+    *val_pointer;
+}
diff --git a/src/test/ui/lint/must-use-ops.stderr b/src/test/ui/lint/must-use-ops.stderr
new file mode 100644
index 00000000000..5703536ef48
--- /dev/null
+++ b/src/test/ui/lint/must-use-ops.stderr
@@ -0,0 +1,132 @@
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:22:5
+   |
+LL |     val == 1;
+   |     ^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must-use-ops.rs:15:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:23:5
+   |
+LL |     val < 1;
+   |     ^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:24:5
+   |
+LL |     val <= 1;
+   |     ^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:25:5
+   |
+LL |     val != 1;
+   |     ^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:26:5
+   |
+LL |     val >= 1;
+   |     ^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/must-use-ops.rs:27:5
+   |
+LL |     val > 1;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:30:5
+   |
+LL |     val + 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:31:5
+   |
+LL |     val - 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:32:5
+   |
+LL |     val / 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:33:5
+   |
+LL |     val * 2;
+   |     ^^^^^^^
+
+warning: unused arithmetic operation which must be used
+  --> $DIR/must-use-ops.rs:34:5
+   |
+LL |     val % 2;
+   |     ^^^^^^^
+
+warning: unused logical operation which must be used
+  --> $DIR/must-use-ops.rs:37:5
+   |
+LL |     true && true;
+   |     ^^^^^^^^^^^^
+
+warning: unused logical operation which must be used
+  --> $DIR/must-use-ops.rs:38:5
+   |
+LL |     false || true;
+   |     ^^^^^^^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:41:5
+   |
+LL |     5 ^ val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:42:5
+   |
+LL |     5 & val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:43:5
+   |
+LL |     5 | val;
+   |     ^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:44:5
+   |
+LL |     5 << val;
+   |     ^^^^^^^^
+
+warning: unused bitwise operation which must be used
+  --> $DIR/must-use-ops.rs:45:5
+   |
+LL |     5 >> val;
+   |     ^^^^^^^^
+
+warning: unused unary operation which must be used
+  --> $DIR/must-use-ops.rs:48:5
+   |
+LL |     !val;
+   |     ^^^^
+
+warning: unused unary operation which must be used
+  --> $DIR/must-use-ops.rs:49:5
+   |
+LL |     -val;
+   |     ^^^^
+
+warning: unused unary operation which must be used
+  --> $DIR/must-use-ops.rs:50:5
+   |
+LL |     *val_pointer;
+   |     ^^^^^^^^^^^^
+
diff --git a/src/test/compile-fail/macro-reexport-undef.rs b/src/test/ui/macro-reexport-removed.rs
index 50ac89e49e0..bab583da37b 100644
--- a/src/test/compile-fail/macro-reexport-undef.rs
+++ b/src/test/ui/macro-reexport-removed.rs
@@ -10,12 +10,9 @@
 
 // aux-build:two_macros.rs
 
-#![feature(macro_reexport)]
+#![feature(macro_reexport)] //~ ERROR feature has been removed
 
-#[macro_use(macro_two)]
-#[macro_reexport(no_way)] //~ ERROR re-exported macro not found
+#[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown
 extern crate two_macros;
 
-pub fn main() {
-    macro_two!();
-}
+fn main() {}
diff --git a/src/test/ui/macro-reexport-removed.stderr b/src/test/ui/macro-reexport-removed.stderr
new file mode 100644
index 00000000000..ba0ab232e86
--- /dev/null
+++ b/src/test/ui/macro-reexport-removed.stderr
@@ -0,0 +1,24 @@
+error[E0557]: feature has been removed
+  --> $DIR/macro-reexport-removed.rs:13:12
+   |
+LL | #![feature(macro_reexport)] //~ ERROR feature has been removed
+   |            ^^^^^^^^^^^^^^
+   |
+note: subsumed by `#![feature(use_extern_macros)]` and `pub use`
+  --> $DIR/macro-reexport-removed.rs:13:12
+   |
+LL | #![feature(macro_reexport)] //~ ERROR feature has been removed
+   |            ^^^^^^^^^^^^^^
+
+error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/macro-reexport-removed.rs:15:1
+   |
+LL | #[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0557, E0658.
+For more information about an error, try `rustc --explain E0557`.
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
index 34232e81cbd..9eb11148a8b 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.rs
+++ b/src/test/ui/mismatched_types/closure-arg-count.rs
@@ -39,7 +39,13 @@ fn main() {
 
     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
     //~^ ERROR function is expected to take
+
+    call(Foo);
+    //~^ ERROR function is expected to take
 }
 
 fn foo() {}
 fn qux(x: usize, y: usize) {}
+
+fn call<F, R>(_: F) where F: FnOnce() -> R {}
+struct Foo(u8);
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 6451c0d06fa..6270e794498 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -116,6 +116,21 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
 LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
    |                                         ^^^ expected function that takes 1 argument
 
-error: aborting due to 12 previous errors
+error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
+  --> $DIR/closure-arg-count.rs:43:5
+   |
+LL |     call(Foo);
+   |     ^^^^ expected function that takes 0 arguments
+...
+LL | struct Foo(u8);
+   | --------------- takes 1 argument
+   |
+note: required by `call`
+  --> $DIR/closure-arg-count.rs:50:1
+   |
+LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0593`.
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
index 7b3ed6a94fc..4767b75d89c 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs
@@ -15,7 +15,6 @@
 // Iterator>::Item`, to be exact).
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 trait Anything { }
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
index 0efbbdff12a..3689ca74adb 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-closure.rs:36:31
+  --> $DIR/projection-no-regions-closure.rs:35:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                               ^^^^^^^^^^^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-closure.rs:54:31
+  --> $DIR/projection-no-regions-closure.rs:53:31
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                               ^^^^^^^^^^^^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:36:23
+  --> $DIR/projection-no-regions-closure.rs:35:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:36:23
+  --> $DIR/projection-no-regions-closure.rs:35:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:32:1
+  --> $DIR/projection-no-regions-closure.rs:31:1
    |
 LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -51,7 +51,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:46:23
+  --> $DIR/projection-no-regions-closure.rs:45:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:42:1
+  --> $DIR/projection-no-regions-closure.rs:41:1
    |
 LL | / fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -82,7 +82,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:54:23
+  --> $DIR/projection-no-regions-closure.rs:53:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -98,7 +98,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-closure.rs:54:23
+  --> $DIR/projection-no-regions-closure.rs:53:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:50:1
+  --> $DIR/projection-no-regions-closure.rs:49:1
    |
 LL | / fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
@@ -124,7 +124,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-no-regions-closure.rs:65:23
+  --> $DIR/projection-no-regions-closure.rs:64:23
    |
 LL |     with_signature(x, |mut y| Box::new(y.next()))
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +140,7 @@ LL |     with_signature(x, |mut y| Box::new(y.next()))
    = note: where <T as std::iter::Iterator>::Item: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-no-regions-closure.rs:60:1
+  --> $DIR/projection-no-regions-closure.rs:59:1
    |
 LL | / fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a>
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
index 32b73a51e11..dea2daf7e8e 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 trait Anything { }
 
diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
index b2c5f28268d..3199ec15133 100644
--- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-fn.rs:24:5
+  --> $DIR/projection-no-regions-fn.rs:23:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-no-regions-fn.rs:40:5
+  --> $DIR/projection-no-regions-fn.rs:39:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-fn.rs:24:5
+  --> $DIR/projection-no-regions-fn.rs:23:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     Box::new(x.next())
    = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
 
 error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
-  --> $DIR/projection-no-regions-fn.rs:40:5
+  --> $DIR/projection-no-regions-fn.rs:39:5
    |
 LL |     Box::new(x.next())
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
index cfe2880bfed..77024c4119f 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs
@@ -25,7 +25,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index 0d5a2dc7c55..e1218830dbb 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -1,23 +1,23 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:56:39
+  --> $DIR/projection-one-region-closure.rs:55:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:68:39
+  --> $DIR/projection-one-region-closure.rs:67:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-closure.rs:90:39
+  --> $DIR/projection-one-region-closure.rs:89:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:56:29
+  --> $DIR/projection-one-region-closure.rs:55:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:56:29
+  --> $DIR/projection-one-region-closure.rs:55:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,13 +41,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
 
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
-  --> $DIR/projection-one-region-closure.rs:56:20
+  --> $DIR/projection-one-region-closure.rs:55:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:52:1
+  --> $DIR/projection-one-region-closure.rs:51:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -64,7 +64,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:68:29
+  --> $DIR/projection-one-region-closure.rs:67:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -81,7 +81,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:68:29
+  --> $DIR/projection-one-region-closure.rs:67:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -89,13 +89,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-closure.rs:68:20
+  --> $DIR/projection-one-region-closure.rs:67:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:63:1
+  --> $DIR/projection-one-region-closure.rs:62:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -113,7 +113,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:90:29
+  --> $DIR/projection-one-region-closure.rs:89:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +130,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/projection-one-region-closure.rs:90:29
+  --> $DIR/projection-one-region-closure.rs:89:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,13 +138,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-closure.rs:90:20
+  --> $DIR/projection-one-region-closure.rs:89:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:75:1
+  --> $DIR/projection-one-region-closure.rs:74:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -162,7 +162,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-closure.rs:103:29
+  --> $DIR/projection-one-region-closure.rs:102:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -179,7 +179,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-closure.rs:97:1
+  --> $DIR/projection-one-region-closure.rs:96:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
index 16e91f2708f..fb1009c9cc8 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs
@@ -17,7 +17,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index d4aca8380b4..76554e29f62 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -1,23 +1,23 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:48:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:39
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:48:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,13 +32,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
-  --> $DIR/projection-one-region-trait-bound-closure.rs:48:20
+  --> $DIR/projection-one-region-trait-bound-closure.rs:47:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:44:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:43:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -55,7 +55,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,13 +71,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-trait-bound-closure.rs:59:20
+  --> $DIR/projection-one-region-trait-bound-closure.rs:58:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:54:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:53:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -95,7 +95,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,13 +111,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)`
-  --> $DIR/projection-one-region-trait-bound-closure.rs:80:20
+  --> $DIR/projection-one-region-trait-bound-closure.rs:79:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:65:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:64:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -135,7 +135,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:91:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:90:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -151,7 +151,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#2r: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:86:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:85:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -169,7 +169,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:103:29
+  --> $DIR/projection-one-region-trait-bound-closure.rs:102:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +184,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where '_#1r: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-closure.rs:95:1
+  --> $DIR/projection-one-region-trait-bound-closure.rs:94:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
index 0d42636c844..1f2f40196f8 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
@@ -16,7 +16,6 @@
 // compile-pass
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
index 875907e6b39..136e143e80e 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr
@@ -1,5 +1,5 @@
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:47:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:46:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:43:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:42:1
    |
 LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -28,7 +28,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:56:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:55:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:51:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:50:1
    |
 LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -60,7 +60,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:75:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:74:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,7 +74,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:60:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:59:1
    |
 LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -92,7 +92,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:84:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:83:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:79:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:78:1
    |
 LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -124,7 +124,7 @@ LL | | }
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:96:29
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:95:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -137,7 +137,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
            ]
 
 note: No external requirements
-  --> $DIR/projection-one-region-trait-bound-static-closure.rs:88:1
+  --> $DIR/projection-one-region-trait-bound-static-closure.rs:87:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
index 7c8ef140a29..5307d0880d4 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
@@ -18,7 +18,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 7e36e467e4e..c7f45692960 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -1,29 +1,29 @@
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:49:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/projection-two-region-trait-bound-closure.rs:109:39
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:39
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                                       ^^^^^^^
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:49:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
 error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:49:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:48:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:45:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:44:1
    |
 LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -65,7 +65,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +82,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:60:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:59:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:55:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:54:1
    |
 LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -109,7 +109,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -126,7 +126,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
-  --> $DIR/projection-two-region-trait-bound-closure.rs:81:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:80:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -134,7 +134,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:66:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:65:1
    |
 LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -153,7 +153,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:92:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:91:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -170,7 +170,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:87:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:86:1
    |
 LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -189,7 +189,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:101:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:100:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,7 +206,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:96:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:95:1
    |
 LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -225,7 +225,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:109:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,13 +240,13 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
 error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))`
-  --> $DIR/projection-two-region-trait-bound-closure.rs:109:20
+  --> $DIR/projection-two-region-trait-bound-closure.rs:108:20
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                    ^^^^
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:105:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:104:1
    |
 LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -263,7 +263,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:120:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:119:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::AssocType: '_#3r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:115:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:114:1
    |
 LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
@@ -297,7 +297,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:132:29
+  --> $DIR/projection-two-region-trait-bound-closure.rs:131:29
    |
 LL |     with_signature(cell, t, |cell, t| require(cell, t));
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -312,7 +312,7 @@ LL |     with_signature(cell, t, |cell, t| require(cell, t));
    = note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::AssocType: '_#2r
 
 note: No external requirements
-  --> $DIR/projection-two-region-trait-bound-closure.rs:124:1
+  --> $DIR/projection-two-region-trait-bound-closure.rs:123:1
    |
 LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
index 80b42c29563..7ff4b484af1 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index c8feaddff93..b4f51401a90 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -1,23 +1,23 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:31
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                               ^^^^^^^^^^^^
 
 note: External requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: where T: '_#1r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:33:1
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:32:1
    |
 LL | / fn generic<T>(value: T) {
 LL | |     let cell = Cell::new(&());
@@ -47,7 +47,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = note: where T: '_#1r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24
    |
 LL |     twice(cell, value, |a, b| invoke(a, b));
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:1
+  --> $DIR/ty-param-closure-approximate-lower-bound.rs:41:1
    |
 LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
 LL | |     twice(cell, value, |a, b| invoke(a, b));
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
index 50763a1d508..b5cbd07b99c 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
index 500595e0c5d..59a8a39a7b0 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:27
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:27
    |
 LL |     with_signature(x, |y| y)
    |                           ^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
    |
 LL |     x
    |     ^
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
    |
 LL |     with_signature(x, |y| y)
    |                       ^^^^^
@@ -26,7 +26,7 @@ LL |     with_signature(x, |y| y)
    = note: where T: '_#2r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23
    |
 LL |     with_signature(x, |y| y)
    |                       ^^^^^
@@ -34,7 +34,7 @@ LL |     with_signature(x, |y| y)
    = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:1
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:25:1
    |
 LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
 LL | | where
@@ -51,7 +51,7 @@ LL | | }
            ]
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5
+  --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5
    |
 LL |     x
    |     ^
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
index b70fc2b2ec4..edaaeac080d 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs
@@ -15,7 +15,6 @@
 // compile-flags:-Zborrowck=mir -Zverbose
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 #![feature(rustc_attrs)]
 
 use std::cell::Cell;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
index 4d8a66ba8e1..a53ce21b7e6 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:45:9
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:44:9
    |
 LL |         require(&x, &y)
    |         ^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:79:9
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:78:9
    |
 LL |         require(&x, &y)
    |         ^^^^^^^
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -32,7 +32,7 @@ LL | |     })
    = note: where T: '_#1r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -47,7 +47,7 @@ LL | |     })
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:36:1
    |
 LL | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
 LL | |     with_signature(a, b, |x, y| {
@@ -63,7 +63,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:55:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:54:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -85,7 +85,7 @@ LL | |     })
    = note: where T: '_#2r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:51:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:50:1
    |
 LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -102,7 +102,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -123,7 +123,7 @@ LL | |     })
    = note: where T: '_#2r
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -137,7 +137,7 @@ LL | |     })
    = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1
    |
 LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
@@ -154,7 +154,7 @@ LL | | }
            ]
 
 note: External requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:90:26
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:89:26
    |
 LL |       with_signature(a, b, |x, y| {
    |  __________________________^
@@ -174,7 +174,7 @@ LL | |     })
    = note: where T: '_#3r
 
 note: No external requirements
-  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:85:1
+  --> $DIR/ty-param-closure-outlives-from-where-clause.rs:84:1
    |
 LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
 LL | | where
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
index babe608354f..c0c483b3957 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
@@ -15,7 +15,6 @@
 #![feature(nll)]
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 use std::cell::Cell;
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
index 1510ca61e5c..dec15f47a03 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
@@ -1,5 +1,5 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn-body-nll-feature.rs:31:5
+  --> $DIR/ty-param-fn-body-nll-feature.rs:30:5
    |
 LL |     outlives(cell, t)
    |     ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
index fb4ea63f853..6226108ef19 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs
@@ -14,7 +14,6 @@
 // function body.
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 use std::cell::Cell;
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
index 0596861e67b..537f1223470 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr
@@ -1,11 +1,11 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn-body.rs:30:5
+  --> $DIR/ty-param-fn-body.rs:29:5
    |
 LL |     outlives(cell, t)
    |     ^^^^^^^^
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn-body.rs:30:5
+  --> $DIR/ty-param-fn-body.rs:29:5
    |
 LL |     outlives(cell, t)
    |     ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.rs b/src/test/ui/nll/ty-outlives/ty-param-fn.rs
index 42d662e1419..258d77eb2b0 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.rs
@@ -11,7 +11,6 @@
 // compile-flags:-Zborrowck=mir
 
 #![allow(warnings)]
-#![feature(dyn_trait)]
 
 use std::fmt::Debug;
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
index 0d09cac8c38..5ce50d81185 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr
@@ -1,17 +1,17 @@
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn.rs:22:5
+  --> $DIR/ty-param-fn.rs:21:5
    |
 LL |     x
    |     ^
 
 warning: not reporting region error due to nll
-  --> $DIR/ty-param-fn.rs:38:5
+  --> $DIR/ty-param-fn.rs:37:5
    |
 LL |     x
    |     ^
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn.rs:22:5
+  --> $DIR/ty-param-fn.rs:21:5
    |
 LL |     x
    |     ^
@@ -19,7 +19,7 @@ LL |     x
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/ty-param-fn.rs:38:5
+  --> $DIR/ty-param-fn.rs:37:5
    |
 LL |     x
    |     ^
diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr
index 5d8f80e57b0..275cd91a435 100644
--- a/src/test/ui/on-unimplemented/no-debug.stderr
+++ b/src/test/ui/on-unimplemented/no-debug.stderr
@@ -2,16 +2,17 @@ error[E0277]: `Foo` doesn't implement `std::fmt::Debug`
   --> $DIR/no-debug.rs:20:27
    |
 LL |     println!("{:?} {:?}", Foo, Bar);
-   |                           ^^^ `Foo` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
+   |                           ^^^ `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `Foo`
+   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
    = note: required by `std::fmt::Debug::fmt`
 
 error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Debug`
   --> $DIR/no-debug.rs:20:32
    |
 LL |     println!("{:?} {:?}", Foo, Bar);
-   |                                ^^^ `no_debug::Bar` cannot be formatted using `:?` because it doesn't implement `std::fmt::Debug`
+   |                                ^^^ `no_debug::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `no_debug::Bar`
    = note: required by `std::fmt::Debug::fmt`
@@ -20,18 +21,20 @@ error[E0277]: `Foo` doesn't implement `std::fmt::Display`
   --> $DIR/no-debug.rs:21:23
    |
 LL |     println!("{} {}", Foo, Bar);
-   |                       ^^^ `Foo` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
+   |                       ^^^ `Foo` cannot be formatted with the default formatter
    |
    = help: the trait `std::fmt::Display` is not implemented for `Foo`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
    = note: required by `std::fmt::Display::fmt`
 
 error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Display`
   --> $DIR/no-debug.rs:21:28
    |
 LL |     println!("{} {}", Foo, Bar);
-   |                            ^^^ `no_debug::Bar` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
+   |                            ^^^ `no_debug::Bar` cannot be formatted with the default formatter
    |
    = help: the trait `std::fmt::Display` is not implemented for `no_debug::Bar`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
    = note: required by `std::fmt::Display::fmt`
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs
new file mode 100644
index 00000000000..04bb2ab26f3
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr_int_c.rs
@@ -0,0 +1,35 @@
+// Copyright 2018 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 print-type-sizes
+// compile-pass
+
+// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
+// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
+
+#![feature(start)]
+#![allow(dead_code)]
+
+#[repr(C, u8)]
+enum ReprCu8 {
+    A(u16),
+    B,
+}
+
+#[repr(u8)]
+enum Repru8 {
+    A(u16),
+    B,
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    0
+}
diff --git a/src/test/ui/print_type_sizes/repr_int_c.stdout b/src/test/ui/print_type_sizes/repr_int_c.stdout
new file mode 100644
index 00000000000..254b3c7a853
--- /dev/null
+++ b/src/test/ui/print_type_sizes/repr_int_c.stdout
@@ -0,0 +1,12 @@
+print-type-size type: `ReprCu8`: 4 bytes, alignment: 2 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 3 bytes
+print-type-size         padding: 1 bytes
+print-type-size         field `.0`: 2 bytes, alignment: 2 bytes
+print-type-size     variant `B`: 1 bytes
+print-type-size type: `Repru8`: 4 bytes, alignment: 2 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `A`: 3 bytes
+print-type-size         padding: 1 bytes
+print-type-size         field `.0`: 2 bytes, alignment: 2 bytes
+print-type-size     variant `B`: 0 bytes
diff --git a/src/test/ui/raw-literal-keywords.rs b/src/test/ui/raw-literal-keywords.rs
index 9b28aa0b151..9bb6653d770 100644
--- a/src/test/ui/raw-literal-keywords.rs
+++ b/src/test/ui/raw-literal-keywords.rs
@@ -10,7 +10,6 @@
 
 // compile-flags: -Z parse-only
 
-#![feature(dyn_trait)]
 #![feature(raw_identifiers)]
 
 fn test_if() {
diff --git a/src/test/ui/raw-literal-keywords.stderr b/src/test/ui/raw-literal-keywords.stderr
index 3758568323c..022f80ae8a4 100644
--- a/src/test/ui/raw-literal-keywords.stderr
+++ b/src/test/ui/raw-literal-keywords.stderr
@@ -1,17 +1,17 @@
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true`
-  --> $DIR/raw-literal-keywords.rs:17:10
+  --> $DIR/raw-literal-keywords.rs:16:10
    |
 LL |     r#if true { } //~ ERROR found `true`
    |          ^^^^ expected one of 8 possible tokens here
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
-  --> $DIR/raw-literal-keywords.rs:21:14
+  --> $DIR/raw-literal-keywords.rs:20:14
    |
 LL |     r#struct Test; //~ ERROR found `Test`
    |              ^^^^ expected one of 8 possible tokens here
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test`
-  --> $DIR/raw-literal-keywords.rs:25:13
+  --> $DIR/raw-literal-keywords.rs:24:13
    |
 LL |     r#union Test; //~ ERROR found `Test`
    |             ^^^^ expected one of 8 possible tokens here
diff --git a/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs b/src/test/ui/repr-align-assign.rs
index 03dfeb1f5c9..c9780dde235 100644
--- a/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs
+++ b/src/test/ui/repr-align-assign.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,14 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:derive-a.rs
-// aux-build:derive-reexport.rs
-// ignore-stage1
+#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format
+struct A(u64);
 
-#[macro_use]
-extern crate derive_reexport;
-
-#[derive(Debug, PartialEq, A, Eq, Copy, Clone)]
-struct A;
+#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format
+struct B(u64);
 
 fn main() {}
diff --git a/src/test/ui/repr-align-assign.stderr b/src/test/ui/repr-align-assign.stderr
new file mode 100644
index 00000000000..1fa1263b946
--- /dev/null
+++ b/src/test/ui/repr-align-assign.stderr
@@ -0,0 +1,15 @@
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:11:8
+   |
+LL | #[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format
+   |        ^^^^^^^ help: use parentheses instead: `align(8)`
+
+error[E0693]: incorrect `repr(align)` attribute format
+  --> $DIR/repr-align-assign.rs:14:8
+   |
+LL | #[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format
+   |        ^^^^^^^^^ help: use parentheses instead: `align(8)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0693`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
new file mode 100644
index 00000000000..1c00edee770
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
@@ -0,0 +1,20 @@
+// Copyright 2018 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: --test
+
+#![feature(termination_trait_test)]
+
+use std::num::ParseIntError;
+
+#[test]
+fn can_parse_zero_as_f32() -> Result<f32, ParseIntError> { //~ ERROR
+    "0".parse()
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
new file mode 100644
index 00000000000..8efd8a216f1
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `main` has invalid return type `std::result::Result<f32, std::num::ParseIntError>`
+  --> $DIR/termination-trait-test-wrong-type.rs:18:1
+   |
+LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseIntError> { //~ ERROR
+LL | |     "0".parse()
+LL | | }
+   | |_^ `main` can only return types that implement `std::process::Termination`
+   |
+   = help: the trait `std::process::Termination` is not implemented for `std::result::Result<f32, std::num::ParseIntError>`
+   = note: required by `__test::test::assert_test_result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/span/gated-features-attr-spans.rs b/src/test/ui/span/gated-features-attr-spans.rs
index 83a4c5d5dd2..eff1f98eb71 100644
--- a/src/test/ui/span/gated-features-attr-spans.rs
+++ b/src/test/ui/span/gated-features-attr-spans.rs
@@ -8,33 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(attr_literals)]
-
-#[repr(align(16))]
-struct Gem {
-    mohs_hardness: u8,
-    poofed: bool,
-    weapon: Weapon,
-}
-
 #[repr(simd)] //~ ERROR are experimental
 struct Weapon {
     name: String,
     damage: u32
 }
 
-impl Gem {
-    #[must_use] fn summon_weapon(&self) -> Weapon { self.weapon }
-    //~^ WARN is experimental
-}
-
-#[must_use] //~ WARN is experimental
-fn bubble(gem: Gem) -> Result<Gem, ()> {
-    if gem.poofed {
-        Ok(gem)
-    } else {
-        Err(())
-    }
-}
-
 fn main() {}
diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr
index 179daf83c3c..a99530529fc 100644
--- a/src/test/ui/span/gated-features-attr-spans.stderr
+++ b/src/test/ui/span/gated-features-attr-spans.stderr
@@ -1,27 +1,11 @@
 error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731)
-  --> $DIR/gated-features-attr-spans.rs:20:1
+  --> $DIR/gated-features-attr-spans.rs:11:1
    |
 LL | #[repr(simd)] //~ ERROR are experimental
    | ^^^^^^^^^^^^^
    |
    = help: add #![feature(repr_simd)] to the crate attributes to enable
 
-warning: `#[must_use]` on methods is experimental (see issue #43302)
-  --> $DIR/gated-features-attr-spans.rs:27:5
-   |
-LL |     #[must_use] fn summon_weapon(&self) -> Weapon { self.weapon }
-   |     ^^^^^^^^^^^
-   |
-   = help: add #![feature(fn_must_use)] to the crate attributes to enable
-
-warning: `#[must_use]` on functions is experimental (see issue #43302)
-  --> $DIR/gated-features-attr-spans.rs:31:1
-   |
-LL | #[must_use] //~ WARN is experimental
-   | ^^^^^^^^^^^
-   |
-   = help: add #![feature(fn_must_use)] to the crate attributes to enable
-
 error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.fixed b/src/test/ui/suggestions/closure-immutable-outer-variable.fixed
new file mode 100644
index 00000000000..b3a0d592f76
--- /dev/null
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.fixed
@@ -0,0 +1,22 @@
+// 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.
+
+// run-rustfix
+
+// Point at the captured immutable outer variable
+
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
+
+fn main() {
+    let mut y = true;
+    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+}
diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed
index 07467e06eb2..e162678460c 100644
--- a/src/test/compile-fail/macro-no-implicit-reexport.rs
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:macro_reexport_1.rs
-// aux-build:macro_non_reexport_2.rs
+// run-rustfix
 
-#[macro_use] #[no_link]
-extern crate macro_non_reexport_2;
+// Point at the captured immutable outer variable
+
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
 
 fn main() {
-    assert_eq!(reexported!(), 3);
-    //~^ ERROR cannot find macro `reexported!` in this scope
+    let y = true;
+    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
 }
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
index e4e93ecac8e..bc655114c2b 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to immutable item `y`
-  --> $DIR/closure-immutable-outer-variable.rs:19:26
+  --> $DIR/closure-immutable-outer-variable.rs:21:26
    |
 LL |     foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
    |                          ^^^^^^^^^ cannot mutate
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs b/src/test/ui/suggestions/closure-immutable-outer-variable.rs
index 1d14afd6a01..e162678460c 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.rs
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 // Point at the captured immutable outer variable
 
 fn foo(mut f: Box<FnMut()>) {
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed b/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed
new file mode 100644
index 00000000000..80a5a45a305
--- /dev/null
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed
@@ -0,0 +1,20 @@
+// 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.
+
+// Point at the captured immutable outer variable
+
+fn foo(mut f: Box<FnMut()>) {
+    f();
+}
+
+fn main() {
+    let mut y = true;
+    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+}
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr
index 3353e2c7291..0ee11d8cf15 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr
@@ -1,5 +1,5 @@
 error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
-  --> $DIR/closure-immutable-outer-variable.rs:19:26
+  --> $DIR/closure-immutable-outer-variable.rs:21:26
    |
 LL |     let y = true;
    |         - help: consider making `y` mutable: `mut y`
diff --git a/src/test/ui/suggestions/issue-45562.fixed b/src/test/ui/suggestions/issue-45562.fixed
new file mode 100644
index 00000000000..7c01f0d1ee5
--- /dev/null
+++ b/src/test/ui/suggestions/issue-45562.fixed
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+// run-rustfix
+
+#[no_mangle] pub static RAH: usize = 5;
+//~^ ERROR const items should never be #[no_mangle]
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-45562.rs b/src/test/ui/suggestions/issue-45562.rs
index f493df56f94..c27d52fcdd3 100644
--- a/src/test/ui/suggestions/issue-45562.rs
+++ b/src/test/ui/suggestions/issue-45562.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 #[no_mangle] pub const RAH: usize = 5;
 //~^ ERROR const items should never be #[no_mangle]
 
diff --git a/src/test/ui/suggestions/issue-45562.stderr b/src/test/ui/suggestions/issue-45562.stderr
index d6960dca054..d9e624cadc7 100644
--- a/src/test/ui/suggestions/issue-45562.stderr
+++ b/src/test/ui/suggestions/issue-45562.stderr
@@ -1,5 +1,5 @@
 error: const items should never be #[no_mangle]
-  --> $DIR/issue-45562.rs:11:14
+  --> $DIR/issue-45562.rs:13:14
    |
 LL | #[no_mangle] pub const RAH: usize = 5;
    |              ---------^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
new file mode 100644
index 00000000000..e3287030408
--- /dev/null
+++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
@@ -0,0 +1,15 @@
+// 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.
+
+// run-rustfix
+
+extern crate std as other_std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
index 4d75127b645..f47ea474d51 100644
--- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
+++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 extern crate std;
 fn main() {}
 //~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
index 8e2b2d845e9..ecdfec2b3bf 100644
--- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
+++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
@@ -1,5 +1,5 @@
 error[E0259]: the name `std` is defined multiple times
-  --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:11:1
+  --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:13:1
    |
 LL | extern crate std;
    | ^^^^^^^^^^^^^^^^^ `std` reimported here
diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed
new file mode 100644
index 00000000000..77171cad6e7
--- /dev/null
+++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed
@@ -0,0 +1,26 @@
+// 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.
+
+// run-rustfix
+
+#![allow(unused)]
+
+fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+    and_yet + 1
+}
+
+fn main() {
+    let behold: isize = 2;
+    let with_tears: usize = 3;
+    light_flows_our_war_of_mocking_words(&(behold as usize));
+    //~^ ERROR mismatched types [E0308]
+    light_flows_our_war_of_mocking_words(&(with_tears + 4));
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs
index 5617c46afa9..e5ea9b5ed09 100644
--- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs
+++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 #![allow(unused)]
 
 fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr
index e89e9dce94d..9c492751ca1 100644
--- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr
+++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:20:42
+  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:22:42
    |
 LL |     light_flows_our_war_of_mocking_words(behold as usize);
    |                                          ^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL |     light_flows_our_war_of_mocking_words(behold as usize);
               found type `usize`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:22:42
+  --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:24:42
    |
 LL |     light_flows_our_war_of_mocking_words(with_tears + 4);
    |                                          ^^^^^^^^^^^^^^
diff --git a/src/test/ui/suggestions/missing-comma-in-match.fixed b/src/test/ui/suggestions/missing-comma-in-match.fixed
new file mode 100644
index 00000000000..4832f35f42d
--- /dev/null
+++ b/src/test/ui/suggestions/missing-comma-in-match.fixed
@@ -0,0 +1,21 @@
+// Copyright 2018 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.
+
+// run-rustfix
+
+fn main() {
+    match &Some(3) {
+        &None => 1,
+        &Some(2) => { 3 }
+        //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
+        //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator here
+        _ => 2
+    };
+}
diff --git a/src/test/ui/suggestions/missing-comma-in-match.rs b/src/test/ui/suggestions/missing-comma-in-match.rs
index 6f86cdea3cf..e39b20e77ea 100644
--- a/src/test/ui/suggestions/missing-comma-in-match.rs
+++ b/src/test/ui/suggestions/missing-comma-in-match.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 fn main() {
     match &Some(3) {
         &None => 1
diff --git a/src/test/ui/suggestions/missing-comma-in-match.stderr b/src/test/ui/suggestions/missing-comma-in-match.stderr
index b71a50b6631..77935934107 100644
--- a/src/test/ui/suggestions/missing-comma-in-match.stderr
+++ b/src/test/ui/suggestions/missing-comma-in-match.stderr
@@ -1,5 +1,5 @@
 error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
-  --> $DIR/missing-comma-in-match.rs:14:18
+  --> $DIR/missing-comma-in-match.rs:16:18
    |
 LL |         &None => 1
    |                   - help: missing a comma here to end this `match` arm
diff --git a/src/test/ui/suggestions/str-as-char.fixed b/src/test/ui/suggestions/str-as-char.fixed
new file mode 100644
index 00000000000..c0dad38e436
--- /dev/null
+++ b/src/test/ui/suggestions/str-as-char.fixed
@@ -0,0 +1,16 @@
+// 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.
+
+// run-rustfix
+
+fn main() {
+    println!("●●");
+    //~^ ERROR character literal may only contain one codepoint
+}
diff --git a/src/test/ui/suggestions/str-as-char.rs b/src/test/ui/suggestions/str-as-char.rs
index 09aca61147d..b5a5df0af7f 100644
--- a/src/test/ui/suggestions/str-as-char.rs
+++ b/src/test/ui/suggestions/str-as-char.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
+
 fn main() {
     println!('●●');
     //~^ ERROR character literal may only contain one codepoint
diff --git a/src/test/ui/suggestions/str-as-char.stderr b/src/test/ui/suggestions/str-as-char.stderr
index d881becf00c..60eb182adf1 100644
--- a/src/test/ui/suggestions/str-as-char.stderr
+++ b/src/test/ui/suggestions/str-as-char.stderr
@@ -1,5 +1,5 @@
 error: character literal may only contain one codepoint
-  --> $DIR/str-as-char.rs:12:14
+  --> $DIR/str-as-char.rs:14:14
    |
 LL |     println!('●●');
    |              ^^^^
diff --git a/src/test/ui/suggestions/tuple-float-index.fixed b/src/test/ui/suggestions/tuple-float-index.fixed
new file mode 100644
index 00000000000..55bc2f77dad
--- /dev/null
+++ b/src/test/ui/suggestions/tuple-float-index.fixed
@@ -0,0 +1,16 @@
+// Copyright 2012 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.
+
+// run-rustfix
+// compile-flags: -Z parse-only
+
+fn main () {
+    ((1, (2, 3)).1).1; //~ ERROR unexpected token: `1.1`
+}
diff --git a/src/test/ui/suggestions/tuple-float-index.rs b/src/test/ui/suggestions/tuple-float-index.rs
index 0a188305a92..d569ca4cb86 100644
--- a/src/test/ui/suggestions/tuple-float-index.rs
+++ b/src/test/ui/suggestions/tuple-float-index.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// run-rustfix
 // compile-flags: -Z parse-only
 
 fn main () {
diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr
index 4a1e34890f4..15af0834f03 100644
--- a/src/test/ui/suggestions/tuple-float-index.stderr
+++ b/src/test/ui/suggestions/tuple-float-index.stderr
@@ -1,5 +1,5 @@
 error: unexpected token: `1.1`
-  --> $DIR/tuple-float-index.rs:14:17
+  --> $DIR/tuple-float-index.rs:15:17
    |
 LL |     (1, (2, 3)).1.1; //~ ERROR unexpected token: `1.1`
    |     ------------^^^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
index e573ad8fc1f..6c83205d050 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs
@@ -13,8 +13,6 @@
 //
 // cc #48468
 
-#![feature(dyn_trait)]
-
 use std::fmt::Debug;
 
 struct Foo {
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
index 6d777841f03..1017217828a 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr
@@ -1,11 +1,11 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/dyn-trait-underscore-in-struct.rs:21:24
+  --> $DIR/dyn-trait-underscore-in-struct.rs:19:24
    |
 LL |     x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
    |                        ^^ expected lifetime parameter
 
 error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/dyn-trait-underscore-in-struct.rs:21:12
+  --> $DIR/dyn-trait-underscore-in-struct.rs:19:12
    |
 LL |     x: Box<dyn Debug + '_>, //~ ERROR missing lifetime specifier
    |            ^^^^^^^^^^^^^^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
index 10a03786d7b..cdc0c78e694 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
@@ -1,29 +1,29 @@
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:14
+  --> $DIR/dyn-trait-underscore.rs:18:14
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |              ^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:20
+  --> $DIR/dyn-trait-underscore.rs:18:20
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |                    ^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:5
+  --> $DIR/dyn-trait-underscore.rs:18:5
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^
 
 warning: not reporting region error due to nll
-  --> $DIR/dyn-trait-underscore.rs:20:5
+  --> $DIR/dyn-trait-underscore.rs:18:5
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: free region `` does not outlive free region `'static`
-  --> $DIR/dyn-trait-underscore.rs:18:52
+  --> $DIR/dyn-trait-underscore.rs:16:52
    |
 LL |   fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
    |  ____________________________________________________^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
index 9640d346597..247492fb7b7 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
@@ -13,8 +13,6 @@
 //
 // cc #48468
 
-#![feature(dyn_trait)]
-
 fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index f1e59aed54a..98249d3f2b5 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -1,11 +1,11 @@
 error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
-  --> $DIR/dyn-trait-underscore.rs:20:20
+  --> $DIR/dyn-trait-underscore.rs:18:20
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |                    ^^^^
    |
-note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 18:1...
-  --> $DIR/dyn-trait-underscore.rs:18:1
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 16:1...
+  --> $DIR/dyn-trait-underscore.rs:16:1
    |
 LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
 LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
@@ -13,7 +13,7 @@ LL | |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
 LL | | }
    | |_^
 note: ...so that reference does not outlive borrowed content
-  --> $DIR/dyn-trait-underscore.rs:20:14
+  --> $DIR/dyn-trait-underscore.rs:18:14
    |
 LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
    |              ^^^^^
diff --git a/src/test/ui/update-references.sh b/src/test/ui/update-references.sh
index 4fc11daaa3a..47a85352b00 100755
--- a/src/test/ui/update-references.sh
+++ b/src/test/ui/update-references.sh
@@ -26,7 +26,6 @@ if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
     echo "   $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
 fi
 
-MYDIR=$(dirname $0)
 
 BUILD_DIR="$1"
 shift
@@ -34,7 +33,8 @@ shift
 shopt -s nullglob
 
 while [[ "$1" != "" ]]; do
-    for EXT in "stderr" "stdout"; do
+    MYDIR=$(dirname $1)
+    for EXT in "stderr" "stdout" "fixed"; do
         for OUT_NAME in $BUILD_DIR/${1%.rs}.*$EXT; do
             OUT_BASE=`basename "$OUT_NAME"`
             if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9f238929215..6b548742fb3 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -57,6 +57,7 @@ static TARGETS: &'static [&'static str] = &[
     "arm-unknown-linux-musleabi",
     "arm-unknown-linux-musleabihf",
     "armv5te-unknown-linux-gnueabi",
+    "armv5te-unknown-linux-musleabi",
     "armv7-apple-ios",
     "armv7-linux-androideabi",
     "armv7-unknown-cloudabi-eabihf",
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 0a1add2d8689ad12a86f6c32d0a5cd0393dc5d8
+Subproject af3f1cd29bc872b932a13083e531255aab233a7
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject c5b39a5917ffc0f1349b6e414fa3b874fdcf842
+Subproject 1742229ebb7843a65c05ee495d8de5366fcc556
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 7d02f0b746d..45cb147fbbc 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -13,10 +13,12 @@ regex = "0.2"
 serde = "1.0"
 serde_json = "1.0"
 serde_derive = "1.0"
+rustfix = "0.2"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
 
 [target.'cfg(windows)'.dependencies]
+lazy_static = "1.0"
 miow = "0.3"
 winapi = { version = "0.3", features = ["winerror"] }
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 365b47447f2..2df52816599 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -74,30 +74,30 @@ impl FromStr for Mode {
 
 impl fmt::Display for Mode {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(match *self {
-                              CompileFail => "compile-fail",
-                              ParseFail => "parse-fail",
-                              RunFail => "run-fail",
-                              RunPass => "run-pass",
-                              RunPassValgrind => "run-pass-valgrind",
-                              Pretty => "pretty",
-                              DebugInfoGdb => "debuginfo-gdb",
-                              DebugInfoLldb => "debuginfo-lldb",
-                              Codegen => "codegen",
-                              Rustdoc => "rustdoc",
-                              CodegenUnits => "codegen-units",
-                              Incremental => "incremental",
-                              RunMake => "run-make",
-                              Ui => "ui",
-                              MirOpt => "mir-opt",
-                          },
-                          f)
+        let s = match *self {
+            CompileFail => "compile-fail",
+            ParseFail => "parse-fail",
+            RunFail => "run-fail",
+            RunPass => "run-pass",
+            RunPassValgrind => "run-pass-valgrind",
+            Pretty => "pretty",
+            DebugInfoGdb => "debuginfo-gdb",
+            DebugInfoLldb => "debuginfo-lldb",
+            Codegen => "codegen",
+            Rustdoc => "rustdoc",
+            CodegenUnits => "codegen-units",
+            Incremental => "incremental",
+            RunMake => "run-make",
+            Ui => "ui",
+            MirOpt => "mir-opt",
+        };
+        fmt::Display::fmt(s, f)
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
 pub enum CompareMode {
-    Nll
+    Nll,
 }
 
 impl CompareMode {
@@ -269,6 +269,7 @@ pub fn expected_output_path(testpaths: &TestPaths,
     testpaths.file.with_extension(extension)
 }
 
-pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT];
+pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED];
 pub const UI_STDERR: &str = "stderr";
 pub const UI_STDOUT: &str = "stdout";
+pub const UI_FIXED: &str = "fixed";
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 73dd079cf0c..7ac3f5b5b25 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -236,6 +236,7 @@ pub struct TestProps {
     pub normalize_stdout: Vec<(String, String)>,
     pub normalize_stderr: Vec<(String, String)>,
     pub failure_status: i32,
+    pub run_rustfix: bool,
 }
 
 impl TestProps {
@@ -267,6 +268,7 @@ impl TestProps {
             normalize_stdout: vec![],
             normalize_stderr: vec![],
             failure_status: 101,
+            run_rustfix: false,
         }
     }
 
@@ -403,6 +405,10 @@ impl TestProps {
             if let Some(code) = config.parse_failure_status(ln) {
                 self.failure_status = code;
             }
+
+            if !self.run_rustfix {
+                self.run_rustfix = config.parse_run_rustfix(ln);
+            }
         });
 
         for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
@@ -642,6 +648,10 @@ impl Config {
 
         None
     }
+
+    fn parse_run_rustfix(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "run-rustfix")
+    }
 }
 
 pub fn lldb_version_to_int(version_string: &str) -> isize {
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 37f7af0abe8..e2b446c99dc 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -23,9 +23,13 @@ extern crate libc;
 extern crate log;
 extern crate regex;
 #[macro_use]
+#[cfg(windows)]
+extern crate lazy_static;
+#[macro_use]
 extern crate serde_derive;
 extern crate serde_json;
 extern crate test;
+extern crate rustfix;
 
 use std::env;
 use std::ffi::OsString;
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 85434bb8a69..1bac9ef66bb 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -12,7 +12,7 @@ use common::{Config, TestPaths};
 use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
 use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
 use common::{Incremental, MirOpt, RunMake, Ui};
-use common::{expected_output_path, UI_STDERR, UI_STDOUT};
+use common::{expected_output_path, UI_STDERR, UI_STDOUT, UI_FIXED};
 use common::CompareMode;
 use diff;
 use errors::{self, Error, ErrorKind};
@@ -21,6 +21,7 @@ use json;
 use header::TestProps;
 use util::logv;
 use regex::Regex;
+use rustfix::{apply_suggestions, get_suggestions_from_json};
 
 use std::collections::VecDeque;
 use std::collections::HashMap;
@@ -37,6 +38,39 @@ use std::str;
 
 use extract_gdb_version;
 
+#[cfg(windows)]
+fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
+    use std::sync::Mutex;
+    const SEM_NOGPFAULTERRORBOX: u32 = 0x0002;
+    extern "system" {
+        fn SetErrorMode(mode: u32) -> u32;
+    }
+
+    lazy_static! {
+        static ref LOCK: Mutex<()> = {
+            Mutex::new(())
+        };
+    }
+    // Error mode is a global variable, so lock it so only one thread will change it
+    let _lock = LOCK.lock().unwrap();
+
+    // Tell Windows to not show any UI on errors (such as terminating abnormally).
+    // This is important for running tests, since some of them use abnormal
+    // termination by design. This mode is inherited by all child processes.
+    unsafe {
+        let old_mode = SetErrorMode(SEM_NOGPFAULTERRORBOX); // read inherited flags
+        SetErrorMode(old_mode | SEM_NOGPFAULTERRORBOX);
+        let r = f();
+        SetErrorMode(old_mode);
+        r
+    }
+}
+
+#[cfg(not(windows))]
+fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
+    f()
+}
+
 /// The name of the environment variable that holds dynamic library locations.
 pub fn dylib_env_var() -> &'static str {
     if cfg!(windows) {
@@ -1168,6 +1202,8 @@ impl<'test> TestCx<'test> {
         for line in proc_res.stderr.lines() {
             if line.contains("error: internal compiler error") {
                 self.fatal_proc_rec("compiler encountered internal error", proc_res);
+            } else if line.contains(" panicked at ") {
+                self.fatal_proc_rec("compiler panicked", proc_res);
             }
         }
     }
@@ -1575,8 +1611,7 @@ impl<'test> TestCx<'test> {
         let newpath = env::join_paths(&path).unwrap();
         command.env(dylib_env_var(), newpath);
 
-        let mut child = command
-            .spawn()
+        let mut child = disable_error_reporting(|| command.spawn())
             .expect(&format!("failed to exec `{:?}`", &command));
         if let Some(input) = input {
             child
@@ -2550,6 +2585,7 @@ impl<'test> TestCx<'test> {
 
         let expected_stderr = self.load_expected_output(UI_STDERR);
         let expected_stdout = self.load_expected_output(UI_STDOUT);
+        let expected_fixed = self.load_expected_output(UI_FIXED);
 
         let normalized_stdout =
             self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
@@ -2566,6 +2602,21 @@ impl<'test> TestCx<'test> {
         errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
         errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr);
 
+        if self.config.compare_mode.is_some() {
+            // don't test rustfix with nll right now
+        } else if self.props.run_rustfix {
+            // Apply suggestions from rustc to the code itself
+            let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file)
+                .unwrap();
+            let suggestions = get_suggestions_from_json(&proc_res.stderr, &HashSet::new()).unwrap();
+            let fixed_code = apply_suggestions(&unfixed_code, &suggestions);
+
+            errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
+        } else if !expected_fixed.is_empty() {
+            panic!("the `// run-rustfix` directive wasn't found but a `*.fixed` \
+                    file was found");
+        }
+
         if errors > 0 {
             println!("To update references, run this command from build directory:");
             let relative_path_to_file = self.testpaths
@@ -2601,6 +2652,23 @@ impl<'test> TestCx<'test> {
                 self.check_error_patterns(&proc_res.stderr, &proc_res);
             }
         }
+
+        if self.props.run_rustfix && self.config.compare_mode.is_none() {
+            // And finally, compile the fixed code and make sure it both
+            // succeeds and has no diagnostics.
+            let mut rustc = self.make_compile_args(
+                &self.testpaths.file.with_extension(UI_FIXED),
+                TargetLocation::ThisFile(self.make_exe_name()),
+            );
+            rustc.arg("-L").arg(&self.aux_output_dir_name());
+            let res = self.compose_and_run_compiler(rustc, None);
+            if !res.status.success() {
+                self.fatal_proc_rec("failed to compile fixed code", &res);
+            }
+            if !res.stderr.is_empty() {
+                self.fatal_proc_rec("fixed code is still producing diagnostics", &res);
+            }
+        }
     }
 
     fn run_mir_opt_test(&self) {
@@ -2733,10 +2801,12 @@ impl<'test> TestCx<'test> {
             panic!(
                 "Did not find expected line, error: {}\n\
                  Expected Line: {:?}\n\
+                 Test Name: {}\n\
                  Expected:\n{}\n\
                  Actual:\n{}",
                 extra_msg,
                 expected_line,
+                test_name,
                 expected_content,
                 normalize_all
             );
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 9144e223a5b90e078366275ff3dcdd406e62eae
+Subproject d2f44357fef6d61f316abc403e0a5d917f2771c
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 6992f2ba123..1c79443dedf 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -87,6 +87,7 @@ function loadContent(content) {
     var Module = module.constructor;
     var m = new Module();
     m._compile(content, "tmp.js");
+    m.exports.ignore_order = content.indexOf("\n// ignore-order\n") !== -1;
     return m.exports;
 }
 
@@ -130,10 +131,10 @@ function lookForEntry(entry, data) {
             }
         }
         if (allGood === true) {
-            return true;
+            return i;
         }
     }
-    return false;
+    return null;
 }
 
 function main(argv) {
@@ -177,6 +178,7 @@ function main(argv) {
                                'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
         const expected = loadedFile.EXPECTED;
         const query = loadedFile.QUERY;
+        const ignore_order = loadedFile.ignore_order;
         var results = loaded.execSearch(loaded.getQuery(query), index);
         process.stdout.write('Checking "' + file + '" ... ');
         var error_text = [];
@@ -189,13 +191,17 @@ function main(argv) {
                 break;
             }
             var entry = expected[key];
-            var found = false;
+            var prev_pos = 0;
             for (var i = 0; i < entry.length; ++i) {
-                if (lookForEntry(entry[i], results[key]) === true) {
-                    found = true;
-                } else {
+                var entry_pos = lookForEntry(entry[i], results[key]);
+                if (entry_pos === null) {
                     error_text.push("==> Result not found in '" + key + "': '" +
                                     JSON.stringify(entry[i]) + "'");
+                } else if (entry_pos < prev_pos && ignore_order === false) {
+                    error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " +
+                                    " before '" + JSON.stringify(results[key][entry_pos]) + "'");
+                } else {
+                    prev_pos = entry_pos;
                 }
             }
         }
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
-Subproject ac8ae0062544743aaea1719a34f299b66f2b7dc
+Subproject b6cd17f28ae314f2484ff05d3ce57652d51c5e8
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 8caf39fc27b..9a87fcb00d5 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -73,6 +73,7 @@ static WHITELIST: &'static [Crate] = &[
     Crate("flate2"),
     Crate("fuchsia-zircon"),
     Crate("fuchsia-zircon-sys"),
+    Crate("getopts"),
     Crate("humantime"),
     Crate("jobserver"),
     Crate("kernel32-sys"),
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index fa227436640..022ef57503a 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -51,6 +51,7 @@ pub mod pal;
 pub mod deps;
 pub mod ui_tests;
 pub mod unstable_book;
+pub mod libcoretest;
 
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs
new file mode 100644
index 00000000000..ef8b55186b1
--- /dev/null
+++ b/src/tools/tidy/src/libcoretest.rs
@@ -0,0 +1,34 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Tidy check to ensure `#[test]` is not used directly inside `libcore`.
+//!
+//! `#![no_core]` libraries cannot be tested directly due to duplicating lang
+//! item. All tests must be written externally in `libcore/tests`.
+
+use std::path::Path;
+use std::fs::read_to_string;
+
+pub fn check(path: &Path, bad: &mut bool) {
+    let libcore_path = path.join("libcore");
+    super::walk(
+        &libcore_path,
+        &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
+        &mut |subpath| {
+            if t!(read_to_string(subpath)).contains("#[test]") {
+                tidy_error!(
+                    bad,
+                    "{} contains #[test]; libcore tests must be placed inside `src/libcore/tests/`",
+                    subpath.display()
+                );
+            }
+        },
+    );
+}
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 24974192795..7b86650823a 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -41,6 +41,7 @@ fn main() {
     features::check(&path, &mut bad, quiet);
     pal::check(&path, &mut bad);
     unstable_book::check(&path, &mut bad);
+    libcoretest::check(&path, &mut bad);
     if !args.iter().any(|s| *s == "--no-vendor") {
         deps::check(&path, &mut bad);
     }