about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock12
-rw-r--r--src/bootstrap/bin/rustc.rs4
-rw-r--r--src/bootstrap/builder.rs5
-rw-r--r--src/bootstrap/compile.rs4
-rw-r--r--src/bootstrap/config.rs8
-rw-r--r--src/bootstrap/flags.rs6
-rw-r--r--src/build_helper/lib.rs118
-rw-r--r--src/ci/docker/scripts/musl.sh2
-rw-r--r--src/ci/docker/wasm32-unknown/Dockerfile1
m---------src/dlmalloc0
m---------src/doc/nomicon0
-rw-r--r--src/doc/unstable-book/src/language-features/catch-expr.md8
-rw-r--r--src/doc/unstable-book/src/language-features/global-allocator.md9
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md2
-rw-r--r--src/doc/unstable-book/src/language-features/repr-packed.md8
-rw-r--r--src/liballoc/Cargo.toml1
-rw-r--r--src/liballoc/alloc.rs215
-rw-r--r--src/liballoc/arc.rs23
-rw-r--r--src/liballoc/benches/lib.rs2
-rw-r--r--src/liballoc/btree/node.rs23
-rw-r--r--src/liballoc/heap.rs285
-rw-r--r--src/liballoc/lib.rs29
-rw-r--r--src/liballoc/raw_vec.rs90
-rw-r--r--src/liballoc/rc.rs25
-rw-r--r--src/liballoc/slice.rs1
-rw-r--r--src/liballoc/str.rs44
-rw-r--r--src/liballoc/string.rs4
-rw-r--r--src/liballoc/tests/heap.rs7
-rw-r--r--src/liballoc/tests/lib.rs5
-rw-r--r--src/liballoc/tests/str.rs3
-rw-r--r--src/liballoc/tests/string.rs14
-rw-r--r--src/liballoc/tests/vec.rs16
-rw-r--r--src/liballoc/tests/vec_deque.rs12
-rw-r--r--src/liballoc/vec.rs7
-rw-r--r--src/liballoc_jemalloc/Cargo.toml1
-rw-r--r--src/liballoc_jemalloc/lib.rs126
-rw-r--r--src/liballoc_system/Cargo.toml1
-rw-r--r--src/liballoc_system/lib.rs456
-rw-r--r--src/libarena/lib.rs1
-rw-r--r--src/libcore/alloc.rs (renamed from src/libcore/heap.rs)346
-rw-r--r--src/libcore/benches/lib.rs2
-rw-r--r--src/libcore/char.rs918
-rw-r--r--src/libcore/char/convert.rs304
-rw-r--r--src/libcore/char/decode.rs259
-rw-r--r--src/libcore/char/methods.rs (renamed from src/libstd_unicode/char.rs)418
-rw-r--r--src/libcore/char/mod.rs506
-rw-r--r--src/libcore/lib.rs14
-rw-r--r--src/libcore/num/mod.rs440
-rw-r--r--src/libcore/option.rs4
-rw-r--r--src/libcore/prelude/v1.rs3
-rw-r--r--src/libcore/ptr.rs20
-rw-r--r--src/libcore/slice/mod.rs11
-rw-r--r--src/libcore/str/lossy.rs (renamed from src/libstd_unicode/lossy.rs)9
-rw-r--r--src/libcore/str/mod.rs120
-rw-r--r--src/libcore/tests/atomic.rs10
-rw-r--r--src/libcore/tests/lib.rs4
-rw-r--r--src/libcore/tests/str_lossy.rs (renamed from src/libstd_unicode/tests/lossy.rs)2
-rw-r--r--src/libcore/unicode/bool_trie.rs (renamed from src/libstd_unicode/bool_trie.rs)0
-rw-r--r--src/libcore/unicode/mod.rs27
-rw-r--r--src/libcore/unicode/printable.py (renamed from src/etc/char_private.py)2
-rw-r--r--src/libcore/unicode/printable.rs (renamed from src/libcore/char_private.rs)2
-rw-r--r--src/libcore/unicode/tables.rs (renamed from src/libstd_unicode/tables.rs)10
-rwxr-xr-xsrc/libcore/unicode/unicode.py (renamed from src/libstd_unicode/unicode.py)10
-rw-r--r--src/libcore/unicode/version.rs (renamed from src/libstd_unicode/version.rs)1
-rw-r--r--src/libfmt_macros/lib.rs1
-rw-r--r--src/libgraphviz/lib.rs1
-rw-r--r--src/libpanic_abort/lib.rs1
-rw-r--r--src/libpanic_unwind/lib.rs1
-rw-r--r--src/libproc_macro/lib.rs12
-rw-r--r--src/librustc/benches/lib.rs2
-rw-r--r--src/librustc/cfg/construct.rs1
-rw-r--r--src/librustc/dep_graph/dep_node.rs2
-rw-r--r--src/librustc/hir/intravisit.rs5
-rw-r--r--src/librustc/hir/lowering.rs47
-rw-r--r--src/librustc/hir/map/mod.rs14
-rw-r--r--src/librustc/hir/mod.rs9
-rw-r--r--src/librustc/hir/print.rs9
-rw-r--r--src/librustc/ich/impls_hir.rs47
-rw-r--r--src/librustc/ich/impls_syntax.rs3
-rw-r--r--src/librustc/ich/impls_ty.rs14
-rw-r--r--src/librustc/infer/anon_types/mod.rs8
-rw-r--r--src/librustc/infer/canonical.rs4
-rw-r--r--src/librustc/infer/error_reporting/mod.rs2
-rw-r--r--src/librustc/infer/type_variable.rs4
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc/lint/mod.rs7
-rw-r--r--src/librustc/middle/cstore.rs2
-rw-r--r--src/librustc/middle/dead.rs53
-rw-r--r--src/librustc/middle/dependency_format.rs7
-rw-r--r--src/librustc/middle/entry.rs19
-rw-r--r--src/librustc/middle/expr_use_visitor.rs20
-rw-r--r--src/librustc/middle/liveness.rs9
-rw-r--r--src/librustc/middle/mem_categorization.rs87
-rw-r--r--src/librustc/middle/recursion_limit.rs11
-rw-r--r--src/librustc/middle/region.rs1
-rw-r--r--src/librustc/mir/cache.rs10
-rw-r--r--src/librustc/mir/mod.rs8
-rw-r--r--src/librustc/session/code_stats.rs37
-rw-r--r--src/librustc/session/config.rs11
-rw-r--r--src/librustc/session/mod.rs210
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc/traits/mod.rs41
-rw-r--r--src/librustc/traits/on_unimplemented.rs2
-rw-r--r--src/librustc/traits/project.rs6
-rw-r--r--src/librustc/traits/query/normalize.rs2
-rw-r--r--src/librustc/traits/select.rs2
-rw-r--r--src/librustc/traits/structural_impls.rs34
-rw-r--r--src/librustc/ty/cast.rs3
-rw-r--r--src/librustc/ty/context.rs148
-rw-r--r--src/librustc/ty/layout.rs86
-rw-r--r--src/librustc/ty/maps/config.rs12
-rw-r--r--src/librustc/ty/maps/mod.rs20
-rw-r--r--src/librustc/ty/maps/plumbing.rs13
-rw-r--r--src/librustc/ty/mod.rs87
-rw-r--r--src/librustc/ty/steal.rs12
-rw-r--r--src/librustc/ty/sty.rs10
-rw-r--r--src/librustc/ty/util.rs40
-rw-r--r--src/librustc/util/common.rs17
-rw-r--r--src/librustc_allocator/expand.rs278
-rw-r--r--src/librustc_allocator/lib.rs37
-rw-r--r--src/librustc_apfloat/lib.rs1
-rw-r--r--src/librustc_back/lib.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs5
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs21
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs9
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_const_math/lib.rs1
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_data_structures/sync.rs210
-rw-r--r--src/librustc_driver/driver.rs7
-rw-r--r--src/librustc_driver/lib.rs12
-rw-r--r--src/librustc_driver/test.rs2
-rw-r--r--src/librustc_errors/lib.rs1
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_lint/bad_style.rs3
-rw-r--r--src/librustc_lint/builtin.rs15
-rw-r--r--src/librustc_lint/lib.rs1
-rw-r--r--src/librustc_llvm/lib.rs1
-rw-r--r--src/librustc_metadata/creader.rs14
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_metadata/decoder.rs9
-rw-r--r--src/librustc_metadata/encoder.rs6
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_mir/borrow_check/mod.rs101
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs6
-rw-r--r--src/librustc_mir/hair/cx/expr.rs34
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs20
-rw-r--r--src/librustc_mir/interpret/eval_context.rs4
-rw-r--r--src/librustc_mir/lib.rs15
-rw-r--r--src/librustc_mir/monomorphize/collector.rs8
-rw-r--r--src/librustc_mir/monomorphize/item.rs2
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs12
-rw-r--r--src/librustc_mir/util/borrowck_errors.rs3
-rw-r--r--src/librustc_mir/util/collect_writes.rs67
-rw-r--r--src/librustc_mir/util/mod.rs1
-rw-r--r--src/librustc_mir/util/pretty.rs10
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_passes/rvalue_promotion.rs1
-rw-r--r--src/librustc_platform_intrinsics/lib.rs1
-rw-r--r--src/librustc_plugin/lib.rs1
-rw-r--r--src/librustc_privacy/lib.rs15
-rw-r--r--src/librustc_resolve/lib.rs18
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs57
-rw-r--r--src/librustc_save_analysis/lib.rs11
-rw-r--r--src/librustc_save_analysis/span_utils.rs4
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_traits/lib.rs2
-rw-r--r--src/librustc_traits/lowering.rs97
-rw-r--r--src/librustc_traits/normalize_erasing_regions.rs7
-rw-r--r--src/librustc_traits/normalize_projection_ty.rs4
-rw-r--r--src/librustc_trans/allocator.rs26
-rw-r--r--src/librustc_trans/back/symbol_export.rs4
-rw-r--r--src/librustc_trans/back/write.rs19
-rw-r--r--src/librustc_trans/base.rs23
-rw-r--r--src/librustc_trans/context.rs2
-rw-r--r--src/librustc_trans/debuginfo/mod.rs8
-rw-r--r--src/librustc_trans/lib.rs2
-rw-r--r--src/librustc_trans/llvm_util.rs5
-rw-r--r--src/librustc_trans_utils/lib.rs3
-rw-r--r--src/librustc_trans_utils/symbol_names.rs4
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/check/_match.rs16
-rw-r--r--src/librustc_typeck/check/autoderef.rs4
-rw-r--r--src/librustc_typeck/check/cast.rs6
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs1
-rw-r--r--src/librustc_typeck/check/method/mod.rs5
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/method/suggest.rs67
-rw-r--r--src/librustc_typeck/check/mod.rs147
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/check/writeback.rs35
-rw-r--r--src/librustc_typeck/collect.rs29
-rw-r--r--src/librustc_typeck/diagnostics.rs89
-rw-r--r--src/librustc_typeck/lib.rs14
-rw-r--r--src/librustc_typeck/outlives/explicit.rs82
-rw-r--r--src/librustc_typeck/outlives/implicit_empty.rs52
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs442
-rw-r--r--src/librustc_typeck/outlives/mod.rs96
-rw-r--r--src/librustc_typeck/outlives/test.rs22
-rw-r--r--src/librustdoc/clean/auto_trait.rs8
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/librustdoc/html/render.rs241
-rw-r--r--src/librustdoc/html/static/rustdoc.css18
-rw-r--r--src/librustdoc/html/static/themes/dark.css7
-rw-r--r--src/librustdoc/html/static/themes/light.css7
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/libserialize/lib.rs1
-rw-r--r--src/libstd/alloc.rs121
-rw-r--r--src/libstd/collections/hash/map.rs8
-rw-r--r--src/libstd/collections/hash/table.rs21
-rw-r--r--src/libstd/collections/mod.rs10
-rw-r--r--src/libstd/error.rs19
-rw-r--r--src/libstd/f32.rs51
-rw-r--r--src/libstd/f64.rs50
-rw-r--r--src/libstd/heap.rs176
-rw-r--r--src/libstd/io/mod.rs3
-rw-r--r--src/libstd/lib.rs36
-rw-r--r--src/libstd/sync/mod.rs2
-rw-r--r--src/libstd/sync/mpsc/mpsc_queue.rs3
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs2
-rw-r--r--src/libstd/sys/cloudabi/thread.rs2
-rw-r--r--src/libstd/sys/redox/os_str.rs2
-rw-r--r--src/libstd/sys/redox/thread.rs2
-rw-r--r--src/libstd/sys/unix/os_str.rs2
-rw-r--r--src/libstd/sys/unix/thread.rs2
-rw-r--r--src/libstd/sys/wasm/os_str.rs2
-rw-r--r--src/libstd/sys/wasm/thread.rs2
-rw-r--r--src/libstd/sys/windows/process.rs2
-rw-r--r--src/libstd/sys/windows/thread.rs2
-rw-r--r--src/libstd/sys_common/at_exit_imp.rs2
-rw-r--r--src/libstd/sys_common/bytestring.rs2
-rw-r--r--src/libstd/sys_common/process.rs2
-rw-r--r--src/libstd/sys_common/thread.rs2
-rw-r--r--src/libstd_unicode/Cargo.toml4
-rw-r--r--src/libstd_unicode/lib.rs35
-rw-r--r--src/libstd_unicode/u_str.rs189
-rw-r--r--src/libsyntax/ast.rs7
-rw-r--r--src/libsyntax/attr.rs46
-rw-r--r--src/libsyntax/ext/base.rs20
-rw-r--r--src/libsyntax/ext/build.rs4
-rw-r--r--src/libsyntax/feature_gate.rs28
-rw-r--r--src/libsyntax/fold.rs5
-rw-r--r--src/libsyntax/lib.rs8
-rw-r--r--src/libsyntax/parse/lexer/mod.rs11
-rw-r--r--src/libsyntax/parse/mod.rs17
-rw-r--r--src/libsyntax/parse/parser.rs88
-rw-r--r--src/libsyntax/parse/token.rs32
-rw-r--r--src/libsyntax/print/pprust.rs8
-rw-r--r--src/libsyntax/util/parser.rs3
-rw-r--r--src/libsyntax/visit.rs3
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs10
-rw-r--r--src/libsyntax_ext/lib.rs1
-rw-r--r--src/libsyntax_pos/hygiene.rs2
-rw-r--r--src/libsyntax_pos/lib.rs1
-rw-r--r--src/libterm/lib.rs1
-rw-r--r--src/libtest/lib.rs1
-rw-r--r--src/libunwind/lib.rs1
m---------src/llvm0
-rw-r--r--src/rustc/dlmalloc_shim/Cargo.toml1
-rw-r--r--src/rustc/rustc.rs1
-rw-r--r--src/rustllvm/llvm-rebuild-trigger2
-rw-r--r--src/test/codegen/link_section.rs6
-rw-r--r--src/test/codegen/packed.rs84
-rw-r--r--src/test/compile-fail/allocator/not-an-allocator.rs15
-rw-r--r--src/test/compile-fail/borrowck/borrowck-issue-14498.rs2
-rw-r--r--src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs2
-rw-r--r--src/test/compile-fail/catch-bad-lifetime.rs2
-rw-r--r--src/test/compile-fail/catch-bad-type.rs13
-rw-r--r--src/test/compile-fail/catch-maybe-bad-lifetime.rs4
-rw-r--r--src/test/compile-fail/catch-opt-init.rs1
-rw-r--r--src/test/compile-fail/conflicting-repr-hints.rs11
-rw-r--r--src/test/compile-fail/issue-19244-1.rs2
-rw-r--r--src/test/compile-fail/lint-non-uppercase-statics.rs3
-rw-r--r--src/test/compile-fail/outlives-associated-types.rs4
-rw-r--r--src/test/compile-fail/single-primitive-inherent-impl.rs8
-rw-r--r--src/test/compile-fail/struct-field-privacy.rs2
-rw-r--r--src/test/compile-fail/tuple-index-out-of-bounds.rs4
-rw-r--r--src/test/mir-opt/end_region_cyclic.rs56
-rw-r--r--src/test/mir-opt/validate_3.rs34
-rw-r--r--src/test/run-make-fulldeps/std-core-cycle/bar.rs8
-rw-r--r--src/test/run-pass/align-struct.rs22
-rw-r--r--src/test/run-pass/allocator-alloc-one.rs4
-rw-r--r--src/test/run-pass/allocator/auxiliary/custom.rs8
-rw-r--r--src/test/run-pass/allocator/custom.rs12
-rw-r--r--src/test/run-pass/allocator/xcrate-use.rs6
-rw-r--r--src/test/run-pass/allocator/xcrate-use2.rs12
-rw-r--r--src/test/run-pass/auxiliary/packed.rs18
-rw-r--r--src/test/run-pass/cast.rs5
-rw-r--r--src/test/run-pass/catch-expr.rs25
-rw-r--r--src/test/run-pass/char_unicode.rs4
-rw-r--r--src/test/run-pass/issue-48159.rs37
-rw-r--r--src/test/run-pass/issue-49556.rs22
-rw-r--r--src/test/run-pass/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs24
-rw-r--r--src/test/run-pass/packed-struct-borrow-element.rs25
-rw-r--r--src/test/run-pass/packed-struct-generic-size.rs33
-rw-r--r--src/test/run-pass/packed-struct-match.rs37
-rw-r--r--src/test/run-pass/packed-struct-size-xc.rs11
-rw-r--r--src/test/run-pass/packed-struct-size.rs126
-rw-r--r--src/test/run-pass/packed-struct-vec.rs99
-rw-r--r--src/test/run-pass/packed-tuple-struct-size.rs68
-rw-r--r--src/test/run-pass/realloc-16687.rs18
-rw-r--r--src/test/run-pass/regions-mock-trans.rs7
-rw-r--r--src/test/run-pass/type-sizes.rs7
-rw-r--r--src/test/run-pass/union/union-packed.rs112
-rw-r--r--src/test/rustdoc/all.rs30
-rw-r--r--src/test/ui/asm-out-assign-imm.rs1
-rw-r--r--src/test/ui/asm-out-assign-imm.stderr2
-rw-r--r--src/test/ui/augmented-assignments.nll.stderr26
-rw-r--r--src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr25
-rw-r--r--src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr78
-rw-r--r--src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr14
-rw-r--r--src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr18
-rw-r--r--src/test/ui/borrowck/borrowck-in-static.nll.stderr9
-rw-r--r--src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr40
-rw-r--r--src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr15
-rw-r--r--src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr14
-rw-r--r--src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs4
-rw-r--r--src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr51
-rw-r--r--src/test/ui/borrowck/issue-45983.nll.stderr30
-rw-r--r--src/test/ui/borrowck/issue-7573.nll.stderr14
-rw-r--r--src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr21
-rw-r--r--src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr14
-rw-r--r--src/test/ui/borrowck/mut-borrow-outside-loop.rs4
-rw-r--r--src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr14
-rw-r--r--src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr14
-rw-r--r--src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr14
-rw-r--r--src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr9
-rw-r--r--src/test/ui/catch-block-type-error.rs26
-rw-r--r--src/test/ui/catch-block-type-error.stderr21
-rw-r--r--src/test/ui/chalkify/lower_trait.rs3
-rw-r--r--src/test/ui/chalkify/lower_trait.stderr20
-rw-r--r--src/test/ui/chalkify/lower_trait_higher_rank.rs24
-rw-r--r--src/test/ui/chalkify/lower_trait_higher_rank.stderr26
-rw-r--r--src/test/ui/chalkify/lower_trait_where_clause.rs31
-rw-r--r--src/test/ui/chalkify/lower_trait_where_clause.stderr44
-rw-r--r--src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr44
-rw-r--r--src/test/ui/closure_context/issue-42065.nll.stderr11
-rw-r--r--src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr9
-rw-r--r--src/test/ui/codemap_tests/issue-11715.nll.stderr12
-rw-r--r--src/test/ui/codemap_tests/issue-11715.rs4
-rw-r--r--src/test/ui/codemap_tests/one_line.nll.stderr13
-rw-r--r--src/test/ui/codemap_tests/overlapping_spans.nll.stderr9
-rw-r--r--src/test/ui/codemap_tests/tab_3.nll.stderr14
-rw-r--r--src/test/ui/command-line-diagnostics.nll.stderr11
-rw-r--r--src/test/ui/did_you_mean/issue-31424.nll.stderr15
-rw-r--r--src/test/ui/did_you_mean/issue-34126.nll.stderr13
-rw-r--r--src/test/ui/did_you_mean/issue-34337.nll.stderr9
-rw-r--r--src/test/ui/did_you_mean/issue-35937.nll.stderr28
-rw-r--r--src/test/ui/did_you_mean/issue-37139.nll.stderr9
-rw-r--r--src/test/ui/did_you_mean/issue-38147-1.nll.stderr11
-rw-r--r--src/test/ui/did_you_mean/issue-38147-2.nll.stderr9
-rw-r--r--src/test/ui/did_you_mean/issue-38147-3.nll.stderr9
-rw-r--r--src/test/ui/did_you_mean/issue-38147-4.nll.stderr11
-rw-r--r--src/test/ui/did_you_mean/issue-39544.nll.stderr98
-rw-r--r--src/test/ui/did_you_mean/issue-40823.nll.stderr9
-rw-r--r--src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs44
-rw-r--r--src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr50
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr14
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-extern-crate.rs4
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr14
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-reorder.rs4
-rw-r--r--src/test/ui/dropck/dropck-eyepatch.nll.stderr14
-rw-r--r--src/test/ui/dropck/dropck-eyepatch.rs4
-rw-r--r--src/test/ui/error-codes/E0017.nll.stderr28
-rw-r--r--src/test/ui/error-codes/E0161.nll.stderr16
-rw-r--r--src/test/ui/error-codes/E0388.nll.stderr28
-rw-r--r--src/test/ui/error-codes/E0389.nll.stderr11
-rw-r--r--src/test/ui/error-codes/E0499.nll.stderr12
-rw-r--r--src/test/ui/error-codes/E0499.rs4
-rw-r--r--src/test/ui/error-codes/E0502.nll.stderr9
-rw-r--r--src/test/ui/error-codes/E0502.rs4
-rw-r--r--src/test/ui/error-codes/E0503.nll.stderr12
-rw-r--r--src/test/ui/error-codes/E0503.rs4
-rw-r--r--src/test/ui/error-codes/E0504.nll.stderr18
-rw-r--r--src/test/ui/error-codes/E0505.nll.stderr14
-rw-r--r--src/test/ui/error-codes/E0505.rs4
-rw-r--r--src/test/ui/error-codes/E0509.nll.stderr9
-rw-r--r--src/test/ui/error-codes/E0597.nll.stderr13
-rw-r--r--src/test/ui/error-codes/E0597.rs4
-rw-r--r--src/test/ui/error-codes/E0609.stderr4
-rw-r--r--src/test/ui/error-codes/E0611.stderr9
-rw-r--r--src/test/ui/error-codes/E0612.stderr9
-rw-r--r--src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr14
-rw-r--r--src/test/ui/error-codes/ex-E0611.rs (renamed from src/test/ui/error-codes/E0611.rs)2
-rw-r--r--src/test/ui/error-codes/ex-E0611.stderr9
-rw-r--r--src/test/ui/error-codes/ex-E0612.rs (renamed from src/test/ui/error-codes/E0612.rs)2
-rw-r--r--src/test/ui/error-codes/ex-E0612.stderr9
-rw-r--r--src/test/ui/feature-gate-infer_outlives_requirements.rs18
-rw-r--r--src/test/ui/feature-gate-infer_outlives_requirements.stderr17
-rw-r--r--src/test/ui/feature-gate-nll.nll.stderr13
-rw-r--r--src/test/ui/feature-gate-nll.rs4
-rw-r--r--src/test/ui/feature-gate-repr_packed.rs (renamed from src/libstd_unicode/tests/lib.rs)9
-rw-r--r--src/test/ui/feature-gate-repr_packed.stderr11
-rw-r--r--src/test/ui/generator/borrowing.nll.stderr14
-rw-r--r--src/test/ui/generator/borrowing.rs4
-rw-r--r--src/test/ui/generator/dropck.nll.stderr14
-rw-r--r--src/test/ui/generator/dropck.rs4
-rw-r--r--src/test/ui/generator/pattern-borrow.nll.stderr8
-rw-r--r--src/test/ui/generator/pattern-borrow.rs4
-rw-r--r--src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr12
-rw-r--r--src/test/ui/generator/yield-in-args.nll.stderr9
-rw-r--r--src/test/ui/generator/yield-while-iterating.nll.stderr55
-rw-r--r--src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr18
-rw-r--r--src/test/ui/hygiene/assoc_item_ctxt.rs (renamed from src/test/compile-fail/hygiene/assoc_item_ctxt.rs)0
-rw-r--r--src/test/ui/hygiene/assoc_item_ctxt.stderr25
-rw-r--r--src/test/ui/hygiene/assoc_ty_bindings.rs (renamed from src/test/compile-fail/hygiene/assoc_ty_bindings.rs)0
-rw-r--r--src/test/ui/hygiene/assoc_ty_bindings.stderr8
-rw-r--r--src/test/ui/hygiene/auxiliary/intercrate.rs (renamed from src/test/compile-fail/hygiene/auxiliary/intercrate.rs)0
-rw-r--r--src/test/ui/hygiene/fields-definition.rs32
-rw-r--r--src/test/ui/hygiene/fields-definition.stderr14
-rw-r--r--src/test/ui/hygiene/fields-move.rs40
-rw-r--r--src/test/ui/hygiene/fields-move.stderr39
-rw-r--r--src/test/ui/hygiene/fields-numeric-borrowck.rs18
-rw-r--r--src/test/ui/hygiene/fields-numeric-borrowck.stderr14
-rw-r--r--src/test/ui/hygiene/fields.rs (renamed from src/test/compile-fail/hygiene/fields.rs)0
-rw-r--r--src/test/ui/hygiene/fields.stderr38
-rw-r--r--src/test/ui/hygiene/for-loop.rs (renamed from src/test/compile-fail/for-loop-hygiene.rs)0
-rw-r--r--src/test/ui/hygiene/for-loop.stderr9
-rw-r--r--src/test/ui/hygiene/globs.rs (renamed from src/test/compile-fail/hygiene/globs.rs)0
-rw-r--r--src/test/ui/hygiene/globs.stderr49
-rw-r--r--src/test/ui/hygiene/impl_items.rs (renamed from src/test/compile-fail/hygiene/impl_items.rs)0
-rw-r--r--src/test/ui/hygiene/impl_items.stderr11
-rw-r--r--src/test/ui/hygiene/intercrate.rs (renamed from src/test/compile-fail/hygiene/intercrate.rs)0
-rw-r--r--src/test/ui/hygiene/intercrate.stderr10
-rw-r--r--src/test/ui/hygiene/nested_macro_privacy.rs (renamed from src/test/compile-fail/hygiene/nested_macro_privacy.rs)0
-rw-r--r--src/test/ui/hygiene/nested_macro_privacy.stderr9
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.rs (renamed from src/test/compile-fail/hygiene/no_implicit_prelude.rs)0
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.stderr30
-rw-r--r--src/test/ui/hygiene/pattern-macro.rs (renamed from src/test/compile-fail/pattern-macro-hygiene.rs)0
-rw-r--r--src/test/ui/hygiene/pattern-macro.stderr9
-rw-r--r--src/test/ui/hygiene/privacy.rs (renamed from src/test/compile-fail/hygiene/privacy.rs)0
-rw-r--r--src/test/ui/hygiene/privacy.stderr9
-rw-r--r--src/test/ui/hygiene/trait_items.rs (renamed from src/test/compile-fail/hygiene/trait_items.rs)0
-rw-r--r--src/test/ui/hygiene/trait_items.stderr16
-rw-r--r--src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr14
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched.nll.stderr32
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr17
-rw-r--r--src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr13
-rw-r--r--src/test/ui/issue-13058.nll.stderr27
-rw-r--r--src/test/ui/issue-17263.nll.stderr14
-rw-r--r--src/test/ui/issue-17263.rs4
-rw-r--r--src/test/ui/issue-21600.nll.stderr15
-rw-r--r--src/test/ui/issue-25793.nll.stderr8
-rw-r--r--src/test/ui/issue-25793.rs4
-rw-r--r--src/test/ui/issue-36400.nll.stderr11
-rw-r--r--src/test/ui/issue-40402-ref-hints/issue-40402-1.nll.stderr9
-rw-r--r--src/test/ui/issue-40402-ref-hints/issue-40402-2.nll.stderr15
-rw-r--r--src/test/ui/issue-42106.nll.stderr8
-rw-r--r--src/test/ui/issue-42106.rs4
-rw-r--r--src/test/ui/issue-4335.nll.stderr25
-rw-r--r--src/test/ui/issue-45697-1.nll.stderr34
-rw-r--r--src/test/ui/issue-45697.nll.stderr34
-rw-r--r--src/test/ui/issue-46471-1.nll.stderr28
-rw-r--r--src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs4
-rw-r--r--src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr11
-rw-r--r--src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr22
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr23
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr18
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr18
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr20
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr20
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr20
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr31
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr19
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr19
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr18
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr28
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr19
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr19
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr24
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr24
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr17
-rw-r--r--src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr10
-rw-r--r--src/test/ui/lifetimes/borrowck-let-suggestion.rs4
-rw-r--r--src/test/ui/macros/macro-backtrace-invalid-internals.rs4
-rw-r--r--src/test/ui/macros/macro-backtrace-invalid-internals.stderr18
-rw-r--r--src/test/ui/macros/span-covering-argument-1.nll.stderr12
-rw-r--r--src/test/ui/moves-based-on-type-block-bad.nll.stderr9
-rw-r--r--src/test/ui/moves-based-on-type-match-bindings.nll.stderr14
-rw-r--r--src/test/ui/nll/get_default.nll.stderr51
-rw-r--r--src/test/ui/nll/issue-16223.rs63
-rw-r--r--src/test/ui/nll/issue-47388.rs20
-rw-r--r--src/test/ui/nll/issue-47388.stderr11
-rw-r--r--src/test/ui/order-dependent-cast-inference.rs18
-rw-r--r--src/test/ui/order-dependent-cast-inference.stderr13
-rw-r--r--src/test/ui/print_type_sizes/packed.rs32
-rw-r--r--src/test/ui/print_type_sizes/packed.stdout18
-rw-r--r--src/test/ui/region-borrow-params-issue-29793-small.nll.stderr279
-rw-r--r--src/test/ui/regions-nested-fns-2.nll.stderr16
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr14
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr21
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr21
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/enum-pass.rs38
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/enum.rs37
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/enum.stderr31
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-impl-lifetime-pass.rs30
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-impl-pass.rs30
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-impl.rs30
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-impl.stderr17
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-where-pass.rs27
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-where.rs23
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-where.stderr17
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/multiple-regions-pass.rs22
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/multiple-regions.rs19
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/multiple-regions.stderr20
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/nested-structs-pass.rs25
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/nested-structs.rs26
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr17
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/projections-pass.rs23
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/projections.rs20
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/projections.stderr16
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/reference-pass.rs23
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/reference.rs18
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/reference.stderr17
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/union-pass.rs39
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/union.rs40
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/union.stderr31
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr51
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr27
-rw-r--r--src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr54
-rw-r--r--src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr9
-rw-r--r--src/test/ui/span/borrowck-fn-in-const-b.nll.stderr9
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr10
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.rs4
-rw-r--r--src/test/ui/span/borrowck-object-mutability.nll.stderr17
-rw-r--r--src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr14
-rw-r--r--src/test/ui/span/destructor-restrictions.nll.stderr0
-rw-r--r--src/test/ui/span/dropck-object-cycle.nll.stderr15
-rw-r--r--src/test/ui/span/dropck_arr_cycle_checked.nll.stderr39
-rw-r--r--src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr27
-rw-r--r--src/test/ui/span/dropck_misc_variants.nll.stderr26
-rw-r--r--src/test/ui/span/dropck_vec_cycle_checked.nll.stderr39
-rw-r--r--src/test/ui/span/issue-11925.nll.stderr12
-rw-r--r--src/test/ui/span/issue-15480.nll.stderr14
-rw-r--r--src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr0
-rw-r--r--src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr15
-rw-r--r--src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr36
-rw-r--r--src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr14
-rw-r--r--src/test/ui/span/issue-25199.nll.stderr15
-rw-r--r--src/test/ui/span/issue-26656.nll.stderr14
-rw-r--r--src/test/ui/span/issue-29106.nll.stderr25
-rw-r--r--src/test/ui/span/issue-36537.nll.stderr13
-rw-r--r--src/test/ui/span/issue-36537.rs4
-rw-r--r--src/test/ui/span/issue-40157.nll.stderr13
-rw-r--r--src/test/ui/span/issue28498-reject-ex1.nll.stderr15
-rw-r--r--src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr15
-rw-r--r--src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr15
-rw-r--r--src/test/ui/span/issue28498-reject-trait-bound.nll.stderr15
-rw-r--r--src/test/ui/span/mut-arg-hint.nll.stderr21
-rw-r--r--src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr14
-rw-r--r--src/test/ui/span/mut-ptr-cant-outlive-ref.rs4
-rw-r--r--src/test/ui/span/range-2.nll.stderr14
-rw-r--r--src/test/ui/span/range-2.rs4
-rw-r--r--src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr14
-rw-r--r--src/test/ui/span/regionck-unboxed-closure-lifetimes.rs4
-rw-r--r--src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr14
-rw-r--r--src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr18
-rw-r--r--src/test/ui/span/regions-escape-loop-via-variable.nll.stderr13
-rw-r--r--src/test/ui/span/regions-escape-loop-via-vec.nll.stderr49
-rw-r--r--src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr14
-rw-r--r--src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr30
-rw-r--r--src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr37
-rw-r--r--src/test/ui/span/send-is-not-static-std-sync.nll.stderr48
-rw-r--r--src/test/ui/span/slice-borrow.nll.stderr14
-rw-r--r--src/test/ui/span/slice-borrow.rs4
-rw-r--r--src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr27
-rw-r--r--src/test/ui/span/vec_refs_data_with_early_death.nll.stderr14
-rw-r--r--src/test/ui/span/vec_refs_data_with_early_death.rs4
-rw-r--r--src/test/ui/span/wf-method-late-bound-regions.nll.stderr14
-rw-r--r--src/test/ui/span/wf-method-late-bound-regions.rs4
-rw-r--r--src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr9
-rw-r--r--src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr9
-rw-r--r--src/test/ui/target-feature-wrong.rs3
-rw-r--r--src/test/ui/target-feature-wrong.stderr14
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr36
m---------src/tools/clippy28
-rw-r--r--src/tools/compiletest/src/header.rs2
m---------src/tools/rls0
-rw-r--r--src/tools/rustdoc/main.rs2
-rw-r--r--src/tools/tidy/src/lib.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs31
601 files changed, 11639 insertions, 4697 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index e7896d247b4..e5297d1482e 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -13,14 +13,12 @@ dependencies = [
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "std_unicode 0.0.0",
 ]
 
 [[package]]
 name = "alloc_jemalloc"
 version = "0.0.0"
 dependencies = [
- "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -33,7 +31,6 @@ dependencies = [
 name = "alloc_system"
 version = "0.0.0"
 dependencies = [
- "alloc 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "dlmalloc 0.0.0",
@@ -286,11 +283,11 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.0.191"
+version = "0.0.193"
 dependencies = [
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
- "clippy_lints 0.0.191",
+ "clippy_lints 0.0.193",
  "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -306,7 +303,7 @@ version = "0.2.0"
 
 [[package]]
 name = "clippy_lints"
-version = "0.0.191"
+version = "0.0.193"
 dependencies = [
  "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -543,7 +540,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "dlmalloc"
 version = "0.0.0"
 dependencies = [
- "alloc 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
@@ -1579,7 +1575,7 @@ version = "0.126.0"
 dependencies = [
  "cargo 0.27.0",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "clippy_lints 0.0.191",
+ "clippy_lints 0.0.193",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "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)",
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 6701f58ba8e..3dd9b684059 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -279,6 +279,10 @@ fn main() {
         cmd.arg("--color=always");
     }
 
+    if env::var_os("RUSTC_DENY_WARNINGS").is_some() {
+        cmd.arg("-Dwarnings");
+    }
+
     if verbose > 1 {
         eprintln!("rustc command: {:?}", cmd);
         eprintln!("sysroot: {:?}", sysroot);
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 3f5ec4933d0..7ff64af9196 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -698,6 +698,11 @@ impl<'a> Builder<'a> {
 
         cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
 
+        // in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful.
+        if self.config.deny_warnings && !(mode == Mode::Libstd && stage == 0) {
+            cargo.env("RUSTC_DENY_WARNINGS", "1");
+        }
+
         // Throughout the build Cargo can execute a number of build scripts
         // compiling C/C++ code and we need to pass compilers, archivers, flags, etc
         // obtained previously to those build scripts.
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 9cc18464fea..b411b19bd53 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -1167,7 +1167,9 @@ pub fn stream_cargo(
     cargo.arg("--message-format").arg("json")
          .stdout(Stdio::piped());
 
-    if stderr_isatty() && build.ci_env == CiEnv::None {
+    if stderr_isatty() && build.ci_env == CiEnv::None &&
+        // if the terminal is reported as dumb, then we don't want to enable color for rustc
+        env::var_os("TERM").map(|t| t != *"dumb").unwrap_or(true) {
         // since we pass message-format=json to cargo, we need to tell the rustc
         // wrapper to give us colored output if necessary. This is because we
         // only want Cargo's JSON output, not rustcs.
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 95baf4f8cca..239316d45c4 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -71,6 +71,8 @@ pub struct Config {
     pub incremental: bool,
     pub dry_run: bool,
 
+    pub deny_warnings: bool,
+
     // llvm codegen options
     pub llvm_enabled: bool,
     pub llvm_assertions: bool,
@@ -301,6 +303,7 @@ struct Rust {
     codegen_backends_dir: Option<String>,
     wasm_syscall: Option<bool>,
     lld: Option<bool>,
+    deny_warnings: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -340,6 +343,7 @@ impl Config {
         config.test_miri = false;
         config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
         config.rust_codegen_backends_dir = "codegen-backends".to_owned();
+        config.deny_warnings = true;
 
         // set by bootstrap.py
         config.src = env::var_os("SRC").map(PathBuf::from).expect("'SRC' to be set");
@@ -366,6 +370,9 @@ impl Config {
         config.incremental = flags.incremental;
         config.dry_run = flags.dry_run;
         config.keep_stage = flags.keep_stage;
+        if let Some(value) = flags.warnings {
+            config.deny_warnings = value;
+        }
 
         if config.dry_run {
             let dir = config.out.join("tmp-dry-run");
@@ -511,6 +518,7 @@ impl Config {
             config.rustc_default_linker = rust.default_linker.clone();
             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));
 
             if let Some(ref backends) = rust.codegen_backends {
                 config.rust_codegen_backends = backends.iter()
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index ef902c68d12..3eb9dca2aa8 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -42,6 +42,9 @@ pub struct Flags {
     pub exclude: Vec<PathBuf>,
     pub rustc_error_format: Option<String>,
     pub dry_run: bool,
+
+    // true => deny
+    pub warnings: Option<bool>,
 }
 
 pub enum Subcommand {
@@ -118,6 +121,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
         opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
         opts.optflag("h", "help", "print this help message");
+        opts.optopt("", "warnings", "if value is deny, will deny warnings, otherwise use default",
+            "VALUE");
         opts.optopt("", "error-format", "rustc error format", "FORMAT");
 
         // fn usage()
@@ -374,6 +379,7 @@ Arguments:
             incremental: matches.opt_present("incremental"),
             exclude: split(matches.opt_strs("exclude"))
                 .into_iter().map(|p| p.into()).collect::<Vec<_>>(),
+            warnings: matches.opt_str("warnings").map(|v| v == "deny"),
         }
     }
 }
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 5a12afd03e1..2f9953330f4 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 use std::fs::File;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
-use std::{fs, env};
 use std::time::{SystemTime, UNIX_EPOCH};
+use std::{env, fs};
 
 /// A helper macro to `unwrap` a result except also print out details like:
 ///
@@ -26,10 +24,12 @@ use std::time::{SystemTime, UNIX_EPOCH};
 /// using a `Result` with `try!`, but this may change one day...
 #[macro_export]
 macro_rules! t {
-    ($e:expr) => (match $e {
-        Ok(e) => e,
-        Err(e) => panic!("{} failed with {}", stringify!($e), e),
-    })
+    ($e:expr) => {
+        match $e {
+            Ok(e) => e,
+            Err(e) => panic!("{} failed with {}", stringify!($e), e),
+        }
+    };
 }
 
 pub fn run(cmd: &mut Command) {
@@ -46,14 +46,17 @@ pub fn run_silent(cmd: &mut Command) {
 pub fn try_run_silent(cmd: &mut Command) -> bool {
     let status = match cmd.status() {
         Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
-                                cmd, e)),
+        Err(e) => fail(&format!(
+            "failed to execute command: {:?}\nerror: {}",
+            cmd, e
+        )),
     };
     if !status.success() {
-        println!("\n\ncommand did not execute successfully: {:?}\n\
-                  expected success, got: {}\n\n",
-                 cmd,
-                 status);
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n",
+            cmd, status
+        );
     }
     status.success()
 }
@@ -67,18 +70,22 @@ pub fn run_suppressed(cmd: &mut Command) {
 pub fn try_run_suppressed(cmd: &mut Command) -> bool {
     let output = match cmd.output() {
         Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
-                                cmd, e)),
+        Err(e) => fail(&format!(
+            "failed to execute command: {:?}\nerror: {}",
+            cmd, e
+        )),
     };
     if !output.status.success() {
-        println!("\n\ncommand did not execute successfully: {:?}\n\
-                  expected success, got: {}\n\n\
-                  stdout ----\n{}\n\
-                  stderr ----\n{}\n\n",
-                 cmd,
-                 output.status,
-                 String::from_utf8_lossy(&output.stdout),
-                 String::from_utf8_lossy(&output.stderr));
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n\
+             stdout ----\n{}\n\
+             stderr ----\n{}\n\n",
+            cmd,
+            output.status,
+            String::from_utf8_lossy(&output.stdout),
+            String::from_utf8_lossy(&output.stderr)
+        );
     }
     output.status.success()
 }
@@ -94,9 +101,9 @@ pub fn gnu_target(target: &str) -> String {
 }
 
 pub fn make(host: &str) -> PathBuf {
-    if host.contains("bitrig") || host.contains("dragonfly") ||
-        host.contains("freebsd") || host.contains("netbsd") ||
-        host.contains("openbsd") {
+    if host.contains("bitrig") || host.contains("dragonfly") || host.contains("freebsd")
+        || host.contains("netbsd") || host.contains("openbsd")
+    {
         PathBuf::from("gmake")
     } else {
         PathBuf::from("make")
@@ -106,23 +113,27 @@ pub fn make(host: &str) -> PathBuf {
 pub fn output(cmd: &mut Command) -> String {
     let output = match cmd.stderr(Stdio::inherit()).output() {
         Ok(status) => status,
-        Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
-                                cmd, e)),
+        Err(e) => fail(&format!(
+            "failed to execute command: {:?}\nerror: {}",
+            cmd, e
+        )),
     };
     if !output.status.success() {
-        panic!("command did not execute successfully: {:?}\n\
-                expected success, got: {}",
-               cmd,
-               output.status);
+        panic!(
+            "command did not execute successfully: {:?}\n\
+             expected success, got: {}",
+            cmd, output.status
+        );
     }
     String::from_utf8(output.stdout).unwrap()
 }
 
 pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
-    let mut stack = dir.read_dir().unwrap()
-                       .map(|e| e.unwrap())
-                       .filter(|e| &*e.file_name() != ".git")
-                       .collect::<Vec<_>>();
+    let mut stack = dir.read_dir()
+        .unwrap()
+        .map(|e| e.unwrap())
+        .filter(|e| &*e.file_name() != ".git")
+        .collect::<Vec<_>>();
     while let Some(entry) = stack.pop() {
         let path = entry.path();
         if entry.file_type().unwrap().is_dir() {
@@ -135,7 +146,9 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
 
 /// Returns the last-modified time for `path`, or zero if it doesn't exist.
 pub fn mtime(path: &Path) -> SystemTime {
-    fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)
+    fs::metadata(path)
+        .and_then(|f| f.modified())
+        .unwrap_or(UNIX_EPOCH)
 }
 
 /// Returns whether `dst` is up to date given that the file or files in `src`
@@ -176,11 +189,12 @@ impl Drop for NativeLibBoilerplate {
 // If Err is returned, then everything is up-to-date and further build actions can be skipped.
 // Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
 // of scope, so all the build actions should be completed until then.
-pub fn native_lib_boilerplate(src_name: &str,
-                              out_name: &str,
-                              link_name: &str,
-                              search_subdir: &str)
-                              -> Result<NativeLibBoilerplate, ()> {
+pub fn native_lib_boilerplate(
+    src_name: &str,
+    out_name: &str,
+    link_name: &str,
+    search_subdir: &str,
+) -> Result<NativeLibBoilerplate, ()> {
     let current_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
     let src_dir = current_dir.join("..").join(src_name);
     rerun_if_changed_anything_in_dir(&src_dir);
@@ -193,11 +207,17 @@ pub fn native_lib_boilerplate(src_name: &str,
     } else {
         println!("cargo:rustc-link-lib=static={}", link_name);
     }
-    println!("cargo:rustc-link-search=native={}", out_dir.join(search_subdir).display());
+    println!(
+        "cargo:rustc-link-search=native={}",
+        out_dir.join(search_subdir).display()
+    );
 
     let timestamp = out_dir.join("rustbuild.timestamp");
     if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(&src_dir, &timestamp) {
-        Ok(NativeLibBoilerplate { src_dir: src_dir, out_dir: out_dir })
+        Ok(NativeLibBoilerplate {
+            src_dir: src_dir,
+            out_dir: out_dir,
+        })
     } else {
         Err(())
     }
@@ -215,10 +235,12 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result<NativeLibBoiler
         ),
         _ => return Err(()),
     };
-    native_lib_boilerplate("libcompiler_builtins/compiler-rt",
-                           sanitizer_name,
-                           &link_name,
-                           search_path)
+    native_lib_boilerplate(
+        "libcompiler_builtins/compiler-rt",
+        sanitizer_name,
+        &link_name,
+        search_path,
+    )
 }
 
 fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
index fb0bd06ce30..f87ba8fe4e6 100644
--- a/src/ci/docker/scripts/musl.sh
+++ b/src/ci/docker/scripts/musl.sh
@@ -40,7 +40,7 @@ if [ ! -d $MUSL ]; then
 fi
 
 cd $MUSL
-./configure --disable-shared --prefix=/musl-$TAG $@
+./configure --enable-optimize --enable-debug --disable-shared --prefix=/musl-$TAG $@
 if [ "$TAG" = "i586" -o "$TAG" = "i686" ]; then
   hide_output make -j$(nproc) AR=ar RANLIB=ranlib
 else
diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile
index 6c0ec1ad9d4..853923ad947 100644
--- a/src/ci/docker/wasm32-unknown/Dockerfile
+++ b/src/ci/docker/wasm32-unknown/Dockerfile
@@ -34,4 +34,3 @@ ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \
   src/test/mir-opt \
   src/test/codegen-units \
   src/libcore \
-  src/libstd_unicode/ \
diff --git a/src/dlmalloc b/src/dlmalloc
-Subproject 9b2dcac06c3e23235f8997b3c5f2325a6d3382d
+Subproject c99638dc2ecfc750cc1656f6edb2bd062c1e098
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 6a8f0a27e9a58c55c89d07bc43a176fdae5e051
+Subproject 3c56329d1bd9038e5341f1962bcd8d043312a71
diff --git a/src/doc/unstable-book/src/language-features/catch-expr.md b/src/doc/unstable-book/src/language-features/catch-expr.md
index fbd213dca56..247333d841a 100644
--- a/src/doc/unstable-book/src/language-features/catch-expr.md
+++ b/src/doc/unstable-book/src/language-features/catch-expr.md
@@ -15,16 +15,16 @@ expression creates a new scope one can use the `?` operator in.
 use std::num::ParseIntError;
 
 let result: Result<i32, ParseIntError> = do catch {
-    Ok("1".parse::<i32>()?
+    "1".parse::<i32>()?
         + "2".parse::<i32>()?
-        + "3".parse::<i32>()?)
+        + "3".parse::<i32>()?
 };
 assert_eq!(result, Ok(6));
 
 let result: Result<i32, ParseIntError> = do catch {
-    Ok("1".parse::<i32>()?
+    "1".parse::<i32>()?
         + "foo".parse::<i32>()?
-        + "3".parse::<i32>()?)
+        + "3".parse::<i32>()?
 };
 assert!(result.is_err());
 ```
diff --git a/src/doc/unstable-book/src/language-features/global-allocator.md b/src/doc/unstable-book/src/language-features/global-allocator.md
index b3e6925b666..031b6347445 100644
--- a/src/doc/unstable-book/src/language-features/global-allocator.md
+++ b/src/doc/unstable-book/src/language-features/global-allocator.md
@@ -29,16 +29,17 @@ looks like:
 ```rust
 #![feature(global_allocator, allocator_api, heap_api)]
 
-use std::heap::{Alloc, System, Layout, AllocErr};
+use std::alloc::{GlobalAlloc, System, Layout, Opaque};
+use std::ptr::NonNull;
 
 struct MyAllocator;
 
-unsafe impl<'a> Alloc for &'a MyAllocator {
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
+unsafe impl GlobalAlloc for MyAllocator {
+    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
         System.alloc(layout)
     }
 
-    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
+    unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
         System.dealloc(ptr, layout)
     }
 }
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index c5167418614..6a7aea7f1c2 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -243,7 +243,7 @@ the source code.
   - `usize`: `libcore/num/mod.rs`
   - `f32`: `libstd/f32.rs`
   - `f64`: `libstd/f64.rs`
-  - `char`: `libstd_unicode/char.rs`
+  - `char`: `libcore/char.rs`
   - `slice`: `liballoc/slice.rs`
   - `str`: `liballoc/str.rs`
   - `const_ptr`: `libcore/ptr.rs`
diff --git a/src/doc/unstable-book/src/language-features/repr-packed.md b/src/doc/unstable-book/src/language-features/repr-packed.md
new file mode 100644
index 00000000000..2dd763d04b0
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/repr-packed.md
@@ -0,0 +1,8 @@
+# `repr_packed`
+
+The tracking issue for this feature is [#33158]
+
+[#33158]: https://github.com/rust-lang/rust/issues/33158
+
+------------------------
+
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index 2eb8ea12604..6383bd1e941 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -9,7 +9,6 @@ path = "lib.rs"
 
 [dependencies]
 core = { path = "../libcore" }
-std_unicode = { path = "../libstd_unicode" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 
 [dev-dependencies]
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
new file mode 100644
index 00000000000..68a617e0ffe
--- /dev/null
+++ b/src/liballoc/alloc.rs
@@ -0,0 +1,215 @@
+// Copyright 2014-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.
+
+#![unstable(feature = "allocator_api",
+            reason = "the precise API and guarantees it provides may be tweaked \
+                      slightly, especially to possibly take into account the \
+                      types being stored to make room for a future \
+                      tracing garbage collector",
+            issue = "32838")]
+
+use core::intrinsics::{min_align_of_val, size_of_val};
+use core::ptr::NonNull;
+use core::usize;
+
+#[doc(inline)]
+pub use core::alloc::*;
+
+#[cfg(stage0)]
+extern "Rust" {
+    #[allocator]
+    #[rustc_allocator_nounwind]
+    fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8;
+    #[cold]
+    #[rustc_allocator_nounwind]
+    fn __rust_oom(err: *const u8) -> !;
+    #[rustc_allocator_nounwind]
+    fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
+    #[rustc_allocator_nounwind]
+    fn __rust_realloc(ptr: *mut u8,
+                      old_size: usize,
+                      old_align: usize,
+                      new_size: usize,
+                      new_align: usize,
+                      err: *mut u8) -> *mut u8;
+    #[rustc_allocator_nounwind]
+    fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8;
+}
+
+#[cfg(not(stage0))]
+extern "Rust" {
+    #[allocator]
+    #[rustc_allocator_nounwind]
+    fn __rust_alloc(size: usize, align: usize) -> *mut u8;
+    #[cold]
+    #[rustc_allocator_nounwind]
+    fn __rust_oom() -> !;
+    #[rustc_allocator_nounwind]
+    fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
+    #[rustc_allocator_nounwind]
+    fn __rust_realloc(ptr: *mut u8,
+                      old_size: usize,
+                      align: usize,
+                      new_size: usize) -> *mut u8;
+    #[rustc_allocator_nounwind]
+    fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
+}
+
+#[derive(Copy, Clone, Default, Debug)]
+pub struct Global;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "type renamed to `Global`")]
+pub type Heap = Global;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "type renamed to `Global`")]
+#[allow(non_upper_case_globals)]
+pub const Heap: Global = Global;
+
+unsafe impl GlobalAlloc for Global {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
+        #[cfg(not(stage0))]
+        let ptr = __rust_alloc(layout.size(), layout.align());
+        #[cfg(stage0)]
+        let ptr = __rust_alloc(layout.size(), layout.align(), &mut 0);
+        ptr as *mut Opaque
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
+        __rust_dealloc(ptr as *mut u8, layout.size(), layout.align())
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *mut Opaque {
+        #[cfg(not(stage0))]
+        let ptr = __rust_realloc(ptr as *mut u8, layout.size(), layout.align(), new_size);
+        #[cfg(stage0)]
+        let ptr = __rust_realloc(ptr as *mut u8, layout.size(), layout.align(),
+                                 new_size, layout.align(), &mut 0);
+        ptr as *mut Opaque
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
+        #[cfg(not(stage0))]
+        let ptr = __rust_alloc_zeroed(layout.size(), layout.align());
+        #[cfg(stage0)]
+        let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0);
+        ptr as *mut Opaque
+    }
+
+    #[inline]
+    fn oom(&self) -> ! {
+        unsafe {
+            #[cfg(not(stage0))]
+            __rust_oom();
+            #[cfg(stage0)]
+            __rust_oom(&mut 0);
+        }
+    }
+}
+
+unsafe impl Alloc for Global {
+    #[inline]
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout) {
+        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+    }
+
+    #[inline]
+    unsafe fn realloc(&mut self,
+                      ptr: NonNull<Opaque>,
+                      layout: Layout,
+                      new_size: usize)
+                      -> Result<NonNull<Opaque>, AllocErr>
+    {
+        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    fn oom(&mut self) -> ! {
+        GlobalAlloc::oom(self)
+    }
+}
+
+/// The allocator for unique pointers.
+// This function must not unwind. If it does, MIR trans will fail.
+#[cfg(not(test))]
+#[lang = "exchange_malloc"]
+#[inline]
+unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
+    if size == 0 {
+        align as *mut u8
+    } else {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        let ptr = Global.alloc(layout);
+        if !ptr.is_null() {
+            ptr as *mut u8
+        } else {
+            Global.oom()
+        }
+    }
+}
+
+#[cfg_attr(not(test), lang = "box_free")]
+#[inline]
+pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+    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.
+    if size != 0 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        Global.dealloc(ptr as *mut Opaque, layout);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    extern crate test;
+    use self::test::Bencher;
+    use boxed::Box;
+    use alloc::{Global, Alloc, Layout};
+
+    #[test]
+    fn allocate_zeroed() {
+        unsafe {
+            let layout = Layout::from_size_align(1024, 1).unwrap();
+            let ptr = Global.alloc_zeroed(layout.clone())
+                .unwrap_or_else(|_| Global.oom());
+
+            let mut i = ptr.cast::<u8>().as_ptr();
+            let end = i.offset(layout.size() as isize);
+            while i < end {
+                assert_eq!(*i, 0);
+                i = i.offset(1);
+            }
+            Global.dealloc(ptr, layout);
+        }
+    }
+
+    #[bench]
+    fn alloc_owned_small(b: &mut Bencher) {
+        b.iter(|| {
+            let _: Box<_> = box 10;
+        })
+    }
+}
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index ccf2e2768d1..225b055d8ee 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -21,7 +21,6 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
 use core::borrow;
 use core::fmt;
 use core::cmp::Ordering;
-use core::heap::{Alloc, Layout};
 use core::intrinsics::abort;
 use core::mem::{self, align_of_val, size_of_val, uninitialized};
 use core::ops::Deref;
@@ -32,7 +31,7 @@ use core::hash::{Hash, Hasher};
 use core::{isize, usize};
 use core::convert::From;
 
-use heap::{Heap, box_free};
+use alloc::{Global, Alloc, Layout, box_free};
 use boxed::Box;
 use string::String;
 use vec::Vec;
@@ -513,15 +512,13 @@ impl<T: ?Sized> Arc<T> {
     // Non-inlined part of `drop`.
     #[inline(never)]
     unsafe fn drop_slow(&mut self) {
-        let ptr = self.ptr.as_ptr();
-
         // Destroy the data at this time, even though we may not free the box
         // allocation itself (there may still be weak pointers lying around).
         ptr::drop_in_place(&mut self.ptr.as_mut().data);
 
         if self.inner().weak.fetch_sub(1, Release) == 1 {
             atomic::fence(Acquire);
-            Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr))
+            Global.dealloc(self.ptr.as_opaque(), Layout::for_value(self.ptr.as_ref()))
         }
     }
 
@@ -555,11 +552,11 @@ impl<T: ?Sized> Arc<T> {
 
         let layout = Layout::for_value(&*fake_ptr);
 
-        let mem = Heap.alloc(layout)
-            .unwrap_or_else(|e| Heap.oom(e));
+        let mem = Global.alloc(layout)
+            .unwrap_or_else(|_| Global.oom());
 
         // Initialize the real ArcInner
-        let inner = set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>;
+        let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
 
         ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
         ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
@@ -626,7 +623,7 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
         // In the event of a panic, elements that have been written
         // into the new ArcInner will be dropped, then the memory freed.
         struct Guard<T> {
-            mem: *mut u8,
+            mem: NonNull<u8>,
             elems: *mut T,
             layout: Layout,
             n_elems: usize,
@@ -640,7 +637,7 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
                     let slice = from_raw_parts_mut(self.elems, self.n_elems);
                     ptr::drop_in_place(slice);
 
-                    Heap.dealloc(self.mem, self.layout.clone());
+                    Global.dealloc(self.mem.as_opaque(), self.layout.clone());
                 }
             }
         }
@@ -656,7 +653,7 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
             let elems = &mut (*ptr).data as *mut [T] as *mut T;
 
             let mut guard = Guard{
-                mem: mem,
+                mem: NonNull::new_unchecked(mem),
                 elems: elems,
                 layout: layout,
                 n_elems: 0,
@@ -1148,8 +1145,6 @@ impl<T: ?Sized> Drop for Weak<T> {
     /// assert!(other_weak_foo.upgrade().is_none());
     /// ```
     fn drop(&mut self) {
-        let ptr = self.ptr.as_ptr();
-
         // If we find out that we were the last weak pointer, then its time to
         // deallocate the data entirely. See the discussion in Arc::drop() about
         // the memory orderings
@@ -1161,7 +1156,7 @@ impl<T: ?Sized> Drop for Weak<T> {
         if self.inner().weak.fetch_sub(1, Release) == 1 {
             atomic::fence(Acquire);
             unsafe {
-                Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr))
+                Global.dealloc(self.ptr.as_opaque(), Layout::for_value(self.ptr.as_ref()))
             }
         }
     }
diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs
index 4d92fc67b2a..4f69aa6670b 100644
--- a/src/liballoc/benches/lib.rs
+++ b/src/liballoc/benches/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(rand)]
 #![feature(repr_simd)]
 #![feature(slice_sort_by_cached_key)]
diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs
index 49109d522e9..d6346662314 100644
--- a/src/liballoc/btree/node.rs
+++ b/src/liballoc/btree/node.rs
@@ -41,14 +41,13 @@
 // - A node of length `n` has `n` keys, `n` values, and (in an internal node) `n + 1` edges.
 //   This implies that even an empty internal node has at least one edge.
 
-use core::heap::{Alloc, Layout};
 use core::marker::PhantomData;
 use core::mem;
 use core::ptr::{self, Unique, NonNull};
 use core::slice;
 
+use alloc::{Global, Alloc, Layout};
 use boxed::Box;
-use heap::Heap;
 
 const B: usize = 6;
 pub const MIN_LEN: usize = B - 1;
@@ -237,7 +236,7 @@ impl<K, V> Root<K, V> {
     pub fn pop_level(&mut self) {
         debug_assert!(self.height > 0);
 
-        let top = self.node.ptr.as_ptr() as *mut u8;
+        let top = self.node.ptr;
 
         self.node = unsafe {
             BoxedNode::from_ptr(self.as_mut()
@@ -250,7 +249,7 @@ impl<K, V> Root<K, V> {
         self.as_mut().as_leaf_mut().parent = ptr::null();
 
         unsafe {
-            Heap.dealloc(top, Layout::new::<InternalNode<K, V>>());
+            Global.dealloc(NonNull::from(top).as_opaque(), Layout::new::<InternalNode<K, V>>());
         }
     }
 }
@@ -434,9 +433,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
             marker::Edge
         >
     > {
-        let ptr = self.as_leaf() as *const LeafNode<K, V> as *const u8 as *mut u8;
+        let node = self.node;
         let ret = self.ascend().ok();
-        Heap.dealloc(ptr, Layout::new::<LeafNode<K, V>>());
+        Global.dealloc(node.as_opaque(), Layout::new::<LeafNode<K, V>>());
         ret
     }
 }
@@ -455,9 +454,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
             marker::Edge
         >
     > {
-        let ptr = self.as_internal() as *const InternalNode<K, V> as *const u8 as *mut u8;
+        let node = self.node;
         let ret = self.ascend().ok();
-        Heap.dealloc(ptr, Layout::new::<InternalNode<K, V>>());
+        Global.dealloc(node.as_opaque(), Layout::new::<InternalNode<K, V>>());
         ret
     }
 }
@@ -1239,13 +1238,13 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
                     ).correct_parent_link();
                 }
 
-                Heap.dealloc(
-                    right_node.node.as_ptr() as *mut u8,
+                Global.dealloc(
+                    right_node.node.as_opaque(),
                     Layout::new::<InternalNode<K, V>>(),
                 );
             } else {
-                Heap.dealloc(
-                    right_node.node.as_ptr() as *mut u8,
+                Global.dealloc(
+                    right_node.node.as_opaque(),
                     Layout::new::<LeafNode<K, V>>(),
                 );
             }
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 9296a113071..faac38ca7ce 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -8,282 +8,103 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "allocator_api",
-            reason = "the precise API and guarantees it provides may be tweaked \
-                      slightly, especially to possibly take into account the \
-                      types being stored to make room for a future \
-                      tracing garbage collector",
-            issue = "32838")]
+#![allow(deprecated)]
 
-use core::intrinsics::{min_align_of_val, size_of_val};
-use core::mem::{self, ManuallyDrop};
-use core::usize;
+pub use alloc::{Layout, AllocErr, CannotReallocInPlace, Opaque};
+use core::alloc::Alloc as CoreAlloc;
+use core::ptr::NonNull;
 
-pub use core::heap::*;
 #[doc(hidden)]
 pub mod __core {
     pub use core::*;
 }
 
-extern "Rust" {
-    #[allocator]
-    #[rustc_allocator_nounwind]
-    fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8;
-    #[cold]
-    #[rustc_allocator_nounwind]
-    fn __rust_oom(err: *const u8) -> !;
-    #[rustc_allocator_nounwind]
-    fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
-    #[rustc_allocator_nounwind]
-    fn __rust_usable_size(layout: *const u8,
-                          min: *mut usize,
-                          max: *mut usize);
-    #[rustc_allocator_nounwind]
-    fn __rust_realloc(ptr: *mut u8,
-                      old_size: usize,
-                      old_align: usize,
-                      new_size: usize,
-                      new_align: usize,
-                      err: *mut u8) -> *mut u8;
-    #[rustc_allocator_nounwind]
-    fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8;
-    #[rustc_allocator_nounwind]
-    fn __rust_alloc_excess(size: usize,
-                           align: usize,
-                           excess: *mut usize,
-                           err: *mut u8) -> *mut u8;
-    #[rustc_allocator_nounwind]
-    fn __rust_realloc_excess(ptr: *mut u8,
-                             old_size: usize,
-                             old_align: usize,
-                             new_size: usize,
-                             new_align: usize,
-                             excess: *mut usize,
-                             err: *mut u8) -> *mut u8;
-    #[rustc_allocator_nounwind]
-    fn __rust_grow_in_place(ptr: *mut u8,
-                            old_size: usize,
-                            old_align: usize,
-                            new_size: usize,
-                            new_align: usize) -> u8;
-    #[rustc_allocator_nounwind]
-    fn __rust_shrink_in_place(ptr: *mut u8,
-                              old_size: usize,
-                              old_align: usize,
-                              new_size: usize,
-                              new_align: usize) -> u8;
-}
+#[derive(Debug)]
+pub struct Excess(pub *mut u8, pub usize);
 
-#[derive(Copy, Clone, Default, Debug)]
-pub struct Heap;
+/// Compatibility with older versions of #[global_allocator] during bootstrap
+pub unsafe trait Alloc {
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>;
+    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout);
+    fn oom(&mut self, err: AllocErr) -> !;
+    fn usable_size(&self, layout: &Layout) -> (usize, usize);
+    unsafe fn realloc(&mut self,
+                      ptr: *mut u8,
+                      layout: Layout,
+                      new_layout: Layout) -> Result<*mut u8, AllocErr>;
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>;
+    unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr>;
+    unsafe fn realloc_excess(&mut self,
+                             ptr: *mut u8,
+                             layout: Layout,
+                             new_layout: Layout) -> Result<Excess, AllocErr>;
+    unsafe fn grow_in_place(&mut self,
+                            ptr: *mut u8,
+                            layout: Layout,
+                            new_layout: Layout) -> Result<(), CannotReallocInPlace>;
+    unsafe fn shrink_in_place(&mut self,
+                              ptr: *mut u8,
+                              layout: Layout,
+                              new_layout: Layout) -> Result<(), CannotReallocInPlace>;
+}
 
-unsafe impl Alloc for Heap {
-    #[inline]
+unsafe impl<T> Alloc for T where T: CoreAlloc {
     unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
-        let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
-        let ptr = __rust_alloc(layout.size(),
-                               layout.align(),
-                               &mut *err as *mut AllocErr as *mut u8);
-        if ptr.is_null() {
-            Err(ManuallyDrop::into_inner(err))
-        } else {
-            Ok(ptr)
-        }
+        CoreAlloc::alloc(self, layout).map(|ptr| ptr.cast().as_ptr())
     }
 
-    #[inline]
-    #[cold]
-    fn oom(&mut self, err: AllocErr) -> ! {
-        unsafe {
-            __rust_oom(&err as *const AllocErr as *const u8)
-        }
+    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
+        let ptr = NonNull::new_unchecked(ptr as *mut Opaque);
+        CoreAlloc::dealloc(self, ptr, layout)
     }
 
-    #[inline]
-    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
-        __rust_dealloc(ptr, layout.size(), layout.align())
+    fn oom(&mut self, _: AllocErr) -> ! {
+        CoreAlloc::oom(self)
     }
 
-    #[inline]
     fn usable_size(&self, layout: &Layout) -> (usize, usize) {
-        let mut min = 0;
-        let mut max = 0;
-        unsafe {
-            __rust_usable_size(layout as *const Layout as *const u8,
-                               &mut min,
-                               &mut max);
-        }
-        (min, max)
+        CoreAlloc::usable_size(self, layout)
     }
 
-    #[inline]
     unsafe fn realloc(&mut self,
                       ptr: *mut u8,
                       layout: Layout,
-                      new_layout: Layout)
-                      -> Result<*mut u8, AllocErr>
-    {
-        let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
-        let ptr = __rust_realloc(ptr,
-                                 layout.size(),
-                                 layout.align(),
-                                 new_layout.size(),
-                                 new_layout.align(),
-                                 &mut *err as *mut AllocErr as *mut u8);
-        if ptr.is_null() {
-            Err(ManuallyDrop::into_inner(err))
-        } else {
-            mem::forget(err);
-            Ok(ptr)
-        }
+                      new_layout: Layout) -> Result<*mut u8, AllocErr> {
+        let ptr = NonNull::new_unchecked(ptr as *mut Opaque);
+        CoreAlloc::realloc(self, ptr, layout, new_layout.size()).map(|ptr| ptr.cast().as_ptr())
     }
 
-    #[inline]
     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
-        let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
-        let ptr = __rust_alloc_zeroed(layout.size(),
-                                      layout.align(),
-                                      &mut *err as *mut AllocErr as *mut u8);
-        if ptr.is_null() {
-            Err(ManuallyDrop::into_inner(err))
-        } else {
-            Ok(ptr)
-        }
+        CoreAlloc::alloc_zeroed(self, layout).map(|ptr| ptr.cast().as_ptr())
     }
 
-    #[inline]
     unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
-        let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
-        let mut size = 0;
-        let ptr = __rust_alloc_excess(layout.size(),
-                                      layout.align(),
-                                      &mut size,
-                                      &mut *err as *mut AllocErr as *mut u8);
-        if ptr.is_null() {
-            Err(ManuallyDrop::into_inner(err))
-        } else {
-            Ok(Excess(ptr, size))
-        }
+        CoreAlloc::alloc_excess(self, layout)
+            .map(|e| Excess(e.0 .cast().as_ptr(), e.1))
     }
 
-    #[inline]
     unsafe fn realloc_excess(&mut self,
                              ptr: *mut u8,
                              layout: Layout,
                              new_layout: Layout) -> Result<Excess, AllocErr> {
-        let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
-        let mut size = 0;
-        let ptr = __rust_realloc_excess(ptr,
-                                        layout.size(),
-                                        layout.align(),
-                                        new_layout.size(),
-                                        new_layout.align(),
-                                        &mut size,
-                                        &mut *err as *mut AllocErr as *mut u8);
-        if ptr.is_null() {
-            Err(ManuallyDrop::into_inner(err))
-        } else {
-            Ok(Excess(ptr, size))
-        }
+        let ptr = NonNull::new_unchecked(ptr as *mut Opaque);
+        CoreAlloc::realloc_excess(self, ptr, layout, new_layout.size())
+            .map(|e| Excess(e.0 .cast().as_ptr(), e.1))
     }
 
-    #[inline]
     unsafe fn grow_in_place(&mut self,
                             ptr: *mut u8,
                             layout: Layout,
-                            new_layout: Layout)
-                            -> Result<(), CannotReallocInPlace>
-    {
-        debug_assert!(new_layout.size() >= layout.size());
-        debug_assert!(new_layout.align() == layout.align());
-        let ret = __rust_grow_in_place(ptr,
-                                       layout.size(),
-                                       layout.align(),
-                                       new_layout.size(),
-                                       new_layout.align());
-        if ret != 0 {
-            Ok(())
-        } else {
-            Err(CannotReallocInPlace)
-        }
+                            new_layout: Layout) -> Result<(), CannotReallocInPlace> {
+        let ptr = NonNull::new_unchecked(ptr as *mut Opaque);
+        CoreAlloc::grow_in_place(self, ptr, layout, new_layout.size())
     }
 
-    #[inline]
     unsafe fn shrink_in_place(&mut self,
                               ptr: *mut u8,
                               layout: Layout,
                               new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        debug_assert!(new_layout.size() <= layout.size());
-        debug_assert!(new_layout.align() == layout.align());
-        let ret = __rust_shrink_in_place(ptr,
-                                         layout.size(),
-                                         layout.align(),
-                                         new_layout.size(),
-                                         new_layout.align());
-        if ret != 0 {
-            Ok(())
-        } else {
-            Err(CannotReallocInPlace)
-        }
-    }
-}
-
-/// The allocator for unique pointers.
-// This function must not unwind. If it does, MIR trans will fail.
-#[cfg(not(test))]
-#[lang = "exchange_malloc"]
-#[inline]
-unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
-    if size == 0 {
-        align as *mut u8
-    } else {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        Heap.alloc(layout).unwrap_or_else(|err| {
-            Heap.oom(err)
-        })
-    }
-}
-
-#[cfg_attr(not(test), lang = "box_free")]
-#[inline]
-pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
-    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.
-    if size != 0 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        Heap.dealloc(ptr as *mut u8, layout);
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    extern crate test;
-    use self::test::Bencher;
-    use boxed::Box;
-    use heap::{Heap, Alloc, Layout};
-
-    #[test]
-    fn allocate_zeroed() {
-        unsafe {
-            let layout = Layout::from_size_align(1024, 1).unwrap();
-            let ptr = Heap.alloc_zeroed(layout.clone())
-                .unwrap_or_else(|e| Heap.oom(e));
-
-            let end = ptr.offset(layout.size() as isize);
-            let mut i = ptr;
-            while i < end {
-                assert_eq!(*i, 0);
-                i = i.offset(1);
-            }
-            Heap.dealloc(ptr, layout);
-        }
-    }
-
-    #[bench]
-    fn alloc_owned_small(b: &mut Bencher) {
-        b.iter(|| {
-            let _: Box<_> = box 10;
-        })
+        let ptr = NonNull::new_unchecked(ptr as *mut Opaque);
+        CoreAlloc::shrink_in_place(self, ptr, layout, new_layout.size())
     }
 }
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index da26e7c852c..3a106a2ff5c 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -57,7 +57,7 @@
 //!
 //! ## Heap interfaces
 //!
-//! The [`heap`](heap/index.html) module defines the low-level interface to the
+//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
 //! default global allocator. It is not compatible with the libc allocator API.
 
 #![allow(unused_attributes)]
@@ -72,7 +72,6 @@
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
 #![no_std]
 #![needs_allocator]
-#![deny(warnings)]
 #![deny(missing_debug_implementations)]
 
 #![cfg_attr(test, allow(deprecated))] // rand
@@ -98,13 +97,15 @@
 #![feature(from_ref)]
 #![feature(fundamental)]
 #![feature(lang_items)]
+#![feature(libc)]
 #![feature(needs_allocator)]
+#![feature(nonnull_cast)]
 #![feature(nonzero)]
-#![feature(offset_to)]
 #![feature(optin_builtin_traits)]
 #![feature(pattern)]
 #![feature(pin)]
 #![feature(ptr_internals)]
+#![feature(ptr_offset_from)]
 #![feature(rustc_attrs)]
 #![feature(slice_get_slice)]
 #![feature(slice_rsplit)]
@@ -114,7 +115,7 @@
 #![feature(trusted_len)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(unicode)]
+#![feature(unicode_internals)]
 #![feature(unsize)]
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
@@ -136,18 +137,32 @@ extern crate test;
 #[cfg(test)]
 extern crate rand;
 
-extern crate std_unicode;
-
 // Module with internal macros used by other modules (needs to be included before other modules).
 #[macro_use]
 mod macros;
 
 #[rustc_deprecated(since = "1.27.0", reason = "use the heap module in core, alloc, or std instead")]
 #[unstable(feature = "allocator_api", issue = "32838")]
-pub use core::heap as allocator;
+/// Use the `alloc` module instead.
+pub mod allocator {
+    pub use alloc::*;
+}
 
 // Heaps provided for low-level allocation strategies
 
+pub mod alloc;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
+/// Use the `alloc` module instead.
+#[cfg(not(stage0))]
+pub mod heap {
+    pub use alloc::*;
+}
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
+#[cfg(stage0)]
 pub mod heap;
 
 // Primitive types using the heaps above
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 3edce8aebdf..214cc7d7d0c 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -8,13 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use alloc::{Alloc, Layout, Global};
 use core::cmp;
-use core::heap::{Alloc, Layout};
 use core::mem;
 use core::ops::Drop;
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull, Unique};
 use core::slice;
-use heap::Heap;
 use super::boxed::Box;
 use super::allocator::CollectionAllocErr;
 use super::allocator::CollectionAllocErr::*;
@@ -47,7 +46,7 @@ use super::allocator::CollectionAllocErr::*;
 /// field. This allows zero-sized types to not be special-cased by consumers of
 /// this type.
 #[allow(missing_debug_implementations)]
-pub struct RawVec<T, A: Alloc = Heap> {
+pub struct RawVec<T, A: Alloc = Global> {
     ptr: Unique<T>,
     cap: usize,
     a: A,
@@ -91,7 +90,7 @@ impl<T, A: Alloc> RawVec<T, A> {
 
             // handles ZSTs and `cap = 0` alike
             let ptr = if alloc_size == 0 {
-                mem::align_of::<T>() as *mut u8
+                NonNull::<T>::dangling().as_opaque()
             } else {
                 let align = mem::align_of::<T>();
                 let result = if zeroed {
@@ -101,12 +100,12 @@ impl<T, A: Alloc> RawVec<T, A> {
                 };
                 match result {
                     Ok(ptr) => ptr,
-                    Err(err) => a.oom(err),
+                    Err(_) => a.oom(),
                 }
             };
 
             RawVec {
-                ptr: Unique::new_unchecked(ptr as *mut _),
+                ptr: ptr.cast().into(),
                 cap,
                 a,
             }
@@ -114,14 +113,14 @@ impl<T, A: Alloc> RawVec<T, A> {
     }
 }
 
-impl<T> RawVec<T, Heap> {
+impl<T> RawVec<T, Global> {
     /// Creates the biggest possible RawVec (on the system heap)
     /// without allocating. If T has positive size, then this makes a
     /// 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 {
-        Self::new_in(Heap)
+        Self::new_in(Global)
     }
 
     /// Creates a RawVec (on the system heap) with exactly the
@@ -141,13 +140,13 @@ impl<T> RawVec<T, Heap> {
     /// Aborts on OOM
     #[inline]
     pub fn with_capacity(cap: usize) -> Self {
-        RawVec::allocate_in(cap, false, Heap)
+        RawVec::allocate_in(cap, false, Global)
     }
 
     /// Like `with_capacity` but guarantees the buffer is zeroed.
     #[inline]
     pub fn with_capacity_zeroed(cap: usize) -> Self {
-        RawVec::allocate_in(cap, true, Heap)
+        RawVec::allocate_in(cap, true, Global)
     }
 }
 
@@ -168,7 +167,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     }
 }
 
-impl<T> RawVec<T, Heap> {
+impl<T> RawVec<T, Global> {
     /// Reconstitutes a RawVec from a pointer, capacity.
     ///
     /// # Undefined Behavior
@@ -180,7 +179,7 @@ impl<T> RawVec<T, Heap> {
         RawVec {
             ptr: Unique::new_unchecked(ptr),
             cap,
-            a: Heap,
+            a: Global,
         }
     }
 
@@ -310,14 +309,13 @@ impl<T, A: Alloc> RawVec<T, A> {
                     // `from_size_align_unchecked`.
                     let new_cap = 2 * self.cap;
                     let new_size = new_cap * elem_size;
-                    let new_layout = Layout::from_size_align_unchecked(new_size, cur.align());
                     alloc_guard(new_size).expect("capacity overflow");
-                    let ptr_res = self.a.realloc(self.ptr.as_ptr() as *mut u8,
+                    let ptr_res = self.a.realloc(NonNull::from(self.ptr).as_opaque(),
                                                  cur,
-                                                 new_layout);
+                                                 new_size);
                     match ptr_res {
-                        Ok(ptr) => (new_cap, Unique::new_unchecked(ptr as *mut T)),
-                        Err(e) => self.a.oom(e),
+                        Ok(ptr) => (new_cap, ptr.cast().into()),
+                        Err(_) => self.a.oom(),
                     }
                 }
                 None => {
@@ -326,7 +324,7 @@ impl<T, A: Alloc> RawVec<T, A> {
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
                         Ok(ptr) => (new_cap, ptr.into()),
-                        Err(e) => self.a.oom(e),
+                        Err(_) => self.a.oom(),
                     }
                 }
             };
@@ -371,9 +369,7 @@ impl<T, A: Alloc> RawVec<T, A> {
             let new_cap = 2 * self.cap;
             let new_size = new_cap * elem_size;
             alloc_guard(new_size).expect("capacity overflow");
-            let ptr = self.ptr() as *mut _;
-            let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
-            match self.a.grow_in_place(ptr, old_layout, new_layout) {
+            match self.a.grow_in_place(NonNull::from(self.ptr).as_opaque(), old_layout, new_size) {
                 Ok(_) => {
                     // We can't directly divide `size`.
                     self.cap = new_cap;
@@ -423,19 +419,19 @@ impl<T, A: Alloc> RawVec<T, A> {
 
             // Nothing we can really do about these checks :(
             let new_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?;
-            let new_layout = Layout::array::<T>(new_cap).ok_or(CapacityOverflow)?;
+            let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
 
             alloc_guard(new_layout.size())?;
 
             let res = match self.current_layout() {
                 Some(layout) => {
-                    let old_ptr = self.ptr.as_ptr() as *mut u8;
-                    self.a.realloc(old_ptr, layout, new_layout)
+                    debug_assert!(new_layout.align() == layout.align());
+                    self.a.realloc(NonNull::from(self.ptr).as_opaque(), layout, new_layout.size())
                 }
                 None => self.a.alloc(new_layout),
             };
 
-            self.ptr = Unique::new_unchecked(res? as *mut T);
+            self.ptr = res?.cast().into();
             self.cap = new_cap;
 
             Ok(())
@@ -445,7 +441,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve_exact(used_cap, needed_extra_cap) {
             Err(CapacityOverflow) => panic!("capacity overflow"),
-            Err(AllocErr(e)) => self.a.oom(e),
+            Err(AllocErr) => self.a.oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -531,20 +527,20 @@ impl<T, A: Alloc> RawVec<T, A> {
             }
 
             let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)?;
-            let new_layout = Layout::array::<T>(new_cap).ok_or(CapacityOverflow)?;
+            let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
 
              // FIXME: may crash and burn on over-reserve
             alloc_guard(new_layout.size())?;
 
             let res = match self.current_layout() {
                 Some(layout) => {
-                    let old_ptr = self.ptr.as_ptr() as *mut u8;
-                    self.a.realloc(old_ptr, layout, new_layout)
+                    debug_assert!(new_layout.align() == layout.align());
+                    self.a.realloc(NonNull::from(self.ptr).as_opaque(), layout, new_layout.size())
                 }
                 None => self.a.alloc(new_layout),
             };
 
-            self.ptr = Unique::new_unchecked(res? as *mut T);
+            self.ptr = res?.cast().into();
             self.cap = new_cap;
 
             Ok(())
@@ -555,7 +551,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve(used_cap, needed_extra_cap) {
             Err(CapacityOverflow) => panic!("capacity overflow"),
-            Err(AllocErr(e)) => self.a.oom(e),
+            Err(AllocErr) => self.a.oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -601,11 +597,12 @@ impl<T, A: Alloc> RawVec<T, A> {
             // (regardless of whether `self.cap - used_cap` wrapped).
             // Therefore we can safely call grow_in_place.
 
-            let ptr = self.ptr() as *mut _;
             let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
             // FIXME: may crash and burn on over-reserve
             alloc_guard(new_layout.size()).expect("capacity overflow");
-            match self.a.grow_in_place(ptr, old_layout, new_layout) {
+            match self.a.grow_in_place(
+                NonNull::from(self.ptr).as_opaque(), old_layout, new_layout.size(),
+            ) {
                 Ok(_) => {
                     self.cap = new_cap;
                     true
@@ -665,12 +662,11 @@ impl<T, A: Alloc> RawVec<T, A> {
                 let new_size = elem_size * amount;
                 let align = mem::align_of::<T>();
                 let old_layout = Layout::from_size_align_unchecked(old_size, align);
-                let new_layout = Layout::from_size_align_unchecked(new_size, align);
-                match self.a.realloc(self.ptr.as_ptr() as *mut u8,
+                match self.a.realloc(NonNull::from(self.ptr).as_opaque(),
                                      old_layout,
-                                     new_layout) {
-                    Ok(p) => self.ptr = Unique::new_unchecked(p as *mut T),
-                    Err(err) => self.a.oom(err),
+                                     new_size) {
+                    Ok(p) => self.ptr = p.cast().into(),
+                    Err(_) => self.a.oom(),
                 }
             }
             self.cap = amount;
@@ -678,7 +674,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     }
 }
 
-impl<T> RawVec<T, Heap> {
+impl<T> RawVec<T, Global> {
     /// Converts the entire buffer into `Box<[T]>`.
     ///
     /// While it is not *strictly* Undefined Behavior to call
@@ -702,8 +698,7 @@ impl<T, A: Alloc> RawVec<T, A> {
         let elem_size = mem::size_of::<T>();
         if elem_size != 0 {
             if let Some(layout) = self.current_layout() {
-                let ptr = self.ptr() as *mut u8;
-                self.a.dealloc(ptr, layout);
+                self.a.dealloc(NonNull::from(self.ptr).as_opaque(), layout);
             }
         }
     }
@@ -739,6 +734,7 @@ fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use alloc::Opaque;
 
     #[test]
     fn allocator_param() {
@@ -758,18 +754,18 @@ mod tests {
         // before allocation attempts start failing.
         struct BoundedAlloc { fuel: usize }
         unsafe impl Alloc for BoundedAlloc {
-            unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
+            unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
                 let size = layout.size();
                 if size > self.fuel {
-                    return Err(AllocErr::Unsupported { details: "fuel exhausted" });
+                    return Err(AllocErr);
                 }
-                match Heap.alloc(layout) {
+                match Global.alloc(layout) {
                     ok @ Ok(_) => { self.fuel -= size; ok }
                     err @ Err(_) => err,
                 }
             }
-            unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
-                Heap.dealloc(ptr, layout)
+            unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout) {
+                Global.dealloc(ptr, layout)
             }
         }
 
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 8bdc57f96a6..de0422d82bb 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -250,7 +250,6 @@ use core::cell::Cell;
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{Hash, Hasher};
-use core::heap::{Alloc, Layout};
 use core::intrinsics::abort;
 use core::marker;
 use core::marker::{Unsize, PhantomData};
@@ -260,7 +259,7 @@ use core::ops::CoerceUnsized;
 use core::ptr::{self, NonNull};
 use core::convert::From;
 
-use heap::{Heap, box_free};
+use alloc::{Global, Alloc, Layout, Opaque, box_free};
 use string::String;
 use vec::Vec;
 
@@ -668,11 +667,11 @@ impl<T: ?Sized> Rc<T> {
 
         let layout = Layout::for_value(&*fake_ptr);
 
-        let mem = Heap.alloc(layout)
-            .unwrap_or_else(|e| Heap.oom(e));
+        let mem = Global.alloc(layout)
+            .unwrap_or_else(|_| Global.oom());
 
         // Initialize the real RcBox
-        let inner = set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>;
+        let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
 
         ptr::write(&mut (*inner).strong, Cell::new(1));
         ptr::write(&mut (*inner).weak, Cell::new(1));
@@ -738,7 +737,7 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
         // In the event of a panic, elements that have been written
         // into the new RcBox will be dropped, then the memory freed.
         struct Guard<T> {
-            mem: *mut u8,
+            mem: NonNull<Opaque>,
             elems: *mut T,
             layout: Layout,
             n_elems: usize,
@@ -752,7 +751,7 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
                     let slice = from_raw_parts_mut(self.elems, self.n_elems);
                     ptr::drop_in_place(slice);
 
-                    Heap.dealloc(self.mem, self.layout.clone());
+                    Global.dealloc(self.mem, self.layout.clone());
                 }
             }
         }
@@ -761,14 +760,14 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
             let v_ptr = v as *const [T];
             let ptr = Self::allocate_for_ptr(v_ptr);
 
-            let mem = ptr as *mut _ as *mut u8;
+            let mem = ptr as *mut _ as *mut Opaque;
             let layout = Layout::for_value(&*ptr);
 
             // Pointer to first element
             let elems = &mut (*ptr).value as *mut [T] as *mut T;
 
             let mut guard = Guard{
-                mem: mem,
+                mem: NonNull::new_unchecked(mem),
                 elems: elems,
                 layout: layout,
                 n_elems: 0,
@@ -835,8 +834,6 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
     /// ```
     fn drop(&mut self) {
         unsafe {
-            let ptr = self.ptr.as_ptr();
-
             self.dec_strong();
             if self.strong() == 0 {
                 // destroy the contained object
@@ -847,7 +844,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
                 self.dec_weak();
 
                 if self.weak() == 0 {
-                    Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr));
+                    Global.dealloc(self.ptr.as_opaque(), Layout::for_value(self.ptr.as_ref()));
                 }
             }
         }
@@ -1267,13 +1264,11 @@ impl<T: ?Sized> Drop for Weak<T> {
     /// ```
     fn drop(&mut self) {
         unsafe {
-            let ptr = self.ptr.as_ptr();
-
             self.dec_weak();
             // the weak count starts at 1, and will only go to zero if all
             // the strong pointers have disappeared.
             if self.weak() == 0 {
-                Heap.dealloc(ptr as *mut u8, Layout::for_value(&*ptr));
+                Global.dealloc(self.ptr.as_opaque(), Layout::for_value(self.ptr.as_ref()));
             }
         }
     }
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 68f2313843c..56c53fca62c 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -1400,6 +1400,7 @@ impl<T> [T] {
         let sz_usize = mem::size_of::<(K, usize)>();
 
         let len = self.len();
+        if len < 2 { return }
         if sz_u8  < sz_u16   && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) }
         if sz_u16 < sz_u32   && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) }
         if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) }
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index d5ef41df0d8..65df93bd3bb 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -45,12 +45,10 @@ use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 use core::mem;
 use core::ptr;
 use core::iter::FusedIterator;
-use std_unicode::str::{UnicodeStr, Utf16Encoder};
 
 use vec_deque::VecDeque;
 use borrow::{Borrow, ToOwned};
 use string::String;
-use std_unicode;
 use vec::Vec;
 use slice::{SliceConcatExt, SliceIndex};
 use boxed::Box;
@@ -75,7 +73,7 @@ pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use std_unicode::str::SplitWhitespace;
+pub use core::str::SplitWhitespace;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::pattern;
 
@@ -147,7 +145,8 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
 #[derive(Clone)]
 #[stable(feature = "encode_utf16", since = "1.8.0")]
 pub struct EncodeUtf16<'a> {
-    encoder: Utf16Encoder<Chars<'a>>,
+    chars: Chars<'a>,
+    extra: u16,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
@@ -163,12 +162,29 @@ impl<'a> Iterator for EncodeUtf16<'a> {
 
     #[inline]
     fn next(&mut self) -> Option<u16> {
-        self.encoder.next()
+        if self.extra != 0 {
+            let tmp = self.extra;
+            self.extra = 0;
+            return Some(tmp);
+        }
+
+        let mut buf = [0; 2];
+        self.chars.next().map(|ch| {
+            let n = ch.encode_utf16(&mut buf).len();
+            if n == 2 {
+                self.extra = buf[1];
+            }
+            buf[0]
+        })
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.encoder.size_hint()
+        let (low, high) = self.chars.size_hint();
+        // every char gets either one u16 or two u16,
+        // so this iterator is between 1 or 2 times as
+        // long as the underlying iterator.
+        (low, high.and_then(|n| n.checked_mul(2)))
     }
 }
 
@@ -801,7 +817,7 @@ impl str {
     #[stable(feature = "split_whitespace", since = "1.1.0")]
     #[inline]
     pub fn split_whitespace(&self) -> SplitWhitespace {
-        UnicodeStr::split_whitespace(self)
+        StrExt::split_whitespace(self)
     }
 
     /// An iterator over the lines of a string, as string slices.
@@ -871,7 +887,7 @@ impl str {
     /// ```
     #[stable(feature = "encode_utf16", since = "1.8.0")]
     pub fn encode_utf16(&self) -> EncodeUtf16 {
-        EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) }
+        EncodeUtf16 { chars: self[..].chars(), extra: 0 }
     }
 
     /// Returns `true` if the given pattern matches a sub-slice of
@@ -1571,7 +1587,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim(&self) -> &str {
-        UnicodeStr::trim(self)
+        StrExt::trim(self)
     }
 
     /// Returns a string slice with leading whitespace removed.
@@ -1607,7 +1623,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim_left(&self) -> &str {
-        UnicodeStr::trim_left(self)
+        StrExt::trim_left(self)
     }
 
     /// Returns a string slice with trailing whitespace removed.
@@ -1643,7 +1659,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn trim_right(&self) -> &str {
-        UnicodeStr::trim_right(self)
+        StrExt::trim_right(self)
     }
 
     /// Returns a string slice with all prefixes and suffixes that match a
@@ -1960,7 +1976,7 @@ impl str {
         }
 
         fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
-            use std_unicode::derived_property::{Cased, Case_Ignorable};
+            use core::unicode::derived_property::{Cased, Case_Ignorable};
             match iter.skip_while(|&c| Case_Ignorable(c)).next() {
                 Some(c) => Cased(c),
                 None => false,
@@ -2142,7 +2158,7 @@ impl str {
     #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
     #[inline]
     pub fn is_whitespace(&self) -> bool {
-        UnicodeStr::is_whitespace(self)
+        StrExt::is_whitespace(self)
     }
 
     /// Returns true if this `str` is entirely alphanumeric, and false otherwise.
@@ -2161,7 +2177,7 @@ impl str {
     #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
     #[inline]
     pub fn is_alphanumeric(&self) -> bool {
-        UnicodeStr::is_alphanumeric(self)
+        StrExt::is_alphanumeric(self)
     }
 
     /// Checks if all characters in this string are within the ASCII range.
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index b95aae02894..29d759b1f00 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -56,6 +56,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
 use core::fmt;
 use core::hash;
 use core::iter::{FromIterator, FusedIterator};
@@ -63,8 +64,7 @@ use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds};
 use core::ptr;
 use core::str::pattern::Pattern;
-use std_unicode::lossy;
-use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
+use core::str::lossy;
 
 use borrow::{Cow, ToOwned};
 use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs
index d3ce12056bb..6fa88ce969a 100644
--- a/src/liballoc/tests/heap.rs
+++ b/src/liballoc/tests/heap.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use alloc_system::System;
-use std::heap::{Heap, Alloc, Layout};
+use std::alloc::{Global, Alloc, Layout};
 
 /// https://github.com/rust-lang/rust/issues/45955
 ///
@@ -22,7 +22,7 @@ fn alloc_system_overaligned_request() {
 
 #[test]
 fn std_heap_overaligned_request() {
-    check_overalign_requests(Heap)
+    check_overalign_requests(Global)
 }
 
 fn check_overalign_requests<T: Alloc>(mut allocator: T) {
@@ -34,7 +34,8 @@ fn check_overalign_requests<T: Alloc>(mut allocator: T) {
             allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
         }).collect();
         for &ptr in &pointers {
-            assert_eq!((ptr as usize) % align, 0, "Got a pointer less aligned than requested")
+            assert_eq!((ptr.as_ptr() as usize) % align, 0,
+                       "Got a pointer less aligned than requested")
         }
 
         // Clean up
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index a173ef10a81..32272169307 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(allocator_api)]
 #![feature(alloc_system)]
 #![feature(attr_literals)]
@@ -26,12 +24,11 @@
 #![feature(string_retain)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(unicode)]
 #![feature(exact_chunks)]
 #![feature(inclusive_range_fields)]
 
 extern crate alloc_system;
-extern crate std_unicode;
+extern crate core;
 extern crate rand;
 
 use std::hash::{Hash, Hasher};
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index a14a5d32738..a3f4c385fe2 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -1204,8 +1204,7 @@ fn test_rev_split_char_iterator_no_trailing() {
 
 #[test]
 fn test_utf16_code_units() {
-    use std_unicode::str::Utf16Encoder;
-    assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
+    assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
                [0xE9, 0xD83D, 0xDCA9])
 }
 
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index cb4a17a22d8..befb36baeef 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -132,7 +132,7 @@ fn test_from_utf16() {
         let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
         let u_as_string = String::from_utf16(&u).unwrap();
 
-        assert!(::std_unicode::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
+        assert!(::core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
         assert_eq!(s_as_utf16, u);
 
         assert_eq!(u_as_string, s);
@@ -575,11 +575,11 @@ fn test_try_reserve() {
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
             // Check isize::MAX + 1 is an OOM
-            if let Err(AllocErr(_)) = empty_string.try_reserve(MAX_CAP + 1) {
+            if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
             // Check usize::MAX is an OOM
-            if let Err(AllocErr(_)) = empty_string.try_reserve(MAX_USIZE) {
+            if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -599,7 +599,7 @@ fn test_try_reserve() {
             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_bytes.try_reserve(MAX_CAP - 9) {
+            if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should always overflow in the add-to-len
@@ -637,10 +637,10 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
-            if let Err(AllocErr(_)) = empty_string.try_reserve_exact(MAX_CAP + 1) {
+            if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
-            if let Err(AllocErr(_)) = empty_string.try_reserve_exact(MAX_USIZE) {
+            if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -659,7 +659,7 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
+            if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 2895c53009d..e329b45a617 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -1016,11 +1016,11 @@ fn test_try_reserve() {
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
             // Check isize::MAX + 1 is an OOM
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve(MAX_CAP + 1) {
+            if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
             // Check usize::MAX is an OOM
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve(MAX_USIZE) {
+            if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -1040,7 +1040,7 @@ fn test_try_reserve() {
             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_bytes.try_reserve(MAX_CAP - 9) {
+            if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should always overflow in the add-to-len
@@ -1063,7 +1063,7 @@ fn test_try_reserve() {
             if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
+            if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should fail in the mul-by-size
@@ -1103,10 +1103,10 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an overflow!") }
         } else {
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
+            if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
 
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve_exact(MAX_USIZE) {
+            if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) {
             } else { panic!("usize::MAX should trigger an OOM!") }
         }
     }
@@ -1125,7 +1125,7 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
+            if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
@@ -1146,7 +1146,7 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
+            if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs
index 75d3f01f8b6..4d55584e2f4 100644
--- a/src/liballoc/tests/vec_deque.rs
+++ b/src/liballoc/tests/vec_deque.rs
@@ -1073,7 +1073,7 @@ fn test_try_reserve() {
             // VecDeque starts with capacity 7, always adds 1 to the capacity
             // and also rounds the number to next power of 2 so this is the
             // furthest we can go without triggering CapacityOverflow
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve(MAX_CAP) {
+            if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
     }
@@ -1093,7 +1093,7 @@ fn test_try_reserve() {
             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_bytes.try_reserve(MAX_CAP - 9) {
+            if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should always overflow in the add-to-len
@@ -1116,7 +1116,7 @@ fn test_try_reserve() {
             if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
+            if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         // Should fail in the mul-by-size
@@ -1160,7 +1160,7 @@ fn test_try_reserve_exact() {
             // VecDeque starts with capacity 7, always adds 1 to the capacity
             // and also rounds the number to next power of 2 so this is the
             // furthest we can go without triggering CapacityOverflow
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve_exact(MAX_CAP) {
+            if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
     }
@@ -1179,7 +1179,7 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
+            if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
@@ -1200,7 +1200,7 @@ fn test_try_reserve_exact() {
             if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an overflow!"); }
         } else {
-            if let Err(AllocErr(_)) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
+            if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
         if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) {
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 4b883b5bce7..0f74743ca49 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -2394,9 +2394,10 @@ impl<T> Iterator for IntoIter<T> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let exact = match self.ptr.offset_to(self.end) {
-            Some(x) => x as usize,
-            None => (self.end as usize).wrapping_sub(self.ptr as usize),
+        let exact = if mem::size_of::<T>() == 0 {
+            (self.end as usize).wrapping_sub(self.ptr as usize)
+        } else {
+            unsafe { self.end.offset_from(self.ptr) as usize }
         };
         (exact, Some(exact))
     }
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
index fd4a4553046..02435170374 100644
--- a/src/liballoc_jemalloc/Cargo.toml
+++ b/src/liballoc_jemalloc/Cargo.toml
@@ -12,7 +12,6 @@ test = false
 doc = false
 
 [dependencies]
-alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 7a8d01e4ef8..2b66c293f21 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -14,7 +14,6 @@
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
             issue = "27783")]
-#![deny(warnings)]
 #![feature(alloc_system)]
 #![feature(libc)]
 #![feature(linkage)]
@@ -31,9 +30,7 @@ extern crate libc;
 pub use contents::*;
 #[cfg(not(dummy_jemalloc))]
 mod contents {
-    use core::ptr;
-
-    use core::heap::{Alloc, AllocErr, Layout};
+    use core::alloc::GlobalAlloc;
     use alloc_system::System;
     use libc::{c_int, c_void, size_t};
 
@@ -55,16 +52,8 @@ mod contents {
         fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
         #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                        target_os = "dragonfly", target_os = "windows", target_env = "musl"),
-                   link_name = "je_xallocx")]
-        fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
-        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                    link_name = "je_sdallocx")]
         fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
-        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
-                   link_name = "je_nallocx")]
-        fn nallocx(size: size_t, flags: c_int) -> size_t;
     }
 
     const MALLOCX_ZERO: c_int = 0x40;
@@ -105,23 +94,16 @@ mod contents {
 
     #[no_mangle]
     #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_alloc(size: usize,
-                                     align: usize,
-                                     err: *mut u8) -> *mut u8 {
+    pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
         let flags = align_to_flags(align, size);
         let ptr = mallocx(size as size_t, flags) as *mut u8;
-        if ptr.is_null() {
-            let layout = Layout::from_size_align_unchecked(size, align);
-            ptr::write(err as *mut AllocErr,
-                       AllocErr::Exhausted { request: layout });
-        }
         ptr
     }
 
     #[no_mangle]
     #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
-        System.oom((*(err as *const AllocErr)).clone())
+    pub unsafe extern fn __rde_oom() -> ! {
+        System.oom()
     }
 
     #[no_mangle]
@@ -135,116 +117,24 @@ mod contents {
 
     #[no_mangle]
     #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_usable_size(layout: *const u8,
-                                           min: *mut usize,
-                                           max: *mut usize) {
-        let layout = &*(layout as *const Layout);
-        let flags = align_to_flags(layout.align(), layout.size());
-        let size = nallocx(layout.size(), flags) as usize;
-        *min = layout.size();
-        if size > 0 {
-            *max = size;
-        } else {
-            *max = layout.size();
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                        _old_size: usize,
-                                       old_align: usize,
-                                       new_size: usize,
-                                       new_align: usize,
-                                       err: *mut u8) -> *mut u8 {
-        if new_align != old_align {
-            ptr::write(err as *mut AllocErr,
-                       AllocErr::Unsupported { details: "can't change alignments" });
-            return 0 as *mut u8
-        }
-
-        let flags = align_to_flags(new_align, new_size);
+                                       align: usize,
+                                       new_size: usize) -> *mut u8 {
+        let flags = align_to_flags(align, new_size);
         let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
-        if ptr.is_null() {
-            let layout = Layout::from_size_align_unchecked(new_size, new_align);
-            ptr::write(err as *mut AllocErr,
-                       AllocErr::Exhausted { request: layout });
-        }
         ptr
     }
 
     #[no_mangle]
     #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_alloc_zeroed(size: usize,
-                                            align: usize,
-                                            err: *mut u8) -> *mut u8 {
+    pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
         let ptr = if align <= MIN_ALIGN && align <= size {
             calloc(size as size_t, 1) as *mut u8
         } else {
             let flags = align_to_flags(align, size) | MALLOCX_ZERO;
             mallocx(size as size_t, flags) as *mut u8
         };
-        if ptr.is_null() {
-            let layout = Layout::from_size_align_unchecked(size, align);
-            ptr::write(err as *mut AllocErr,
-                       AllocErr::Exhausted { request: layout });
-        }
         ptr
     }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_alloc_excess(size: usize,
-                                            align: usize,
-                                            excess: *mut usize,
-                                            err: *mut u8) -> *mut u8 {
-        let p = __rde_alloc(size, align, err);
-        if !p.is_null() {
-            let flags = align_to_flags(align, size);
-            *excess = nallocx(size, flags) as usize;
-        }
-        return p
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
-                                              old_size: usize,
-                                              old_align: usize,
-                                              new_size: usize,
-                                              new_align: usize,
-                                              excess: *mut usize,
-                                              err: *mut u8) -> *mut u8 {
-        let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
-        if !p.is_null() {
-            let flags = align_to_flags(new_align, new_size);
-            *excess = nallocx(new_size, flags) as usize;
-        }
-        p
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
-                                             old_size: usize,
-                                             old_align: usize,
-                                             new_size: usize,
-                                             new_align: usize) -> u8 {
-        __rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
-                                               _old_size: usize,
-                                               old_align: usize,
-                                               new_size: usize,
-                                               new_align: usize) -> u8 {
-        if old_align == new_align {
-            let flags = align_to_flags(new_align, new_size);
-            (xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
-        } else {
-            0
-        }
-    }
 }
diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml
index 936e20a32e1..c34e2f203a8 100644
--- a/src/liballoc_system/Cargo.toml
+++ b/src/liballoc_system/Cargo.toml
@@ -10,7 +10,6 @@ test = false
 doc = false
 
 [dependencies]
-alloc = { path = "../liballoc" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index d4404e564e0..fd8109e2a4a 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -10,7 +10,6 @@
 
 #![no_std]
 #![allow(unused_attributes)]
-#![deny(warnings)]
 #![unstable(feature = "alloc_system",
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
@@ -42,7 +41,8 @@ const MIN_ALIGN: usize = 8;
 #[allow(dead_code)]
 const MIN_ALIGN: usize = 16;
 
-use core::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace};
+use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout, Opaque};
+use core::ptr::NonNull;
 
 #[unstable(feature = "allocator_api", issue = "32838")]
 pub struct System;
@@ -50,66 +50,86 @@ pub struct System;
 #[unstable(feature = "allocator_api", issue = "32838")]
 unsafe impl Alloc for System {
     #[inline]
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
-        (&*self).alloc(layout)
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
     }
 
     #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout)
-        -> Result<*mut u8, AllocErr>
-    {
-        (&*self).alloc_zeroed(layout)
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
     }
 
     #[inline]
-    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
-        (&*self).dealloc(ptr, layout)
+    unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout) {
+        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
     }
 
     #[inline]
     unsafe fn realloc(&mut self,
-                      ptr: *mut u8,
-                      old_layout: Layout,
-                      new_layout: Layout) -> Result<*mut u8, AllocErr> {
-        (&*self).realloc(ptr, old_layout, new_layout)
+                      ptr: NonNull<Opaque>,
+                      layout: Layout,
+                      new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
 
-    fn oom(&mut self, err: AllocErr) -> ! {
-        (&*self).oom(err)
+    #[inline]
+    fn oom(&mut self) -> ! {
+        ::oom()
     }
+}
 
+#[cfg(stage0)]
+#[unstable(feature = "allocator_api", issue = "32838")]
+unsafe impl<'a> Alloc for &'a System {
     #[inline]
-    fn usable_size(&self, layout: &Layout) -> (usize, usize) {
-        (&self).usable_size(layout)
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc(*self, layout)).ok_or(AllocErr)
     }
 
     #[inline]
-    unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
-        (&*self).alloc_excess(layout)
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc_zeroed(*self, layout)).ok_or(AllocErr)
     }
 
     #[inline]
-    unsafe fn realloc_excess(&mut self,
-                             ptr: *mut u8,
-                             layout: Layout,
-                             new_layout: Layout) -> Result<Excess, AllocErr> {
-        (&*self).realloc_excess(ptr, layout, new_layout)
+    unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout) {
+        GlobalAlloc::dealloc(*self, ptr.as_ptr(), layout)
     }
 
     #[inline]
-    unsafe fn grow_in_place(&mut self,
-                            ptr: *mut u8,
-                            layout: Layout,
-                            new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        (&*self).grow_in_place(ptr, layout, new_layout)
+    unsafe fn realloc(&mut self,
+                      ptr: NonNull<Opaque>,
+                      layout: Layout,
+                      new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
+        NonNull::new(GlobalAlloc::realloc(*self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
 
     #[inline]
-    unsafe fn shrink_in_place(&mut self,
-                              ptr: *mut u8,
-                              layout: Layout,
-                              new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-        (&*self).shrink_in_place(ptr, layout, new_layout)
+    fn oom(&mut self) -> ! {
+        ::oom()
+    }
+}
+
+#[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
+mod realloc_fallback {
+    use core::alloc::{GlobalAlloc, Opaque, Layout};
+    use core::cmp;
+    use core::ptr;
+
+    impl super::System {
+        pub(crate) unsafe fn realloc_fallback(&self, ptr: *mut Opaque, old_layout: Layout,
+                                              new_size: usize) -> *mut Opaque {
+            // Docs for GlobalAlloc::realloc require this to be valid:
+            let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
+
+            let new_ptr = GlobalAlloc::alloc(self, new_layout);
+            if !new_ptr.is_null() {
+                let size = cmp::min(old_layout.size(), new_size);
+                ptr::copy_nonoverlapping(ptr as *mut u8, new_ptr as *mut u8, size);
+                GlobalAlloc::dealloc(self, ptr, old_layout);
+            }
+            new_ptr
+        }
     }
 }
 
@@ -117,132 +137,62 @@ unsafe impl Alloc for System {
 mod platform {
     extern crate libc;
 
-    use core::cmp;
     use core::ptr;
 
     use MIN_ALIGN;
     use System;
-    use core::heap::{Alloc, AllocErr, Layout};
+    use core::alloc::{GlobalAlloc, Layout, Opaque};
 
     #[unstable(feature = "allocator_api", issue = "32838")]
-    unsafe impl<'a> Alloc for &'a System {
+    unsafe impl GlobalAlloc for System {
         #[inline]
-        unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
-            let ptr = if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-                libc::malloc(layout.size()) as *mut u8
+        unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
+            if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+                libc::malloc(layout.size()) as *mut Opaque
             } else {
                 #[cfg(target_os = "macos")]
                 {
                     if layout.align() > (1 << 31) {
-                        return Err(AllocErr::Unsupported {
-                            details: "requested alignment too large"
-                        })
+                        // FIXME: use Opaque::null_mut
+                        // https://github.com/rust-lang/rust/issues/49659
+                        return 0 as *mut Opaque
                     }
                 }
                 aligned_malloc(&layout)
-            };
-            if !ptr.is_null() {
-                Ok(ptr)
-            } else {
-                Err(AllocErr::Exhausted { request: layout })
             }
         }
 
         #[inline]
-        unsafe fn alloc_zeroed(&mut self, layout: Layout)
-            -> Result<*mut u8, AllocErr>
-        {
+        unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
             if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-                let ptr = libc::calloc(layout.size(), 1) as *mut u8;
-                if !ptr.is_null() {
-                    Ok(ptr)
-                } else {
-                    Err(AllocErr::Exhausted { request: layout })
-                }
+                libc::calloc(layout.size(), 1) as *mut Opaque
             } else {
-                let ret = self.alloc(layout.clone());
-                if let Ok(ptr) = ret {
-                    ptr::write_bytes(ptr, 0, layout.size());
+                let ptr = self.alloc(layout.clone());
+                if !ptr.is_null() {
+                    ptr::write_bytes(ptr as *mut u8, 0, layout.size());
                 }
-                ret
+                ptr
             }
         }
 
         #[inline]
-        unsafe fn dealloc(&mut self, ptr: *mut u8, _layout: Layout) {
+        unsafe fn dealloc(&self, ptr: *mut Opaque, _layout: Layout) {
             libc::free(ptr as *mut libc::c_void)
         }
 
         #[inline]
-        unsafe fn realloc(&mut self,
-                          ptr: *mut u8,
-                          old_layout: Layout,
-                          new_layout: Layout) -> Result<*mut u8, AllocErr> {
-            if old_layout.align() != new_layout.align() {
-                return Err(AllocErr::Unsupported {
-                    details: "cannot change alignment on `realloc`",
-                })
-            }
-
-            if new_layout.align() <= MIN_ALIGN  && new_layout.align() <= new_layout.size(){
-                let ptr = libc::realloc(ptr as *mut libc::c_void, new_layout.size());
-                if !ptr.is_null() {
-                    Ok(ptr as *mut u8)
-                } else {
-                    Err(AllocErr::Exhausted { request: new_layout })
-                }
+        unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *mut Opaque {
+            if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
+                libc::realloc(ptr as *mut libc::c_void, new_size) as *mut Opaque
             } else {
-                let res = self.alloc(new_layout.clone());
-                if let Ok(new_ptr) = res {
-                    let size = cmp::min(old_layout.size(), new_layout.size());
-                    ptr::copy_nonoverlapping(ptr, new_ptr, size);
-                    self.dealloc(ptr, old_layout);
-                }
-                res
-            }
-        }
-
-        fn oom(&mut self, err: AllocErr) -> ! {
-            use core::fmt::{self, Write};
-
-            // Print a message to stderr before aborting to assist with
-            // debugging. It is critical that this code does not allocate any
-            // memory since we are in an OOM situation. Any errors are ignored
-            // while printing since there's nothing we can do about them and we
-            // are about to exit anyways.
-            drop(writeln!(Stderr, "fatal runtime error: {}", err));
-            unsafe {
-                ::core::intrinsics::abort();
-            }
-
-            struct Stderr;
-
-            impl Write for Stderr {
-                #[cfg(target_os = "cloudabi")]
-                fn write_str(&mut self, _: &str) -> fmt::Result {
-                    // CloudABI does not have any reserved file descriptor
-                    // numbers. We should not attempt to write to file
-                    // descriptor #2, as it may be associated with any kind of
-                    // resource.
-                    Ok(())
-                }
-
-                #[cfg(not(target_os = "cloudabi"))]
-                fn write_str(&mut self, s: &str) -> fmt::Result {
-                    unsafe {
-                        libc::write(libc::STDERR_FILENO,
-                                    s.as_ptr() as *const libc::c_void,
-                                    s.len());
-                    }
-                    Ok(())
-                }
+                self.realloc_fallback(ptr, layout, new_size)
             }
         }
     }
 
     #[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))]
     #[inline]
-    unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+    unsafe fn aligned_malloc(layout: &Layout) -> *mut Opaque {
         // On android we currently target API level 9 which unfortunately
         // doesn't have the `posix_memalign` API used below. Instead we use
         // `memalign`, but this unfortunately has the property on some systems
@@ -260,18 +210,19 @@ mod platform {
         // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
         // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
         //                                       /memory/aligned_memory.cc
-        libc::memalign(layout.align(), layout.size()) as *mut u8
+        libc::memalign(layout.align(), layout.size()) as *mut Opaque
     }
 
     #[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))]
     #[inline]
-    unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+    unsafe fn aligned_malloc(layout: &Layout) -> *mut Opaque {
         let mut out = ptr::null_mut();
         let ret = libc::posix_memalign(&mut out, layout.align(), layout.size());
         if ret != 0 {
-            ptr::null_mut()
+            // FIXME: use Opaque::null_mut https://github.com/rust-lang/rust/issues/49659
+            0 as *mut Opaque
         } else {
-            out as *mut u8
+            out as *mut Opaque
         }
     }
 }
@@ -279,22 +230,15 @@ mod platform {
 #[cfg(windows)]
 #[allow(bad_style)]
 mod platform {
-    use core::cmp;
-    use core::ptr;
-
     use MIN_ALIGN;
     use System;
-    use core::heap::{Alloc, AllocErr, Layout, CannotReallocInPlace};
+    use core::alloc::{GlobalAlloc, Opaque, Layout};
 
     type LPVOID = *mut u8;
     type HANDLE = LPVOID;
     type SIZE_T = usize;
     type DWORD = u32;
     type BOOL = i32;
-    type LPDWORD = *mut DWORD;
-    type LPOVERLAPPED = *mut u8;
-
-    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
 
     extern "system" {
         fn GetProcessHeap() -> HANDLE;
@@ -302,20 +246,12 @@ mod platform {
         fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
         fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
         fn GetLastError() -> DWORD;
-        fn WriteFile(hFile: HANDLE,
-                     lpBuffer: LPVOID,
-                     nNumberOfBytesToWrite: DWORD,
-                     lpNumberOfBytesWritten: LPDWORD,
-                     lpOverlapped: LPOVERLAPPED)
-                     -> BOOL;
-        fn GetStdHandle(which: DWORD) -> HANDLE;
     }
 
     #[repr(C)]
     struct Header(*mut u8);
 
     const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
-    const HEAP_REALLOC_IN_PLACE_ONLY: DWORD = 0x00000010;
 
     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
         &mut *(ptr as *mut Header).offset(-1)
@@ -328,9 +264,7 @@ mod platform {
     }
 
     #[inline]
-    unsafe fn allocate_with_flags(layout: Layout, flags: DWORD)
-        -> Result<*mut u8, AllocErr>
-    {
+    unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut Opaque {
         let ptr = if layout.align() <= MIN_ALIGN {
             HeapAlloc(GetProcessHeap(), flags, layout.size())
         } else {
@@ -342,35 +276,29 @@ mod platform {
                 align_ptr(ptr, layout.align())
             }
         };
-        if ptr.is_null() {
-            Err(AllocErr::Exhausted { request: layout })
-        } else {
-            Ok(ptr as *mut u8)
-        }
+        ptr as *mut Opaque
     }
 
     #[unstable(feature = "allocator_api", issue = "32838")]
-    unsafe impl<'a> Alloc for &'a System {
+    unsafe impl GlobalAlloc for System {
         #[inline]
-        unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
+        unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
             allocate_with_flags(layout, 0)
         }
 
         #[inline]
-        unsafe fn alloc_zeroed(&mut self, layout: Layout)
-            -> Result<*mut u8, AllocErr>
-        {
+        unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
             allocate_with_flags(layout, HEAP_ZERO_MEMORY)
         }
 
         #[inline]
-        unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
+        unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
             if layout.align() <= MIN_ALIGN {
                 let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
                 debug_assert!(err != 0, "Failed to free heap memory: {}",
                               GetLastError());
             } else {
-                let header = get_header(ptr);
+                let header = get_header(ptr as *mut u8);
                 let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
                 debug_assert!(err != 0, "Failed to free heap memory: {}",
                               GetLastError());
@@ -378,98 +306,11 @@ mod platform {
         }
 
         #[inline]
-        unsafe fn realloc(&mut self,
-                          ptr: *mut u8,
-                          old_layout: Layout,
-                          new_layout: Layout) -> Result<*mut u8, AllocErr> {
-            if old_layout.align() != new_layout.align() {
-                return Err(AllocErr::Unsupported {
-                    details: "cannot change alignment on `realloc`",
-                })
-            }
-
-            if new_layout.align() <= MIN_ALIGN {
-                let ptr = HeapReAlloc(GetProcessHeap(),
-                                      0,
-                                      ptr as LPVOID,
-                                      new_layout.size());
-                if !ptr.is_null() {
-                    Ok(ptr as *mut u8)
-                } else {
-                    Err(AllocErr::Exhausted { request: new_layout })
-                }
-            } else {
-                let res = self.alloc(new_layout.clone());
-                if let Ok(new_ptr) = res {
-                    let size = cmp::min(old_layout.size(), new_layout.size());
-                    ptr::copy_nonoverlapping(ptr, new_ptr, size);
-                    self.dealloc(ptr, old_layout);
-                }
-                res
-            }
-        }
-
-        #[inline]
-        unsafe fn grow_in_place(&mut self,
-                                ptr: *mut u8,
-                                layout: Layout,
-                                new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-            self.shrink_in_place(ptr, layout, new_layout)
-        }
-
-        #[inline]
-        unsafe fn shrink_in_place(&mut self,
-                                  ptr: *mut u8,
-                                  old_layout: Layout,
-                                  new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-            if old_layout.align() != new_layout.align() {
-                return Err(CannotReallocInPlace)
-            }
-
-            let new = if new_layout.align() <= MIN_ALIGN {
-                HeapReAlloc(GetProcessHeap(),
-                            HEAP_REALLOC_IN_PLACE_ONLY,
-                            ptr as LPVOID,
-                            new_layout.size())
-            } else {
-                let header = get_header(ptr);
-                HeapReAlloc(GetProcessHeap(),
-                            HEAP_REALLOC_IN_PLACE_ONLY,
-                            header.0 as LPVOID,
-                            new_layout.size() + new_layout.align())
-            };
-            if new.is_null() {
-                Err(CannotReallocInPlace)
+        unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *mut Opaque {
+            if layout.align() <= MIN_ALIGN {
+                HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, new_size) as *mut Opaque
             } else {
-                Ok(())
-            }
-        }
-
-        fn oom(&mut self, err: AllocErr) -> ! {
-            use core::fmt::{self, Write};
-
-            // Same as with unix we ignore all errors here
-            drop(writeln!(Stderr, "fatal runtime error: {}", err));
-            unsafe {
-                ::core::intrinsics::abort();
-            }
-
-            struct Stderr;
-
-            impl Write for Stderr {
-                fn write_str(&mut self, s: &str) -> fmt::Result {
-                    unsafe {
-                        // WriteFile silently fails if it is passed an invalid
-                        // handle, so there is no need to check the result of
-                        // GetStdHandle.
-                        WriteFile(GetStdHandle(STD_ERROR_HANDLE),
-                                  s.as_ptr() as LPVOID,
-                                  s.len() as DWORD,
-                                  ptr::null_mut(),
-                                  ptr::null_mut());
-                    }
-                    Ok(())
-                }
+                self.realloc_fallback(ptr, layout, new_size)
             }
         }
     }
@@ -496,69 +337,92 @@ mod platform {
 mod platform {
     extern crate dlmalloc;
 
-    use core::heap::{Alloc, AllocErr, Layout, Excess, CannotReallocInPlace};
+    use core::alloc::{GlobalAlloc, Layout, Opaque};
     use System;
-    use self::dlmalloc::GlobalDlmalloc;
+
+    // No need for synchronization here as wasm is currently single-threaded
+    static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
 
     #[unstable(feature = "allocator_api", issue = "32838")]
-    unsafe impl<'a> Alloc for &'a System {
+    unsafe impl GlobalAlloc for System {
         #[inline]
-        unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
-            GlobalDlmalloc.alloc(layout)
+        unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
+            DLMALLOC.malloc(layout.size(), layout.align()) as *mut Opaque
         }
 
         #[inline]
-        unsafe fn alloc_zeroed(&mut self, layout: Layout)
-            -> Result<*mut u8, AllocErr>
-        {
-            GlobalDlmalloc.alloc_zeroed(layout)
+        unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
+            DLMALLOC.calloc(layout.size(), layout.align()) as *mut Opaque
         }
 
         #[inline]
-        unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
-            GlobalDlmalloc.dealloc(ptr, layout)
+        unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
+            DLMALLOC.free(ptr as *mut u8, layout.size(), layout.align())
         }
 
         #[inline]
-        unsafe fn realloc(&mut self,
-                          ptr: *mut u8,
-                          old_layout: Layout,
-                          new_layout: Layout) -> Result<*mut u8, AllocErr> {
-            GlobalDlmalloc.realloc(ptr, old_layout, new_layout)
+        unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *mut Opaque {
+            DLMALLOC.realloc(ptr as *mut u8, layout.size(), layout.align(), new_size) as *mut Opaque
         }
+    }
+}
 
-        #[inline]
-        fn usable_size(&self, layout: &Layout) -> (usize, usize) {
-            GlobalDlmalloc.usable_size(layout)
-        }
+#[inline]
+fn oom() -> ! {
+    write_to_stderr("fatal runtime error: memory allocation failed");
+    unsafe {
+        ::core::intrinsics::abort();
+    }
+}
 
-        #[inline]
-        unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
-            GlobalDlmalloc.alloc_excess(layout)
-        }
+#[cfg(any(unix, target_os = "redox"))]
+#[inline]
+fn write_to_stderr(s: &str) {
+    extern crate libc;
 
-        #[inline]
-        unsafe fn realloc_excess(&mut self,
-                                 ptr: *mut u8,
-                                 layout: Layout,
-                                 new_layout: Layout) -> Result<Excess, AllocErr> {
-            GlobalDlmalloc.realloc_excess(ptr, layout, new_layout)
-        }
+    unsafe {
+        libc::write(libc::STDERR_FILENO,
+                    s.as_ptr() as *const libc::c_void,
+                    s.len());
+    }
+}
 
-        #[inline]
-        unsafe fn grow_in_place(&mut self,
-                                ptr: *mut u8,
-                                layout: Layout,
-                                new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-            GlobalDlmalloc.grow_in_place(ptr, layout, new_layout)
-        }
+#[cfg(windows)]
+#[inline]
+fn write_to_stderr(s: &str) {
+    use core::ptr;
 
-        #[inline]
-        unsafe fn shrink_in_place(&mut self,
-                                  ptr: *mut u8,
-                                  layout: Layout,
-                                  new_layout: Layout) -> Result<(), CannotReallocInPlace> {
-            GlobalDlmalloc.shrink_in_place(ptr, layout, new_layout)
-        }
+    type LPVOID = *mut u8;
+    type HANDLE = LPVOID;
+    type DWORD = u32;
+    type BOOL = i32;
+    type LPDWORD = *mut DWORD;
+    type LPOVERLAPPED = *mut u8;
+
+    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
+
+    extern "system" {
+        fn WriteFile(hFile: HANDLE,
+                     lpBuffer: LPVOID,
+                     nNumberOfBytesToWrite: DWORD,
+                     lpNumberOfBytesWritten: LPDWORD,
+                     lpOverlapped: LPOVERLAPPED)
+                     -> BOOL;
+        fn GetStdHandle(which: DWORD) -> HANDLE;
+    }
+
+    unsafe {
+        // WriteFile silently fails if it is passed an invalid
+        // handle, so there is no need to check the result of
+        // GetStdHandle.
+        WriteFile(GetStdHandle(STD_ERROR_HANDLE),
+                  s.as_ptr() as LPVOID,
+                  s.len() as DWORD,
+                  ptr::null_mut(),
+                  ptr::null_mut());
     }
 }
+
+#[cfg(not(any(windows, unix, target_os = "redox")))]
+#[inline]
+fn write_to_stderr(_: &str) {}
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 7eaf67e6ea6..b319f333342 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -22,7 +22,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(no_crate_inject, attr(deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
diff --git a/src/libcore/heap.rs b/src/libcore/alloc.rs
index fe19c923a58..8f8849e32e6 100644
--- a/src/libcore/heap.rs
+++ b/src/libcore/alloc.rs
@@ -21,10 +21,30 @@ use mem;
 use usize;
 use ptr::{self, NonNull};
 
+extern {
+    /// An opaque, unsized type. Used for pointers to allocated memory.
+    ///
+    /// This type can only be used behind a pointer like `*mut Opaque` or `ptr::NonNull<Opaque>`.
+    /// Such pointers are similar to C’s `void*` type.
+    pub type Opaque;
+}
+
+impl Opaque {
+    /// Similar to `std::ptr::null`, which requires `T: Sized`.
+    pub fn null() -> *const Self {
+        0 as _
+    }
+
+    /// Similar to `std::ptr::null_mut`, which requires `T: Sized`.
+    pub fn null_mut() -> *mut Self {
+        0 as _
+    }
+}
+
 /// Represents the combination of a starting address and
 /// a total capacity of the returned block.
 #[derive(Debug)]
-pub struct Excess(pub *mut u8, pub usize);
+pub struct Excess(pub NonNull<Opaque>, pub usize);
 
 fn size_align<T>() -> (usize, usize) {
     (mem::size_of::<T>(), mem::align_of::<T>())
@@ -74,9 +94,9 @@ impl Layout {
     ///    must not overflow (i.e. the rounded value must be less than
     ///    `usize::MAX`).
     #[inline]
-    pub fn from_size_align(size: usize, align: usize) -> Option<Layout> {
+    pub fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
         if !align.is_power_of_two() {
-            return None;
+            return Err(LayoutErr { private: () });
         }
 
         // (power-of-two implies align != 0.)
@@ -94,11 +114,11 @@ impl Layout {
         // Above implies that checking for summation overflow is both
         // necessary and sufficient.
         if size > usize::MAX - (align - 1) {
-            return None;
+            return Err(LayoutErr { private: () });
         }
 
         unsafe {
-            Some(Layout::from_size_align_unchecked(size, align))
+            Ok(Layout::from_size_align_unchecked(size, align))
         }
     }
 
@@ -110,7 +130,7 @@ impl Layout {
     /// a power-of-two nor `size` aligned to `align` fits within the
     /// address space (i.e. the `Layout::from_size_align` preconditions).
     #[inline]
-    pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Layout {
+    pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
         Layout { size: size, align: align }
     }
 
@@ -209,15 +229,17 @@ impl Layout {
     ///
     /// On arithmetic overflow, returns `None`.
     #[inline]
-    pub fn repeat(&self, n: usize) -> Option<(Self, usize)> {
-        let padded_size = self.size.checked_add(self.padding_needed_for(self.align))?;
-        let alloc_size = padded_size.checked_mul(n)?;
+    pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
+        let padded_size = self.size.checked_add(self.padding_needed_for(self.align))
+            .ok_or(LayoutErr { private: () })?;
+        let alloc_size = padded_size.checked_mul(n)
+            .ok_or(LayoutErr { private: () })?;
 
         // We can assume that `self.align` is a power-of-two.
         // Furthermore, `alloc_size` has already been rounded up
         // to a multiple of `self.align`; therefore, the call to
         // `Layout::from_size_align` below should never panic.
-        Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size))
+        Ok((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size))
     }
 
     /// Creates a layout describing the record for `self` followed by
@@ -231,17 +253,19 @@ impl Layout {
     /// (assuming that the record itself starts at offset 0).
     ///
     /// On arithmetic overflow, returns `None`.
-    pub fn extend(&self, next: Self) -> Option<(Self, usize)> {
+    pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
         let new_align = cmp::max(self.align, next.align);
         let realigned = Layout::from_size_align(self.size, new_align)?;
 
         let pad = realigned.padding_needed_for(next.align);
 
-        let offset = self.size.checked_add(pad)?;
-        let new_size = offset.checked_add(next.size)?;
+        let offset = self.size.checked_add(pad)
+            .ok_or(LayoutErr { private: () })?;
+        let new_size = offset.checked_add(next.size)
+            .ok_or(LayoutErr { private: () })?;
 
         let layout = Layout::from_size_align(new_size, new_align)?;
-        Some((layout, offset))
+        Ok((layout, offset))
     }
 
     /// Creates a layout describing the record for `n` instances of
@@ -256,8 +280,8 @@ impl Layout {
     /// aligned.
     ///
     /// On arithmetic overflow, returns `None`.
-    pub fn repeat_packed(&self, n: usize) -> Option<Self> {
-        let size = self.size().checked_mul(n)?;
+    pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
+        let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
         Layout::from_size_align(size, self.align)
     }
 
@@ -276,16 +300,17 @@ impl Layout {
     ///  `extend`.)
     ///
     /// On arithmetic overflow, returns `None`.
-    pub fn extend_packed(&self, next: Self) -> Option<(Self, usize)> {
-        let new_size = self.size().checked_add(next.size())?;
+    pub fn extend_packed(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
+        let new_size = self.size().checked_add(next.size())
+            .ok_or(LayoutErr { private: () })?;
         let layout = Layout::from_size_align(new_size, self.align)?;
-        Some((layout, self.size()))
+        Ok((layout, self.size()))
     }
 
     /// Creates a layout describing the record for a `[T; n]`.
     ///
     /// On arithmetic overflow, returns `None`.
-    pub fn array<T>(n: usize) -> Option<Self> {
+    pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
         Layout::new::<T>()
             .repeat(n)
             .map(|(k, offs)| {
@@ -295,55 +320,31 @@ impl Layout {
     }
 }
 
-/// The `AllocErr` error specifies whether an allocation failure is
-/// specifically due to resource exhaustion or if it is due to
-/// something wrong when combining the given input arguments with this
-/// allocator.
+/// The parameters given to `Layout::from_size_align` do not satisfy
+/// its documented constraints.
 #[derive(Clone, PartialEq, Eq, Debug)]
-pub enum AllocErr {
-    /// Error due to hitting some resource limit or otherwise running
-    /// out of memory. This condition strongly implies that *some*
-    /// series of deallocations would allow a subsequent reissuing of
-    /// the original allocation request to succeed.
-    Exhausted { request: Layout },
-
-    /// Error due to allocator being fundamentally incapable of
-    /// satisfying the original request. This condition implies that
-    /// such an allocation request will never succeed on the given
-    /// allocator, regardless of environment, memory pressure, or
-    /// other contextual conditions.
-    ///
-    /// For example, an allocator that does not support requests for
-    /// large memory blocks might return this error variant.
-    Unsupported { details: &'static str },
+pub struct LayoutErr {
+    private: ()
 }
 
-impl AllocErr {
-    #[inline]
-    pub fn invalid_input(details: &'static str) -> Self {
-        AllocErr::Unsupported { details: details }
-    }
-    #[inline]
-    pub fn is_memory_exhausted(&self) -> bool {
-        if let AllocErr::Exhausted { .. } = *self { true } else { false }
-    }
-    #[inline]
-    pub fn is_request_unsupported(&self) -> bool {
-        if let AllocErr::Unsupported { .. } = *self { true } else { false }
-    }
-    #[inline]
-    pub fn description(&self) -> &str {
-        match *self {
-            AllocErr::Exhausted { .. } => "allocator memory exhausted",
-            AllocErr::Unsupported { .. } => "unsupported allocator request",
-        }
+// (we need this for downstream impl of trait Error)
+impl fmt::Display for LayoutErr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("invalid parameters to Layout::from_size_align")
     }
 }
 
+/// The `AllocErr` error specifies whether an allocation failure is
+/// specifically due to resource exhaustion or if it is due to
+/// something wrong when combining the given input arguments with this
+/// allocator.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AllocErr;
+
 // (we need this for downstream impl of trait Error)
 impl fmt::Display for AllocErr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.description())
+        f.write_str("memory allocation failed")
     }
 }
 
@@ -374,13 +375,85 @@ pub enum CollectionAllocErr {
     /// (usually `isize::MAX` bytes).
     CapacityOverflow,
     /// Error due to the allocator (see the `AllocErr` type's docs).
-    AllocErr(AllocErr),
+    AllocErr,
 }
 
 #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
 impl From<AllocErr> for CollectionAllocErr {
-    fn from(err: AllocErr) -> Self {
-        CollectionAllocErr::AllocErr(err)
+    fn from(AllocErr: AllocErr) -> Self {
+        CollectionAllocErr::AllocErr
+    }
+}
+
+/// A memory allocator that can be registered to be the one backing `std::alloc::Global`
+/// though the `#[global_allocator]` attributes.
+pub unsafe trait GlobalAlloc {
+    /// Allocate memory as described by the given `layout`.
+    ///
+    /// Returns a pointer to newly-allocated memory,
+    /// or NULL to indicate allocation failure.
+    ///
+    /// # Safety
+    ///
+    /// **FIXME:** what are the exact requirements?
+    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque;
+
+    /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
+    ///
+    /// # Safety
+    ///
+    /// **FIXME:** what are the exact requirements?
+    /// In particular around layout *fit*. (See docs for the `Alloc` trait.)
+    unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout);
+
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
+        let size = layout.size();
+        let ptr = self.alloc(layout);
+        if !ptr.is_null() {
+            ptr::write_bytes(ptr as *mut u8, 0, size);
+        }
+        ptr
+    }
+
+    /// Shink or grow a block of memory to the given `new_size`.
+    /// The block is described by the given `ptr` pointer and `layout`.
+    ///
+    /// Return a new pointer (which may or may not be the same as `ptr`),
+    /// or NULL to indicate reallocation failure.
+    ///
+    /// If reallocation is successful, the old `ptr` pointer is considered
+    /// to have been deallocated.
+    ///
+    /// # Safety
+    ///
+    /// `new_size`, when rounded up to the nearest multiple of `old_layout.align()`,
+    /// must not overflow (i.e. the rounded value must be less than `usize::MAX`).
+    ///
+    /// **FIXME:** what are the exact requirements?
+    /// In particular around layout *fit*. (See docs for the `Alloc` trait.)
+    unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *mut Opaque {
+        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
+        let new_ptr = self.alloc(new_layout);
+        if !new_ptr.is_null() {
+            ptr::copy_nonoverlapping(
+                ptr as *const u8,
+                new_ptr as *mut u8,
+                cmp::min(layout.size(), new_size),
+            );
+            self.dealloc(ptr, layout);
+        }
+        new_ptr
+    }
+
+    /// Aborts the thread or process, optionally performing
+    /// cleanup or logging diagnostic information before panicking or
+    /// aborting.
+    ///
+    /// `oom` is meant to be used by clients unable to cope with an
+    /// unsatisfied allocation request, and wish to abandon
+    /// computation rather than attempt to recover locally.
+    fn oom(&self) -> ! {
+        unsafe { ::intrinsics::abort() }
     }
 }
 
@@ -515,7 +588,7 @@ pub unsafe trait Alloc {
     /// Clients wishing to abort computation in response to an
     /// allocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>;
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr>;
 
     /// Deallocate the memory referenced by `ptr`.
     ///
@@ -532,7 +605,7 @@ pub unsafe trait Alloc {
     /// * In addition to fitting the block of memory `layout`, the
     ///   alignment of the `layout` must match the alignment used
     ///   to allocate that block of memory.
-    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout);
+    unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout);
 
     /// Allocator-specific method for signaling an out-of-memory
     /// condition.
@@ -542,12 +615,8 @@ pub unsafe trait Alloc {
     /// aborting.
     ///
     /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request (signaled by an error such as
-    /// `AllocErr::Exhausted`), and wish to abandon computation rather
-    /// than attempt to recover locally. Such clients should pass the
-    /// signaling error value back into `oom`, where the allocator
-    /// may incorporate that error value into its diagnostic report
-    /// before aborting.
+    /// unsatisfied allocation request, and wish to abandon
+    /// computation rather than attempt to recover locally.
     ///
     /// Implementations of the `oom` method are discouraged from
     /// infinitely regressing in nested calls to `oom`. In
@@ -560,7 +629,7 @@ pub unsafe trait Alloc {
     /// instead they should return an appropriate error from the
     /// invoked method, and let the client decide whether to invoke
     /// this `oom` method in response.
-    fn oom(&mut self, _: AllocErr) -> ! {
+    fn oom(&mut self) -> ! {
         unsafe { ::intrinsics::abort() }
     }
 
@@ -602,9 +671,10 @@ pub unsafe trait Alloc {
     // realloc. alloc_excess, realloc_excess
 
     /// Returns a pointer suitable for holding data described by
-    /// `new_layout`, meeting its size and alignment guarantees. To
+    /// a new layout with `layout`’s alginment and a size given
+    /// by `new_size`. To
     /// accomplish this, this may extend or shrink the allocation
-    /// referenced by `ptr` to fit `new_layout`.
+    /// referenced by `ptr` to fit the new layout.
     ///
     /// If this returns `Ok`, then ownership of the memory block
     /// referenced by `ptr` has been transferred to this
@@ -617,12 +687,6 @@ pub unsafe trait Alloc {
     /// block has not been transferred to this allocator, and the
     /// contents of the memory block are unaltered.
     ///
-    /// For best results, `new_layout` should not impose a different
-    /// alignment constraint than `layout`. (In other words,
-    /// `new_layout.align()` should equal `layout.align()`.) However,
-    /// behavior is well-defined (though underspecified) when this
-    /// constraint is violated; further discussion below.
-    ///
     /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
@@ -630,12 +694,13 @@ pub unsafe trait Alloc {
     ///
     /// * `ptr` must be currently allocated via this allocator,
     ///
-    /// * `layout` must *fit* the `ptr` (see above). (The `new_layout`
+    /// * `layout` must *fit* the `ptr` (see above). (The `new_size`
     ///   argument need not fit it.)
     ///
-    /// * `new_layout` must have size greater than zero.
+    /// * `new_size` must be greater than zero.
     ///
-    /// * the alignment of `new_layout` is non-zero.
+    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
+    ///   must not overflow (i.e. the rounded value must be less than `usize::MAX`).
     ///
     /// (Extension subtraits might provide more specific bounds on
     /// behavior, e.g. guarantee a sentinel address or a null pointer
@@ -643,18 +708,11 @@ pub unsafe trait Alloc {
     ///
     /// # Errors
     ///
-    /// Returns `Err` only if `new_layout` does not match the
-    /// alignment of `layout`, or does not meet the allocator's size
+    /// Returns `Err` only if the new layout
+    /// does not meet the allocator's size
     /// and alignment constraints of the allocator, or if reallocation
     /// otherwise fails.
     ///
-    /// (Note the previous sentence did not say "if and only if" -- in
-    /// particular, an implementation of this method *can* return `Ok`
-    /// if `new_layout.align() != old_layout.align()`; or it can
-    /// return `Err` in that scenario, depending on whether this
-    /// allocator can dynamically adjust the alignment constraint for
-    /// the block.)
-    ///
     /// Implementations are encouraged to return `Err` on memory
     /// exhaustion rather than panicking or aborting, but this is not
     /// a strict requirement. (Specifically: it is *legal* to
@@ -665,27 +723,28 @@ pub unsafe trait Alloc {
     /// reallocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
     unsafe fn realloc(&mut self,
-                      ptr: *mut u8,
+                      ptr: NonNull<Opaque>,
                       layout: Layout,
-                      new_layout: Layout) -> Result<*mut u8, AllocErr> {
-        let new_size = new_layout.size();
+                      new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         let old_size = layout.size();
-        let aligns_match = layout.align == new_layout.align;
 
-        if new_size >= old_size && aligns_match {
-            if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_layout.clone()) {
+        if new_size >= old_size {
+            if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_size) {
                 return Ok(ptr);
             }
-        } else if new_size < old_size && aligns_match {
-            if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_layout.clone()) {
+        } else if new_size < old_size {
+            if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_size) {
                 return Ok(ptr);
             }
         }
 
         // otherwise, fall back on alloc + copy + dealloc.
+        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
         let result = self.alloc(new_layout);
         if let Ok(new_ptr) = result {
-            ptr::copy_nonoverlapping(ptr as *const u8, new_ptr, cmp::min(old_size, new_size));
+            ptr::copy_nonoverlapping(ptr.as_ptr() as *const u8,
+                                     new_ptr.as_ptr() as *mut u8,
+                                     cmp::min(old_size, new_size));
             self.dealloc(ptr, layout);
         }
         result
@@ -707,11 +766,11 @@ pub unsafe trait Alloc {
     /// Clients wishing to abort computation in response to an
     /// allocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
         let size = layout.size();
         let p = self.alloc(layout);
         if let Ok(p) = p {
-            ptr::write_bytes(p, 0, size);
+            ptr::write_bytes(p.as_ptr() as *mut u8, 0, size);
         }
         p
     }
@@ -756,19 +815,21 @@ pub unsafe trait Alloc {
     /// reallocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
     unsafe fn realloc_excess(&mut self,
-                             ptr: *mut u8,
+                             ptr: NonNull<Opaque>,
                              layout: Layout,
-                             new_layout: Layout) -> Result<Excess, AllocErr> {
+                             new_size: usize) -> Result<Excess, AllocErr> {
+        let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
         let usable_size = self.usable_size(&new_layout);
-        self.realloc(ptr, layout, new_layout)
+        self.realloc(ptr, layout, new_size)
             .map(|p| Excess(p, usable_size.1))
     }
 
-    /// Attempts to extend the allocation referenced by `ptr` to fit `new_layout`.
+    /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`.
     ///
     /// If this returns `Ok`, then the allocator has asserted that the
-    /// memory block referenced by `ptr` now fits `new_layout`, and thus can
-    /// be used to carry data of that layout. (The allocator is allowed to
+    /// memory block referenced by `ptr` now fits `new_size`, and thus can
+    /// be used to carry data of a layout of that size and same alignment as
+    /// `layout`. (The allocator is allowed to
     /// expend effort to accomplish this, such as extending the memory block to
     /// include successor blocks, or virtual memory tricks.)
     ///
@@ -784,11 +845,9 @@ pub unsafe trait Alloc {
     /// * `ptr` must be currently allocated via this allocator,
     ///
     /// * `layout` must *fit* the `ptr` (see above); note the
-    ///   `new_layout` argument need not fit it,
+    ///   `new_size` argument need not fit it,
     ///
-    /// * `new_layout.size()` must not be less than `layout.size()`,
-    ///
-    /// * `new_layout.align()` must equal `layout.align()`.
+    /// * `new_size` must not be less than `layout.size()`,
     ///
     /// # Errors
     ///
@@ -801,26 +860,25 @@ pub unsafe trait Alloc {
     /// `grow_in_place` failures without aborting, or to fall back on
     /// another reallocation method before resorting to an abort.
     unsafe fn grow_in_place(&mut self,
-                            ptr: *mut u8,
+                            ptr: NonNull<Opaque>,
                             layout: Layout,
-                            new_layout: Layout) -> Result<(), CannotReallocInPlace> {
+                            new_size: usize) -> Result<(), CannotReallocInPlace> {
         let _ = ptr; // this default implementation doesn't care about the actual address.
-        debug_assert!(new_layout.size >= layout.size);
-        debug_assert!(new_layout.align == layout.align);
+        debug_assert!(new_size >= layout.size);
         let (_l, u) = self.usable_size(&layout);
         // _l <= layout.size()                       [guaranteed by usable_size()]
         //       layout.size() <= new_layout.size()  [required by this method]
-        if new_layout.size <= u {
+        if new_size <= u {
             return Ok(());
         } else {
             return Err(CannotReallocInPlace);
         }
     }
 
-    /// Attempts to shrink the allocation referenced by `ptr` to fit `new_layout`.
+    /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`.
     ///
     /// If this returns `Ok`, then the allocator has asserted that the
-    /// memory block referenced by `ptr` now fits `new_layout`, and
+    /// memory block referenced by `ptr` now fits `new_size`, and
     /// thus can only be used to carry data of that smaller
     /// layout. (The allocator is allowed to take advantage of this,
     /// carving off portions of the block for reuse elsewhere.) The
@@ -841,13 +899,11 @@ pub unsafe trait Alloc {
     /// * `ptr` must be currently allocated via this allocator,
     ///
     /// * `layout` must *fit* the `ptr` (see above); note the
-    ///   `new_layout` argument need not fit it,
+    ///   `new_size` argument need not fit it,
     ///
-    /// * `new_layout.size()` must not be greater than `layout.size()`
+    /// * `new_size` must not be greater than `layout.size()`
     ///   (and must be greater than zero),
     ///
-    /// * `new_layout.align()` must equal `layout.align()`.
-    ///
     /// # Errors
     ///
     /// Returns `Err(CannotReallocInPlace)` when the allocator is
@@ -859,16 +915,15 @@ pub unsafe trait Alloc {
     /// `shrink_in_place` failures without aborting, or to fall back
     /// on another reallocation method before resorting to an abort.
     unsafe fn shrink_in_place(&mut self,
-                              ptr: *mut u8,
+                              ptr: NonNull<Opaque>,
                               layout: Layout,
-                              new_layout: Layout) -> Result<(), CannotReallocInPlace> {
+                              new_size: usize) -> Result<(), CannotReallocInPlace> {
         let _ = ptr; // this default implementation doesn't care about the actual address.
-        debug_assert!(new_layout.size <= layout.size);
-        debug_assert!(new_layout.align == layout.align);
+        debug_assert!(new_size <= layout.size);
         let (l, _u) = self.usable_size(&layout);
         //                      layout.size() <= _u  [guaranteed by usable_size()]
         // new_layout.size() <= layout.size()        [required by this method]
-        if l <= new_layout.size {
+        if l <= new_size {
             return Ok(());
         } else {
             return Err(CannotReallocInPlace);
@@ -911,9 +966,9 @@ pub unsafe trait Alloc {
     {
         let k = Layout::new::<T>();
         if k.size() > 0 {
-            unsafe { self.alloc(k).map(|p| NonNull::new_unchecked(p as *mut T)) }
+            unsafe { self.alloc(k).map(|p| p.cast()) }
         } else {
-            Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
+            Err(AllocErr)
         }
     }
 
@@ -937,10 +992,9 @@ pub unsafe trait Alloc {
     unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
         where Self: Sized
     {
-        let raw_ptr = ptr.as_ptr() as *mut u8;
         let k = Layout::new::<T>();
         if k.size() > 0 {
-            self.dealloc(raw_ptr, k);
+            self.dealloc(ptr.as_opaque(), k);
         }
     }
 
@@ -978,15 +1032,12 @@ pub unsafe trait Alloc {
         where Self: Sized
     {
         match Layout::array::<T>(n) {
-            Some(ref layout) if layout.size() > 0 => {
+            Ok(ref layout) if layout.size() > 0 => {
                 unsafe {
-                    self.alloc(layout.clone())
-                        .map(|p| {
-                            NonNull::new_unchecked(p as *mut T)
-                        })
+                    self.alloc(layout.clone()).map(|p| p.cast())
                 }
             }
-            _ => Err(AllocErr::invalid_input("invalid layout for alloc_array")),
+            _ => Err(AllocErr),
         }
     }
 
@@ -1028,13 +1079,13 @@ pub unsafe trait Alloc {
                                n_new: usize) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
-        match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
-            (Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
-                self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
-                    .map(|p| NonNull::new_unchecked(p as *mut T))
+        match (Layout::array::<T>(n_old), Layout::array::<T>(n_new)) {
+            (Ok(ref k_old), Ok(ref k_new)) if k_old.size() > 0 && k_new.size() > 0 => {
+                debug_assert!(k_old.align() == k_new.align());
+                self.realloc(ptr.as_opaque(), k_old.clone(), k_new.size()).map(NonNull::cast)
             }
             _ => {
-                Err(AllocErr::invalid_input("invalid layout for realloc_array"))
+                Err(AllocErr)
             }
         }
     }
@@ -1062,13 +1113,12 @@ pub unsafe trait Alloc {
     unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr>
         where Self: Sized
     {
-        let raw_ptr = ptr.as_ptr() as *mut u8;
         match Layout::array::<T>(n) {
-            Some(ref k) if k.size() > 0 => {
-                Ok(self.dealloc(raw_ptr, k.clone()))
+            Ok(ref k) if k.size() > 0 => {
+                Ok(self.dealloc(ptr.as_opaque(), k.clone()))
             }
             _ => {
-                Err(AllocErr::invalid_input("invalid layout for dealloc_array"))
+                Err(AllocErr)
             }
         }
     }
diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs
index c947b003ccb..ced77d77918 100644
--- a/src/libcore/benches/lib.rs
+++ b/src/libcore/benches/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(flt2dec)]
 #![feature(test)]
 
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
deleted file mode 100644
index 718c6b893ed..00000000000
--- a/src/libcore/char.rs
+++ /dev/null
@@ -1,918 +0,0 @@
-// 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.
-
-//! Character manipulation.
-//!
-//! For more details, see ::std_unicode::char (a.k.a. std::char)
-
-#![allow(non_snake_case)]
-#![stable(feature = "core_char", since = "1.2.0")]
-
-use char_private::is_printable;
-use convert::TryFrom;
-use fmt::{self, Write};
-use slice;
-use str::{from_utf8_unchecked_mut, FromStr};
-use iter::FusedIterator;
-use mem::transmute;
-
-// UTF-8 ranges and tags for encoding characters
-const TAG_CONT: u8    = 0b1000_0000;
-const TAG_TWO_B: u8   = 0b1100_0000;
-const TAG_THREE_B: u8 = 0b1110_0000;
-const TAG_FOUR_B: u8  = 0b1111_0000;
-const MAX_ONE_B: u32   =     0x80;
-const MAX_TWO_B: u32   =    0x800;
-const MAX_THREE_B: u32 =  0x10000;
-
-/*
-    Lu  Uppercase_Letter        an uppercase letter
-    Ll  Lowercase_Letter        a lowercase letter
-    Lt  Titlecase_Letter        a digraphic character, with first part uppercase
-    Lm  Modifier_Letter         a modifier letter
-    Lo  Other_Letter            other letters, including syllables and ideographs
-    Mn  Nonspacing_Mark         a nonspacing combining mark (zero advance width)
-    Mc  Spacing_Mark            a spacing combining mark (positive advance width)
-    Me  Enclosing_Mark          an enclosing combining mark
-    Nd  Decimal_Number          a decimal digit
-    Nl  Letter_Number           a letterlike numeric character
-    No  Other_Number            a numeric character of other type
-    Pc  Connector_Punctuation   a connecting punctuation mark, like a tie
-    Pd  Dash_Punctuation        a dash or hyphen punctuation mark
-    Ps  Open_Punctuation        an opening punctuation mark (of a pair)
-    Pe  Close_Punctuation       a closing punctuation mark (of a pair)
-    Pi  Initial_Punctuation     an initial quotation mark
-    Pf  Final_Punctuation       a final quotation mark
-    Po  Other_Punctuation       a punctuation mark of other type
-    Sm  Math_Symbol             a symbol of primarily mathematical use
-    Sc  Currency_Symbol         a currency sign
-    Sk  Modifier_Symbol         a non-letterlike modifier symbol
-    So  Other_Symbol            a symbol of other type
-    Zs  Space_Separator         a space character (of various non-zero widths)
-    Zl  Line_Separator          U+2028 LINE SEPARATOR only
-    Zp  Paragraph_Separator     U+2029 PARAGRAPH SEPARATOR only
-    Cc  Control                 a C0 or C1 control code
-    Cf  Format                  a format control character
-    Cs  Surrogate               a surrogate code point
-    Co  Private_Use             a private-use character
-    Cn  Unassigned              a reserved unassigned code point or a noncharacter
-*/
-
-/// The highest valid code point a `char` can have.
-///
-/// A [`char`] is a [Unicode Scalar Value], which means that it is a [Code
-/// Point], but only ones within a certain range. `MAX` is the highest valid
-/// code point that's a valid [Unicode Scalar Value].
-///
-/// [`char`]: ../../std/primitive.char.html
-/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
-/// [Code Point]: http://www.unicode.org/glossary/#code_point
-#[stable(feature = "rust1", since = "1.0.0")]
-pub const MAX: char = '\u{10ffff}';
-
-/// Converts a `u32` to a `char`.
-///
-/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
-/// [`as`]:
-///
-/// ```
-/// let c = '💯';
-/// let i = c as u32;
-///
-/// assert_eq!(128175, i);
-/// ```
-///
-/// However, the reverse is not true: not all valid [`u32`]s are valid
-/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
-/// for a [`char`].
-///
-/// [`char`]: ../../std/primitive.char.html
-/// [`u32`]: ../../std/primitive.u32.html
-/// [`as`]: ../../book/first-edition/casting-between-types.html#as
-///
-/// For an unsafe version of this function which ignores these checks, see
-/// [`from_u32_unchecked`].
-///
-/// [`from_u32_unchecked`]: fn.from_u32_unchecked.html
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::char;
-///
-/// let c = char::from_u32(0x2764);
-///
-/// assert_eq!(Some('❤'), c);
-/// ```
-///
-/// Returning `None` when the input is not a valid [`char`]:
-///
-/// ```
-/// use std::char;
-///
-/// let c = char::from_u32(0x110000);
-///
-/// assert_eq!(None, c);
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn from_u32(i: u32) -> Option<char> {
-    char::try_from(i).ok()
-}
-
-/// Converts a `u32` to a `char`, ignoring validity.
-///
-/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
-/// [`as`]:
-///
-/// ```
-/// let c = '💯';
-/// let i = c as u32;
-///
-/// assert_eq!(128175, i);
-/// ```
-///
-/// However, the reverse is not true: not all valid [`u32`]s are valid
-/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
-/// [`char`], possibly creating an invalid one.
-///
-/// [`char`]: ../../std/primitive.char.html
-/// [`u32`]: ../../std/primitive.u32.html
-/// [`as`]: ../../book/first-edition/casting-between-types.html#as
-///
-/// # Safety
-///
-/// This function is unsafe, as it may construct invalid `char` values.
-///
-/// For a safe version of this function, see the [`from_u32`] function.
-///
-/// [`from_u32`]: fn.from_u32.html
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::char;
-///
-/// let c = unsafe { char::from_u32_unchecked(0x2764) };
-///
-/// assert_eq!('❤', c);
-/// ```
-#[inline]
-#[stable(feature = "char_from_unchecked", since = "1.5.0")]
-pub unsafe fn from_u32_unchecked(i: u32) -> char {
-    transmute(i)
-}
-
-#[stable(feature = "char_convert", since = "1.13.0")]
-impl From<char> for u32 {
-    #[inline]
-    fn from(c: char) -> Self {
-        c as u32
-    }
-}
-
-/// Maps a byte in 0x00...0xFF to a `char` whose code point has the same value, in U+0000 to U+00FF.
-///
-/// Unicode is designed such that this effectively decodes bytes
-/// with the character encoding that IANA calls ISO-8859-1.
-/// This encoding is compatible with ASCII.
-///
-/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
-/// which leaves some "blanks", byte values that are not assigned to any character.
-/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
-///
-/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
-/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
-/// to punctuation and various Latin characters.
-///
-/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
-/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
-/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
-/// C0 and C1 control codes.
-#[stable(feature = "char_convert", since = "1.13.0")]
-impl From<u8> for char {
-    #[inline]
-    fn from(i: u8) -> Self {
-        i as char
-    }
-}
-
-
-/// An error which can be returned when parsing a char.
-#[stable(feature = "char_from_str", since = "1.20.0")]
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct ParseCharError {
-    kind: CharErrorKind,
-}
-
-impl ParseCharError {
-    #[unstable(feature = "char_error_internals",
-               reason = "this method should not be available publicly",
-               issue = "0")]
-    #[doc(hidden)]
-    pub fn __description(&self) -> &str {
-        match self.kind {
-            CharErrorKind::EmptyString => {
-                "cannot parse char from empty string"
-            },
-            CharErrorKind::TooManyChars => "too many characters in string"
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-enum CharErrorKind {
-    EmptyString,
-    TooManyChars,
-}
-
-#[stable(feature = "char_from_str", since = "1.20.0")]
-impl fmt::Display for ParseCharError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.__description().fmt(f)
-    }
-}
-
-
-#[stable(feature = "char_from_str", since = "1.20.0")]
-impl FromStr for char {
-    type Err = ParseCharError;
-
-    #[inline]
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        let mut chars = s.chars();
-        match (chars.next(), chars.next()) {
-            (None, _) => {
-                Err(ParseCharError { kind: CharErrorKind::EmptyString })
-            },
-            (Some(c), None) => Ok(c),
-            _ => {
-                Err(ParseCharError { kind: CharErrorKind::TooManyChars })
-            }
-        }
-    }
-}
-
-
-#[stable(feature = "try_from", since = "1.26.0")]
-impl TryFrom<u32> for char {
-    type Error = CharTryFromError;
-
-    #[inline]
-    fn try_from(i: u32) -> Result<Self, Self::Error> {
-        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
-            Err(CharTryFromError(()))
-        } else {
-            Ok(unsafe { from_u32_unchecked(i) })
-        }
-    }
-}
-
-/// The error type returned when a conversion from u32 to char fails.
-#[stable(feature = "try_from", since = "1.26.0")]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct CharTryFromError(());
-
-#[stable(feature = "try_from", since = "1.26.0")]
-impl fmt::Display for CharTryFromError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        "converted integer out of range for `char`".fmt(f)
-    }
-}
-
-/// Converts a digit in the given radix to a `char`.
-///
-/// A 'radix' here is sometimes also called a 'base'. A radix of two
-/// indicates a binary number, a radix of ten, decimal, and a radix of
-/// sixteen, hexadecimal, to give some common values. Arbitrary
-/// radices are supported.
-///
-/// `from_digit()` will return `None` if the input is not a digit in
-/// the given radix.
-///
-/// # Panics
-///
-/// Panics if given a radix larger than 36.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::char;
-///
-/// let c = char::from_digit(4, 10);
-///
-/// assert_eq!(Some('4'), c);
-///
-/// // Decimal 11 is a single digit in base 16
-/// let c = char::from_digit(11, 16);
-///
-/// assert_eq!(Some('b'), c);
-/// ```
-///
-/// Returning `None` when the input is not a digit:
-///
-/// ```
-/// use std::char;
-///
-/// let c = char::from_digit(20, 10);
-///
-/// assert_eq!(None, c);
-/// ```
-///
-/// Passing a large radix, causing a panic:
-///
-/// ```
-/// use std::thread;
-/// use std::char;
-///
-/// let result = thread::spawn(|| {
-///     // this panics
-///     let c = char::from_digit(1, 37);
-/// }).join();
-///
-/// assert!(result.is_err());
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn from_digit(num: u32, radix: u32) -> Option<char> {
-    if radix > 36 {
-        panic!("from_digit: radix is too high (maximum 36)");
-    }
-    if num < radix {
-        let num = num as u8;
-        if num < 10 {
-            Some((b'0' + num) as char)
-        } else {
-            Some((b'a' + num - 10) as char)
-        }
-    } else {
-        None
-    }
-}
-
-// NB: the stabilization and documentation for this trait is in
-// unicode/char.rs, not here
-#[allow(missing_docs)] // docs in libunicode/u_char.rs
-#[doc(hidden)]
-#[unstable(feature = "core_char_ext",
-           reason = "the stable interface is `impl char` in later crate",
-           issue = "32110")]
-pub trait CharExt {
-    #[stable(feature = "core", since = "1.6.0")]
-    fn is_digit(self, radix: u32) -> bool;
-    #[stable(feature = "core", since = "1.6.0")]
-    fn to_digit(self, radix: u32) -> Option<u32>;
-    #[stable(feature = "core", since = "1.6.0")]
-    fn escape_unicode(self) -> EscapeUnicode;
-    #[stable(feature = "core", since = "1.6.0")]
-    fn escape_default(self) -> EscapeDefault;
-    #[stable(feature = "char_escape_debug", since = "1.20.0")]
-    fn escape_debug(self) -> EscapeDebug;
-    #[stable(feature = "core", since = "1.6.0")]
-    fn len_utf8(self) -> usize;
-    #[stable(feature = "core", since = "1.6.0")]
-    fn len_utf16(self) -> usize;
-    #[stable(feature = "unicode_encode_char", since = "1.15.0")]
-    fn encode_utf8(self, dst: &mut [u8]) -> &mut str;
-    #[stable(feature = "unicode_encode_char", since = "1.15.0")]
-    fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16];
-}
-
-#[stable(feature = "core", since = "1.6.0")]
-impl CharExt for char {
-    #[inline]
-    fn is_digit(self, radix: u32) -> bool {
-        self.to_digit(radix).is_some()
-    }
-
-    #[inline]
-    fn to_digit(self, radix: u32) -> Option<u32> {
-        if radix > 36 {
-            panic!("to_digit: radix is too high (maximum 36)");
-        }
-        let val = match self {
-          '0' ... '9' => self as u32 - '0' as u32,
-          'a' ... 'z' => self as u32 - 'a' as u32 + 10,
-          'A' ... 'Z' => self as u32 - 'A' as u32 + 10,
-          _ => return None,
-        };
-        if val < radix { Some(val) }
-        else { None }
-    }
-
-    #[inline]
-    fn escape_unicode(self) -> EscapeUnicode {
-        let c = self as u32;
-
-        // or-ing 1 ensures that for c==0 the code computes that one
-        // digit should be printed and (which is the same) avoids the
-        // (31 - 32) underflow
-        let msb = 31 - (c | 1).leading_zeros();
-
-        // the index of the most significant hex digit
-        let ms_hex_digit = msb / 4;
-        EscapeUnicode {
-            c: self,
-            state: EscapeUnicodeState::Backslash,
-            hex_digit_idx: ms_hex_digit as usize,
-        }
-    }
-
-    #[inline]
-    fn escape_default(self) -> EscapeDefault {
-        let init_state = match self {
-            '\t' => EscapeDefaultState::Backslash('t'),
-            '\r' => EscapeDefaultState::Backslash('r'),
-            '\n' => EscapeDefaultState::Backslash('n'),
-            '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
-            '\x20' ... '\x7e' => EscapeDefaultState::Char(self),
-            _ => EscapeDefaultState::Unicode(self.escape_unicode())
-        };
-        EscapeDefault { state: init_state }
-    }
-
-    #[inline]
-    fn escape_debug(self) -> EscapeDebug {
-        let init_state = match self {
-            '\t' => EscapeDefaultState::Backslash('t'),
-            '\r' => EscapeDefaultState::Backslash('r'),
-            '\n' => EscapeDefaultState::Backslash('n'),
-            '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
-            c if is_printable(c) => EscapeDefaultState::Char(c),
-            c => EscapeDefaultState::Unicode(c.escape_unicode()),
-        };
-        EscapeDebug(EscapeDefault { state: init_state })
-    }
-
-    #[inline]
-    fn len_utf8(self) -> usize {
-        let code = self as u32;
-        if code < MAX_ONE_B {
-            1
-        } else if code < MAX_TWO_B {
-            2
-        } else if code < MAX_THREE_B {
-            3
-        } else {
-            4
-        }
-    }
-
-    #[inline]
-    fn len_utf16(self) -> usize {
-        let ch = self as u32;
-        if (ch & 0xFFFF) == ch { 1 } else { 2 }
-    }
-
-    #[inline]
-    fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
-        let code = self as u32;
-        unsafe {
-            let len =
-            if code < MAX_ONE_B && !dst.is_empty() {
-                *dst.get_unchecked_mut(0) = code as u8;
-                1
-            } else if code < MAX_TWO_B && dst.len() >= 2 {
-                *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
-                *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
-                2
-            } else if code < MAX_THREE_B && dst.len() >= 3  {
-                *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
-                *dst.get_unchecked_mut(1) = (code >>  6 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
-                3
-            } else if dst.len() >= 4 {
-                *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
-                *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(2) = (code >>  6 & 0x3F) as u8 | TAG_CONT;
-                *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
-                4
-            } else {
-                panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
-                    from_u32_unchecked(code).len_utf8(),
-                    code,
-                    dst.len())
-            };
-            from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
-        }
-    }
-
-    #[inline]
-    fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
-        let mut code = self as u32;
-        unsafe {
-            if (code & 0xFFFF) == code && !dst.is_empty() {
-                // The BMP falls through (assuming non-surrogate, as it should)
-                *dst.get_unchecked_mut(0) = code as u16;
-                slice::from_raw_parts_mut(dst.as_mut_ptr(), 1)
-            } else if dst.len() >= 2 {
-                // Supplementary planes break into surrogates.
-                code -= 0x1_0000;
-                *dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16);
-                *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF);
-                slice::from_raw_parts_mut(dst.as_mut_ptr(), 2)
-            } else {
-                panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
-                    from_u32_unchecked(code).len_utf16(),
-                    code,
-                    dst.len())
-            }
-        }
-    }
-}
-
-/// Returns an iterator that yields the hexadecimal Unicode escape of a
-/// character, as `char`s.
-///
-/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
-/// its documentation for more.
-///
-/// [`escape_unicode`]: ../../std/primitive.char.html#method.escape_unicode
-/// [`char`]: ../../std/primitive.char.html
-#[derive(Clone, Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct EscapeUnicode {
-    c: char,
-    state: EscapeUnicodeState,
-
-    // The index of the next hex digit to be printed (0 if none),
-    // i.e. the number of remaining hex digits to be printed;
-    // increasing from the least significant digit: 0x543210
-    hex_digit_idx: usize,
-}
-
-// The enum values are ordered so that their representation is the
-// same as the remaining length (besides the hexadecimal digits). This
-// likely makes `len()` a single load from memory) and inline-worth.
-#[derive(Clone, Debug)]
-enum EscapeUnicodeState {
-    Done,
-    RightBrace,
-    Value,
-    LeftBrace,
-    Type,
-    Backslash,
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for EscapeUnicode {
-    type Item = char;
-
-    fn next(&mut self) -> Option<char> {
-        match self.state {
-            EscapeUnicodeState::Backslash => {
-                self.state = EscapeUnicodeState::Type;
-                Some('\\')
-            }
-            EscapeUnicodeState::Type => {
-                self.state = EscapeUnicodeState::LeftBrace;
-                Some('u')
-            }
-            EscapeUnicodeState::LeftBrace => {
-                self.state = EscapeUnicodeState::Value;
-                Some('{')
-            }
-            EscapeUnicodeState::Value => {
-                let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf;
-                let c = from_digit(hex_digit, 16).unwrap();
-                if self.hex_digit_idx == 0 {
-                    self.state = EscapeUnicodeState::RightBrace;
-                } else {
-                    self.hex_digit_idx -= 1;
-                }
-                Some(c)
-            }
-            EscapeUnicodeState::RightBrace => {
-                self.state = EscapeUnicodeState::Done;
-                Some('}')
-            }
-            EscapeUnicodeState::Done => None,
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let n = self.len();
-        (n, Some(n))
-    }
-
-    #[inline]
-    fn count(self) -> usize {
-        self.len()
-    }
-
-    fn last(self) -> Option<char> {
-        match self.state {
-            EscapeUnicodeState::Done => None,
-
-            EscapeUnicodeState::RightBrace |
-            EscapeUnicodeState::Value |
-            EscapeUnicodeState::LeftBrace |
-            EscapeUnicodeState::Type |
-            EscapeUnicodeState::Backslash => Some('}'),
-        }
-    }
-}
-
-#[stable(feature = "exact_size_escape", since = "1.11.0")]
-impl ExactSizeIterator for EscapeUnicode {
-    #[inline]
-    fn len(&self) -> usize {
-        // The match is a single memory access with no branching
-        self.hex_digit_idx + match self.state {
-            EscapeUnicodeState::Done => 0,
-            EscapeUnicodeState::RightBrace => 1,
-            EscapeUnicodeState::Value => 2,
-            EscapeUnicodeState::LeftBrace => 3,
-            EscapeUnicodeState::Type => 4,
-            EscapeUnicodeState::Backslash => 5,
-        }
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl FusedIterator for EscapeUnicode {}
-
-#[stable(feature = "char_struct_display", since = "1.16.0")]
-impl fmt::Display for EscapeUnicode {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for c in self.clone() {
-            f.write_char(c)?;
-        }
-        Ok(())
-    }
-}
-
-/// An iterator that yields the literal escape code of a `char`.
-///
-/// This `struct` is created by the [`escape_default`] method on [`char`]. See
-/// its documentation for more.
-///
-/// [`escape_default`]: ../../std/primitive.char.html#method.escape_default
-/// [`char`]: ../../std/primitive.char.html
-#[derive(Clone, Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct EscapeDefault {
-    state: EscapeDefaultState
-}
-
-#[derive(Clone, Debug)]
-enum EscapeDefaultState {
-    Done,
-    Char(char),
-    Backslash(char),
-    Unicode(EscapeUnicode),
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for EscapeDefault {
-    type Item = char;
-
-    fn next(&mut self) -> Option<char> {
-        match self.state {
-            EscapeDefaultState::Backslash(c) => {
-                self.state = EscapeDefaultState::Char(c);
-                Some('\\')
-            }
-            EscapeDefaultState::Char(c) => {
-                self.state = EscapeDefaultState::Done;
-                Some(c)
-            }
-            EscapeDefaultState::Done => None,
-            EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let n = self.len();
-        (n, Some(n))
-    }
-
-    #[inline]
-    fn count(self) -> usize {
-        self.len()
-    }
-
-    fn nth(&mut self, n: usize) -> Option<char> {
-        match self.state {
-            EscapeDefaultState::Backslash(c) if n == 0 => {
-                self.state = EscapeDefaultState::Char(c);
-                Some('\\')
-            },
-            EscapeDefaultState::Backslash(c) if n == 1 => {
-                self.state = EscapeDefaultState::Done;
-                Some(c)
-            },
-            EscapeDefaultState::Backslash(_) => {
-                self.state = EscapeDefaultState::Done;
-                None
-            },
-            EscapeDefaultState::Char(c) => {
-                self.state = EscapeDefaultState::Done;
-
-                if n == 0 {
-                    Some(c)
-                } else {
-                    None
-                }
-            },
-            EscapeDefaultState::Done => return None,
-            EscapeDefaultState::Unicode(ref mut i) => return i.nth(n),
-        }
-    }
-
-    fn last(self) -> Option<char> {
-        match self.state {
-            EscapeDefaultState::Unicode(iter) => iter.last(),
-            EscapeDefaultState::Done => None,
-            EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c),
-        }
-    }
-}
-
-#[stable(feature = "exact_size_escape", since = "1.11.0")]
-impl ExactSizeIterator for EscapeDefault {
-    fn len(&self) -> usize {
-        match self.state {
-            EscapeDefaultState::Done => 0,
-            EscapeDefaultState::Char(_) => 1,
-            EscapeDefaultState::Backslash(_) => 2,
-            EscapeDefaultState::Unicode(ref iter) => iter.len(),
-        }
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl FusedIterator for EscapeDefault {}
-
-#[stable(feature = "char_struct_display", since = "1.16.0")]
-impl fmt::Display for EscapeDefault {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for c in self.clone() {
-            f.write_char(c)?;
-        }
-        Ok(())
-    }
-}
-
-/// An iterator that yields the literal escape code of a `char`.
-///
-/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
-/// documentation for more.
-///
-/// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug
-/// [`char`]: ../../std/primitive.char.html
-#[stable(feature = "char_escape_debug", since = "1.20.0")]
-#[derive(Clone, Debug)]
-pub struct EscapeDebug(EscapeDefault);
-
-#[stable(feature = "char_escape_debug", since = "1.20.0")]
-impl Iterator for EscapeDebug {
-    type Item = char;
-    fn next(&mut self) -> Option<char> { self.0.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
-}
-
-#[stable(feature = "char_escape_debug", since = "1.20.0")]
-impl ExactSizeIterator for EscapeDebug { }
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl FusedIterator for EscapeDebug {}
-
-#[stable(feature = "char_escape_debug", since = "1.20.0")]
-impl fmt::Display for EscapeDebug {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
-    }
-}
-
-
-
-/// An iterator over an iterator of bytes of the characters the bytes represent
-/// as UTF-8
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[derive(Clone, Debug)]
-pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>);
-
-/// Decodes an `Iterator` of bytes as UTF-8.
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[inline]
-pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> {
-    DecodeUtf8(i.into_iter().peekable())
-}
-
-/// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence.
-#[unstable(feature = "decode_utf8", issue = "33906")]
-#[derive(PartialEq, Eq, Debug)]
-pub struct InvalidSequence(());
-
-#[unstable(feature = "decode_utf8", issue = "33906")]
-impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
-    type Item = Result<char, InvalidSequence>;
-    #[inline]
-
-    fn next(&mut self) -> Option<Result<char, InvalidSequence>> {
-        self.0.next().map(|first_byte| {
-            // Emit InvalidSequence according to
-            // Unicode §5.22 Best Practice for U+FFFD Substitution
-            // http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630
-
-            // Roughly: consume at least one byte,
-            // then validate one byte at a time and stop before the first unexpected byte
-            // (which might be the valid start of the next byte sequence).
-
-            let mut code_point;
-            macro_rules! first_byte {
-                ($mask: expr) => {
-                    code_point = u32::from(first_byte & $mask)
-                }
-            }
-            macro_rules! continuation_byte {
-                () => { continuation_byte!(0x80...0xBF) };
-                ($range: pat) => {
-                    match self.0.peek() {
-                        Some(&byte @ $range) => {
-                            code_point = (code_point << 6) | u32::from(byte & 0b0011_1111);
-                            self.0.next();
-                        }
-                        _ => return Err(InvalidSequence(()))
-                    }
-                }
-            }
-
-            match first_byte {
-                0x00...0x7F => {
-                    first_byte!(0b1111_1111);
-                }
-                0xC2...0xDF => {
-                    first_byte!(0b0001_1111);
-                    continuation_byte!();
-                }
-                0xE0 => {
-                    first_byte!(0b0000_1111);
-                    continuation_byte!(0xA0...0xBF);  // 0x80...0x9F here are overlong
-                    continuation_byte!();
-                }
-                0xE1...0xEC | 0xEE...0xEF => {
-                    first_byte!(0b0000_1111);
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                0xED => {
-                    first_byte!(0b0000_1111);
-                    continuation_byte!(0x80...0x9F);  // 0xA0..0xBF here are surrogates
-                    continuation_byte!();
-                }
-                0xF0 => {
-                    first_byte!(0b0000_0111);
-                    continuation_byte!(0x90...0xBF);  // 0x80..0x8F here are overlong
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                0xF1...0xF3 => {
-                    first_byte!(0b0000_0111);
-                    continuation_byte!();
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                0xF4 => {
-                    first_byte!(0b0000_0111);
-                    continuation_byte!(0x80...0x8F);  // 0x90..0xBF here are beyond char::MAX
-                    continuation_byte!();
-                    continuation_byte!();
-                }
-                _ => return Err(InvalidSequence(()))  // Illegal first byte, overlong, or beyond MAX
-            }
-            unsafe {
-                Ok(from_u32_unchecked(code_point))
-            }
-        })
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (lower, upper) = self.0.size_hint();
-
-        // A code point is at most 4 bytes long.
-        let min_code_points = lower / 4;
-
-        (min_code_points, upper)
-    }
-}
-
-#[unstable(feature = "decode_utf8", issue = "33906")]
-impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {}
diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs
new file mode 100644
index 00000000000..150562a4a9b
--- /dev/null
+++ b/src/libcore/char/convert.rs
@@ -0,0 +1,304 @@
+// 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.
+
+//! Character conversions.
+
+use convert::TryFrom;
+use fmt;
+use mem::transmute;
+use str::FromStr;
+use super::MAX;
+
+/// Converts a `u32` to a `char`.
+///
+/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
+/// [`as`]:
+///
+/// ```
+/// let c = '💯';
+/// let i = c as u32;
+///
+/// assert_eq!(128175, i);
+/// ```
+///
+/// However, the reverse is not true: not all valid [`u32`]s are valid
+/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
+/// for a [`char`].
+///
+/// [`char`]: ../../std/primitive.char.html
+/// [`u32`]: ../../std/primitive.u32.html
+/// [`as`]: ../../book/first-edition/casting-between-types.html#as
+///
+/// For an unsafe version of this function which ignores these checks, see
+/// [`from_u32_unchecked`].
+///
+/// [`from_u32_unchecked`]: fn.from_u32_unchecked.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_u32(0x2764);
+///
+/// assert_eq!(Some('❤'), c);
+/// ```
+///
+/// Returning `None` when the input is not a valid [`char`]:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_u32(0x110000);
+///
+/// assert_eq!(None, c);
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn from_u32(i: u32) -> Option<char> {
+    char::try_from(i).ok()
+}
+
+/// Converts a `u32` to a `char`, ignoring validity.
+///
+/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
+/// [`as`]:
+///
+/// ```
+/// let c = '💯';
+/// let i = c as u32;
+///
+/// assert_eq!(128175, i);
+/// ```
+///
+/// However, the reverse is not true: not all valid [`u32`]s are valid
+/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
+/// [`char`], possibly creating an invalid one.
+///
+/// [`char`]: ../../std/primitive.char.html
+/// [`u32`]: ../../std/primitive.u32.html
+/// [`as`]: ../../book/first-edition/casting-between-types.html#as
+///
+/// # Safety
+///
+/// This function is unsafe, as it may construct invalid `char` values.
+///
+/// For a safe version of this function, see the [`from_u32`] function.
+///
+/// [`from_u32`]: fn.from_u32.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char;
+///
+/// let c = unsafe { char::from_u32_unchecked(0x2764) };
+///
+/// assert_eq!('❤', c);
+/// ```
+#[inline]
+#[stable(feature = "char_from_unchecked", since = "1.5.0")]
+pub unsafe fn from_u32_unchecked(i: u32) -> char {
+    transmute(i)
+}
+
+#[stable(feature = "char_convert", since = "1.13.0")]
+impl From<char> for u32 {
+    #[inline]
+    fn from(c: char) -> Self {
+        c as u32
+    }
+}
+
+/// Maps a byte in 0x00...0xFF to a `char` whose code point has the same value, in U+0000 to U+00FF.
+///
+/// Unicode is designed such that this effectively decodes bytes
+/// with the character encoding that IANA calls ISO-8859-1.
+/// This encoding is compatible with ASCII.
+///
+/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
+/// which leaves some "blanks", byte values that are not assigned to any character.
+/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
+///
+/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
+/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
+/// to punctuation and various Latin characters.
+///
+/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
+/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
+/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
+/// C0 and C1 control codes.
+#[stable(feature = "char_convert", since = "1.13.0")]
+impl From<u8> for char {
+    #[inline]
+    fn from(i: u8) -> Self {
+        i as char
+    }
+}
+
+
+/// An error which can be returned when parsing a char.
+#[stable(feature = "char_from_str", since = "1.20.0")]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ParseCharError {
+    kind: CharErrorKind,
+}
+
+impl ParseCharError {
+    #[unstable(feature = "char_error_internals",
+               reason = "this method should not be available publicly",
+               issue = "0")]
+    #[doc(hidden)]
+    pub fn __description(&self) -> &str {
+        match self.kind {
+            CharErrorKind::EmptyString => {
+                "cannot parse char from empty string"
+            },
+            CharErrorKind::TooManyChars => "too many characters in string"
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum CharErrorKind {
+    EmptyString,
+    TooManyChars,
+}
+
+#[stable(feature = "char_from_str", since = "1.20.0")]
+impl fmt::Display for ParseCharError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.__description().fmt(f)
+    }
+}
+
+
+#[stable(feature = "char_from_str", since = "1.20.0")]
+impl FromStr for char {
+    type Err = ParseCharError;
+
+    #[inline]
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let mut chars = s.chars();
+        match (chars.next(), chars.next()) {
+            (None, _) => {
+                Err(ParseCharError { kind: CharErrorKind::EmptyString })
+            },
+            (Some(c), None) => Ok(c),
+            _ => {
+                Err(ParseCharError { kind: CharErrorKind::TooManyChars })
+            }
+        }
+    }
+}
+
+
+#[stable(feature = "try_from", since = "1.26.0")]
+impl TryFrom<u32> for char {
+    type Error = CharTryFromError;
+
+    #[inline]
+    fn try_from(i: u32) -> Result<Self, Self::Error> {
+        if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
+            Err(CharTryFromError(()))
+        } else {
+            Ok(unsafe { from_u32_unchecked(i) })
+        }
+    }
+}
+
+/// The error type returned when a conversion from u32 to char fails.
+#[stable(feature = "try_from", since = "1.26.0")]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct CharTryFromError(());
+
+#[stable(feature = "try_from", since = "1.26.0")]
+impl fmt::Display for CharTryFromError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "converted integer out of range for `char`".fmt(f)
+    }
+}
+
+/// Converts a digit in the given radix to a `char`.
+///
+/// A 'radix' here is sometimes also called a 'base'. A radix of two
+/// indicates a binary number, a radix of ten, decimal, and a radix of
+/// sixteen, hexadecimal, to give some common values. Arbitrary
+/// radices are supported.
+///
+/// `from_digit()` will return `None` if the input is not a digit in
+/// the given radix.
+///
+/// # Panics
+///
+/// Panics if given a radix larger than 36.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_digit(4, 10);
+///
+/// assert_eq!(Some('4'), c);
+///
+/// // Decimal 11 is a single digit in base 16
+/// let c = char::from_digit(11, 16);
+///
+/// assert_eq!(Some('b'), c);
+/// ```
+///
+/// Returning `None` when the input is not a digit:
+///
+/// ```
+/// use std::char;
+///
+/// let c = char::from_digit(20, 10);
+///
+/// assert_eq!(None, c);
+/// ```
+///
+/// Passing a large radix, causing a panic:
+///
+/// ```
+/// use std::thread;
+/// use std::char;
+///
+/// let result = thread::spawn(|| {
+///     // this panics
+///     let c = char::from_digit(1, 37);
+/// }).join();
+///
+/// assert!(result.is_err());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn from_digit(num: u32, radix: u32) -> Option<char> {
+    if radix > 36 {
+        panic!("from_digit: radix is too high (maximum 36)");
+    }
+    if num < radix {
+        let num = num as u8;
+        if num < 10 {
+            Some((b'0' + num) as char)
+        } else {
+            Some((b'a' + num - 10) as char)
+        }
+    } else {
+        None
+    }
+}
+
diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs
new file mode 100644
index 00000000000..48b531104f8
--- /dev/null
+++ b/src/libcore/char/decode.rs
@@ -0,0 +1,259 @@
+// 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.
+
+//! UTF-8 and UTF-16 decoding iterators
+
+use fmt;
+use iter::FusedIterator;
+use super::from_u32_unchecked;
+
+/// An iterator over an iterator of bytes of the characters the bytes represent
+/// as UTF-8
+#[unstable(feature = "decode_utf8", issue = "33906")]
+#[derive(Clone, Debug)]
+pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>);
+
+/// Decodes an `Iterator` of bytes as UTF-8.
+#[unstable(feature = "decode_utf8", issue = "33906")]
+#[inline]
+pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> {
+    DecodeUtf8(i.into_iter().peekable())
+}
+
+/// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence.
+#[unstable(feature = "decode_utf8", issue = "33906")]
+#[derive(PartialEq, Eq, Debug)]
+pub struct InvalidSequence(());
+
+#[unstable(feature = "decode_utf8", issue = "33906")]
+impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
+    type Item = Result<char, InvalidSequence>;
+    #[inline]
+
+    fn next(&mut self) -> Option<Result<char, InvalidSequence>> {
+        self.0.next().map(|first_byte| {
+            // Emit InvalidSequence according to
+            // Unicode §5.22 Best Practice for U+FFFD Substitution
+            // http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630
+
+            // Roughly: consume at least one byte,
+            // then validate one byte at a time and stop before the first unexpected byte
+            // (which might be the valid start of the next byte sequence).
+
+            let mut code_point;
+            macro_rules! first_byte {
+                ($mask: expr) => {
+                    code_point = u32::from(first_byte & $mask)
+                }
+            }
+            macro_rules! continuation_byte {
+                () => { continuation_byte!(0x80...0xBF) };
+                ($range: pat) => {
+                    match self.0.peek() {
+                        Some(&byte @ $range) => {
+                            code_point = (code_point << 6) | u32::from(byte & 0b0011_1111);
+                            self.0.next();
+                        }
+                        _ => return Err(InvalidSequence(()))
+                    }
+                }
+            }
+
+            match first_byte {
+                0x00...0x7F => {
+                    first_byte!(0b1111_1111);
+                }
+                0xC2...0xDF => {
+                    first_byte!(0b0001_1111);
+                    continuation_byte!();
+                }
+                0xE0 => {
+                    first_byte!(0b0000_1111);
+                    continuation_byte!(0xA0...0xBF);  // 0x80...0x9F here are overlong
+                    continuation_byte!();
+                }
+                0xE1...0xEC | 0xEE...0xEF => {
+                    first_byte!(0b0000_1111);
+                    continuation_byte!();
+                    continuation_byte!();
+                }
+                0xED => {
+                    first_byte!(0b0000_1111);
+                    continuation_byte!(0x80...0x9F);  // 0xA0..0xBF here are surrogates
+                    continuation_byte!();
+                }
+                0xF0 => {
+                    first_byte!(0b0000_0111);
+                    continuation_byte!(0x90...0xBF);  // 0x80..0x8F here are overlong
+                    continuation_byte!();
+                    continuation_byte!();
+                }
+                0xF1...0xF3 => {
+                    first_byte!(0b0000_0111);
+                    continuation_byte!();
+                    continuation_byte!();
+                    continuation_byte!();
+                }
+                0xF4 => {
+                    first_byte!(0b0000_0111);
+                    continuation_byte!(0x80...0x8F);  // 0x90..0xBF here are beyond char::MAX
+                    continuation_byte!();
+                    continuation_byte!();
+                }
+                _ => return Err(InvalidSequence(()))  // Illegal first byte, overlong, or beyond MAX
+            }
+            unsafe {
+                Ok(from_u32_unchecked(code_point))
+            }
+        })
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (lower, upper) = self.0.size_hint();
+
+        // A code point is at most 4 bytes long.
+        let min_code_points = lower / 4;
+
+        (min_code_points, upper)
+    }
+}
+
+#[unstable(feature = "decode_utf8", issue = "33906")]
+impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {}
+
+/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+#[derive(Clone, Debug)]
+pub struct DecodeUtf16<I>
+    where I: Iterator<Item = u16>
+{
+    iter: I,
+    buf: Option<u16>,
+}
+
+/// An error that can be returned when decoding UTF-16 code points.
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct DecodeUtf16Error {
+    code: u16,
+}
+
+/// Create an iterator over the UTF-16 encoded code points in `iter`,
+/// returning unpaired surrogates as `Err`s.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::char::decode_utf16;
+///
+/// fn main() {
+///     // 𝄞mus<invalid>ic<invalid>
+///     let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
+///              0x0073, 0xDD1E, 0x0069, 0x0063,
+///              0xD834];
+///
+///     assert_eq!(decode_utf16(v.iter().cloned())
+///                            .map(|r| r.map_err(|e| e.unpaired_surrogate()))
+///                            .collect::<Vec<_>>(),
+///                vec![Ok('𝄞'),
+///                     Ok('m'), Ok('u'), Ok('s'),
+///                     Err(0xDD1E),
+///                     Ok('i'), Ok('c'),
+///                     Err(0xD834)]);
+/// }
+/// ```
+///
+/// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
+///
+/// ```
+/// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
+///
+/// fn main() {
+///     // 𝄞mus<invalid>ic<invalid>
+///     let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
+///              0x0073, 0xDD1E, 0x0069, 0x0063,
+///              0xD834];
+///
+///     assert_eq!(decode_utf16(v.iter().cloned())
+///                    .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
+///                    .collect::<String>(),
+///                "𝄞mus�ic�");
+/// }
+/// ```
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+#[inline]
+pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
+    DecodeUtf16 {
+        iter: iter.into_iter(),
+        buf: None,
+    }
+}
+
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
+    type Item = Result<char, DecodeUtf16Error>;
+
+    fn next(&mut self) -> Option<Result<char, DecodeUtf16Error>> {
+        let u = match self.buf.take() {
+            Some(buf) => buf,
+            None => self.iter.next()?
+        };
+
+        if u < 0xD800 || 0xDFFF < u {
+            // not a surrogate
+            Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
+        } else if u >= 0xDC00 {
+            // a trailing surrogate
+            Some(Err(DecodeUtf16Error { code: u }))
+        } else {
+            let u2 = match self.iter.next() {
+                Some(u2) => u2,
+                // eof
+                None => return Some(Err(DecodeUtf16Error { code: u })),
+            };
+            if u2 < 0xDC00 || u2 > 0xDFFF {
+                // not a trailing surrogate so we're not a valid
+                // surrogate pair, so rewind to redecode u2 next time.
+                self.buf = Some(u2);
+                return Some(Err(DecodeUtf16Error { code: u }));
+            }
+
+            // all ok, so lets decode it.
+            let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
+            Some(Ok(unsafe { from_u32_unchecked(c) }))
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (low, high) = self.iter.size_hint();
+        // we could be entirely valid surrogates (2 elements per
+        // char), or entirely non-surrogates (1 element per char)
+        (low / 2, high)
+    }
+}
+
+impl DecodeUtf16Error {
+    /// Returns the unpaired surrogate which caused this error.
+    #[stable(feature = "decode_utf16", since = "1.9.0")]
+    pub fn unpaired_surrogate(&self) -> u16 {
+        self.code
+    }
+}
+
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+impl fmt::Display for DecodeUtf16Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "unpaired surrogate found: {:x}", self.code)
+    }
+}
diff --git a/src/libstd_unicode/char.rs b/src/libcore/char/methods.rs
index 33e47ade8cb..374adafef64 100644
--- a/src/libstd_unicode/char.rs
+++ b/src/libcore/char/methods.rs
@@ -8,169 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! A character type.
-//!
-//! The `char` type represents a single character. More specifically, since
-//! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
-//! scalar value]', which is similar to, but not the same as, a '[Unicode code
-//! point]'.
-//!
-//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
-//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
-//!
-//! This module exists for technical reasons, the primary documentation for
-//! `char` is directly on [the `char` primitive type](../../std/primitive.char.html)
-//! itself.
-//!
-//! This module is the home of the iterator implementations for the iterators
-//! implemented on `char`, as well as some useful constants and conversion
-//! functions that convert various types to `char`.
+//! impl char {}
 
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use core::char::CharExt as C;
-use core::iter::FusedIterator;
-use core::fmt::{self, Write};
-use tables::{conversions, derived_property, general_category, property};
-
-// stable re-exports
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::char::{MAX, from_digit, from_u32, from_u32_unchecked};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode};
-#[stable(feature = "char_from_str", since = "1.20.0")]
-pub use core::char::ParseCharError;
-
-// unstable re-exports
-#[stable(feature = "try_from", since = "1.26.0")]
-pub use core::char::CharTryFromError;
-#[unstable(feature = "decode_utf8", issue = "33906")]
-pub use core::char::{DecodeUtf8, decode_utf8};
-#[unstable(feature = "unicode", issue = "27783")]
-pub use tables::{UNICODE_VERSION};
-#[unstable(feature = "unicode", issue = "27783")]
-pub use version::UnicodeVersion;
-
-/// Returns an iterator that yields the lowercase equivalent of a `char`.
-///
-/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
-/// its documentation for more.
-///
-/// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase
-/// [`char`]: ../../std/primitive.char.html
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Debug, Clone)]
-pub struct ToLowercase(CaseMappingIter);
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for ToLowercase {
-    type Item = char;
-    fn next(&mut self) -> Option<char> {
-        self.0.next()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl FusedIterator for ToLowercase {}
-
-/// Returns an iterator that yields the uppercase equivalent of a `char`.
-///
-/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
-/// its documentation for more.
-///
-/// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase
-/// [`char`]: ../../std/primitive.char.html
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Debug, Clone)]
-pub struct ToUppercase(CaseMappingIter);
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for ToUppercase {
-    type Item = char;
-    fn next(&mut self) -> Option<char> {
-        self.0.next()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl FusedIterator for ToUppercase {}
-
-#[derive(Debug, Clone)]
-enum CaseMappingIter {
-    Three(char, char, char),
-    Two(char, char),
-    One(char),
-    Zero,
-}
-
-impl CaseMappingIter {
-    fn new(chars: [char; 3]) -> CaseMappingIter {
-        if chars[2] == '\0' {
-            if chars[1] == '\0' {
-                CaseMappingIter::One(chars[0])  // Including if chars[0] == '\0'
-            } else {
-                CaseMappingIter::Two(chars[0], chars[1])
-            }
-        } else {
-            CaseMappingIter::Three(chars[0], chars[1], chars[2])
-        }
-    }
-}
-
-impl Iterator for CaseMappingIter {
-    type Item = char;
-    fn next(&mut self) -> Option<char> {
-        match *self {
-            CaseMappingIter::Three(a, b, c) => {
-                *self = CaseMappingIter::Two(b, c);
-                Some(a)
-            }
-            CaseMappingIter::Two(b, c) => {
-                *self = CaseMappingIter::One(c);
-                Some(b)
-            }
-            CaseMappingIter::One(c) => {
-                *self = CaseMappingIter::Zero;
-                Some(c)
-            }
-            CaseMappingIter::Zero => None,
-        }
-    }
-}
-
-impl fmt::Display for CaseMappingIter {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            CaseMappingIter::Three(a, b, c) => {
-                f.write_char(a)?;
-                f.write_char(b)?;
-                f.write_char(c)
-            }
-            CaseMappingIter::Two(b, c) => {
-                f.write_char(b)?;
-                f.write_char(c)
-            }
-            CaseMappingIter::One(c) => {
-                f.write_char(c)
-            }
-            CaseMappingIter::Zero => Ok(()),
-        }
-    }
-}
-
-#[stable(feature = "char_struct_display", since = "1.16.0")]
-impl fmt::Display for ToLowercase {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
-    }
-}
-
-#[stable(feature = "char_struct_display", since = "1.16.0")]
-impl fmt::Display for ToUppercase {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
-    }
-}
+use slice;
+use str::from_utf8_unchecked_mut;
+use super::*;
+use unicode::printable::is_printable;
+use unicode::tables::{conversions, derived_property, general_category, property};
 
 #[lang = "char"]
 impl char {
@@ -223,7 +67,7 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_digit(self, radix: u32) -> bool {
-        C::is_digit(self, radix)
+        self.to_digit(radix).is_some()
     }
 
     /// Converts a `char` to a digit in the given radix.
@@ -277,7 +121,17 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_digit(self, radix: u32) -> Option<u32> {
-        C::to_digit(self, radix)
+        if radix > 36 {
+            panic!("to_digit: radix is too high (maximum 36)");
+        }
+        let val = match self {
+          '0' ... '9' => self as u32 - '0' as u32,
+          'a' ... 'z' => self as u32 - 'a' as u32 + 10,
+          'A' ... 'Z' => self as u32 - 'A' as u32 + 10,
+          _ => return None,
+        };
+        if val < radix { Some(val) }
+        else { None }
     }
 
     /// Returns an iterator that yields the hexadecimal Unicode escape of a
@@ -317,7 +171,20 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn escape_unicode(self) -> EscapeUnicode {
-        C::escape_unicode(self)
+        let c = self as u32;
+
+        // or-ing 1 ensures that for c==0 the code computes that one
+        // digit should be printed and (which is the same) avoids the
+        // (31 - 32) underflow
+        let msb = 31 - (c | 1).leading_zeros();
+
+        // the index of the most significant hex digit
+        let ms_hex_digit = msb / 4;
+        EscapeUnicode {
+            c: self,
+            state: EscapeUnicodeState::Backslash,
+            hex_digit_idx: ms_hex_digit as usize,
+        }
     }
 
     /// Returns an iterator that yields the literal escape code of a character
@@ -357,7 +224,15 @@ impl char {
     #[stable(feature = "char_escape_debug", since = "1.20.0")]
     #[inline]
     pub fn escape_debug(self) -> EscapeDebug {
-        C::escape_debug(self)
+        let init_state = match self {
+            '\t' => EscapeDefaultState::Backslash('t'),
+            '\r' => EscapeDefaultState::Backslash('r'),
+            '\n' => EscapeDefaultState::Backslash('n'),
+            '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
+            c if is_printable(c) => EscapeDefaultState::Char(c),
+            c => EscapeDefaultState::Unicode(c.escape_unicode()),
+        };
+        EscapeDebug(EscapeDefault { state: init_state })
     }
 
     /// Returns an iterator that yields the literal escape code of a character
@@ -412,7 +287,15 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn escape_default(self) -> EscapeDefault {
-        C::escape_default(self)
+        let init_state = match self {
+            '\t' => EscapeDefaultState::Backslash('t'),
+            '\r' => EscapeDefaultState::Backslash('r'),
+            '\n' => EscapeDefaultState::Backslash('n'),
+            '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
+            '\x20' ... '\x7e' => EscapeDefaultState::Char(self),
+            _ => EscapeDefaultState::Unicode(self.escape_unicode())
+        };
+        EscapeDefault { state: init_state }
     }
 
     /// Returns the number of bytes this `char` would need if encoded in UTF-8.
@@ -463,7 +346,16 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn len_utf8(self) -> usize {
-        C::len_utf8(self)
+        let code = self as u32;
+        if code < MAX_ONE_B {
+            1
+        } else if code < MAX_TWO_B {
+            2
+        } else if code < MAX_THREE_B {
+            3
+        } else {
+            4
+        }
     }
 
     /// Returns the number of 16-bit code units this `char` would need if
@@ -488,7 +380,8 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn len_utf16(self) -> usize {
-        C::len_utf16(self)
+        let ch = self as u32;
+        if (ch & 0xFFFF) == ch { 1 } else { 2 }
     }
 
     /// Encodes this character as UTF-8 into the provided byte buffer,
@@ -530,7 +423,35 @@ impl char {
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
     #[inline]
     pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
-        C::encode_utf8(self, dst)
+        let code = self as u32;
+        unsafe {
+            let len =
+            if code < MAX_ONE_B && !dst.is_empty() {
+                *dst.get_unchecked_mut(0) = code as u8;
+                1
+            } else if code < MAX_TWO_B && dst.len() >= 2 {
+                *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
+                *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
+                2
+            } else if code < MAX_THREE_B && dst.len() >= 3  {
+                *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
+                *dst.get_unchecked_mut(1) = (code >>  6 & 0x3F) as u8 | TAG_CONT;
+                *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
+                3
+            } else if dst.len() >= 4 {
+                *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
+                *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
+                *dst.get_unchecked_mut(2) = (code >>  6 & 0x3F) as u8 | TAG_CONT;
+                *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
+                4
+            } else {
+                panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
+                    from_u32_unchecked(code).len_utf8(),
+                    code,
+                    dst.len())
+            };
+            from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
+        }
     }
 
     /// Encodes this character as UTF-16 into the provided `u16` buffer,
@@ -570,7 +491,25 @@ impl char {
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
     #[inline]
     pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
-        C::encode_utf16(self, dst)
+        let mut code = self as u32;
+        unsafe {
+            if (code & 0xFFFF) == code && !dst.is_empty() {
+                // The BMP falls through (assuming non-surrogate, as it should)
+                *dst.get_unchecked_mut(0) = code as u16;
+                slice::from_raw_parts_mut(dst.as_mut_ptr(), 1)
+            } else if dst.len() >= 2 {
+                // Supplementary planes break into surrogates.
+                code -= 0x1_0000;
+                *dst.get_unchecked_mut(0) = 0xD800 | ((code >> 10) as u16);
+                *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF);
+                slice::from_raw_parts_mut(dst.as_mut_ptr(), 2)
+            } else {
+                panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
+                    from_u32_unchecked(code).len_utf16(),
+                    code,
+                    dst.len())
+            }
+        }
     }
 
     /// Returns true if this `char` is an alphabetic code point, and false if not.
@@ -1452,140 +1391,3 @@ impl char {
         self.is_ascii() && (*self as u8).is_ascii_control()
     }
 }
-
-/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-#[derive(Clone, Debug)]
-pub struct DecodeUtf16<I>
-    where I: Iterator<Item = u16>
-{
-    iter: I,
-    buf: Option<u16>,
-}
-
-/// An error that can be returned when decoding UTF-16 code points.
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct DecodeUtf16Error {
-    code: u16,
-}
-
-/// Create an iterator over the UTF-16 encoded code points in `iter`,
-/// returning unpaired surrogates as `Err`s.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::char::decode_utf16;
-///
-/// fn main() {
-///     // 𝄞mus<invalid>ic<invalid>
-///     let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
-///              0x0073, 0xDD1E, 0x0069, 0x0063,
-///              0xD834];
-///
-///     assert_eq!(decode_utf16(v.iter().cloned())
-///                            .map(|r| r.map_err(|e| e.unpaired_surrogate()))
-///                            .collect::<Vec<_>>(),
-///                vec![Ok('𝄞'),
-///                     Ok('m'), Ok('u'), Ok('s'),
-///                     Err(0xDD1E),
-///                     Ok('i'), Ok('c'),
-///                     Err(0xD834)]);
-/// }
-/// ```
-///
-/// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
-///
-/// ```
-/// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
-///
-/// fn main() {
-///     // 𝄞mus<invalid>ic<invalid>
-///     let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
-///              0x0073, 0xDD1E, 0x0069, 0x0063,
-///              0xD834];
-///
-///     assert_eq!(decode_utf16(v.iter().cloned())
-///                    .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-///                    .collect::<String>(),
-///                "𝄞mus�ic�");
-/// }
-/// ```
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-#[inline]
-pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
-    DecodeUtf16 {
-        iter: iter.into_iter(),
-        buf: None,
-    }
-}
-
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
-    type Item = Result<char, DecodeUtf16Error>;
-
-    fn next(&mut self) -> Option<Result<char, DecodeUtf16Error>> {
-        let u = match self.buf.take() {
-            Some(buf) => buf,
-            None => self.iter.next()?
-        };
-
-        if u < 0xD800 || 0xDFFF < u {
-            // not a surrogate
-            Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
-        } else if u >= 0xDC00 {
-            // a trailing surrogate
-            Some(Err(DecodeUtf16Error { code: u }))
-        } else {
-            let u2 = match self.iter.next() {
-                Some(u2) => u2,
-                // eof
-                None => return Some(Err(DecodeUtf16Error { code: u })),
-            };
-            if u2 < 0xDC00 || u2 > 0xDFFF {
-                // not a trailing surrogate so we're not a valid
-                // surrogate pair, so rewind to redecode u2 next time.
-                self.buf = Some(u2);
-                return Some(Err(DecodeUtf16Error { code: u }));
-            }
-
-            // all ok, so lets decode it.
-            let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
-            Some(Ok(unsafe { from_u32_unchecked(c) }))
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (low, high) = self.iter.size_hint();
-        // we could be entirely valid surrogates (2 elements per
-        // char), or entirely non-surrogates (1 element per char)
-        (low / 2, high)
-    }
-}
-
-impl DecodeUtf16Error {
-    /// Returns the unpaired surrogate which caused this error.
-    #[stable(feature = "decode_utf16", since = "1.9.0")]
-    pub fn unpaired_surrogate(&self) -> u16 {
-        self.code
-    }
-}
-
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-impl fmt::Display for DecodeUtf16Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "unpaired surrogate found: {:x}", self.code)
-    }
-}
-
-/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
-/// decoding error.
-///
-/// It can occur, for example, when giving ill-formed UTF-8 bytes to
-/// [`String::from_utf8_lossy`](../../std/string/struct.String.html#method.from_utf8_lossy).
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs
new file mode 100644
index 00000000000..9edc0c88756
--- /dev/null
+++ b/src/libcore/char/mod.rs
@@ -0,0 +1,506 @@
+// 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.
+
+//! A character type.
+//!
+//! The `char` type represents a single character. More specifically, since
+//! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
+//! scalar value]', which is similar to, but not the same as, a '[Unicode code
+//! point]'.
+//!
+//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
+//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
+//!
+//! This module exists for technical reasons, the primary documentation for
+//! `char` is directly on [the `char` primitive type](../../std/primitive.char.html)
+//! itself.
+//!
+//! This module is the home of the iterator implementations for the iterators
+//! implemented on `char`, as well as some useful constants and conversion
+//! functions that convert various types to `char`.
+
+#![allow(non_snake_case)]
+#![stable(feature = "core_char", since = "1.2.0")]
+
+mod convert;
+mod decode;
+mod methods;
+
+// stable re-exports
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::convert::{from_u32, from_digit};
+#[stable(feature = "char_from_unchecked", since = "1.5.0")]
+pub use self::convert::from_u32_unchecked;
+#[stable(feature = "char_from_str", since = "1.20.0")]
+pub use self::convert::ParseCharError;
+#[stable(feature = "try_from", since = "1.26.0")]
+pub use self::convert::CharTryFromError;
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
+
+// unstable re-exports
+#[unstable(feature = "unicode_version", issue = "49726")]
+pub use unicode::tables::UNICODE_VERSION;
+#[unstable(feature = "unicode_version", issue = "49726")]
+pub use unicode::version::UnicodeVersion;
+#[unstable(feature = "decode_utf8", issue = "33906")]
+pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence};
+
+use fmt::{self, Write};
+use iter::FusedIterator;
+
+// UTF-8 ranges and tags for encoding characters
+const TAG_CONT: u8    = 0b1000_0000;
+const TAG_TWO_B: u8   = 0b1100_0000;
+const TAG_THREE_B: u8 = 0b1110_0000;
+const TAG_FOUR_B: u8  = 0b1111_0000;
+const MAX_ONE_B: u32   =     0x80;
+const MAX_TWO_B: u32   =    0x800;
+const MAX_THREE_B: u32 =  0x10000;
+
+/*
+    Lu  Uppercase_Letter        an uppercase letter
+    Ll  Lowercase_Letter        a lowercase letter
+    Lt  Titlecase_Letter        a digraphic character, with first part uppercase
+    Lm  Modifier_Letter         a modifier letter
+    Lo  Other_Letter            other letters, including syllables and ideographs
+    Mn  Nonspacing_Mark         a nonspacing combining mark (zero advance width)
+    Mc  Spacing_Mark            a spacing combining mark (positive advance width)
+    Me  Enclosing_Mark          an enclosing combining mark
+    Nd  Decimal_Number          a decimal digit
+    Nl  Letter_Number           a letterlike numeric character
+    No  Other_Number            a numeric character of other type
+    Pc  Connector_Punctuation   a connecting punctuation mark, like a tie
+    Pd  Dash_Punctuation        a dash or hyphen punctuation mark
+    Ps  Open_Punctuation        an opening punctuation mark (of a pair)
+    Pe  Close_Punctuation       a closing punctuation mark (of a pair)
+    Pi  Initial_Punctuation     an initial quotation mark
+    Pf  Final_Punctuation       a final quotation mark
+    Po  Other_Punctuation       a punctuation mark of other type
+    Sm  Math_Symbol             a symbol of primarily mathematical use
+    Sc  Currency_Symbol         a currency sign
+    Sk  Modifier_Symbol         a non-letterlike modifier symbol
+    So  Other_Symbol            a symbol of other type
+    Zs  Space_Separator         a space character (of various non-zero widths)
+    Zl  Line_Separator          U+2028 LINE SEPARATOR only
+    Zp  Paragraph_Separator     U+2029 PARAGRAPH SEPARATOR only
+    Cc  Control                 a C0 or C1 control code
+    Cf  Format                  a format control character
+    Cs  Surrogate               a surrogate code point
+    Co  Private_Use             a private-use character
+    Cn  Unassigned              a reserved unassigned code point or a noncharacter
+*/
+
+/// The highest valid code point a `char` can have.
+///
+/// A [`char`] is a [Unicode Scalar Value], which means that it is a [Code
+/// Point], but only ones within a certain range. `MAX` is the highest valid
+/// code point that's a valid [Unicode Scalar Value].
+///
+/// [`char`]: ../../std/primitive.char.html
+/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
+/// [Code Point]: http://www.unicode.org/glossary/#code_point
+#[stable(feature = "rust1", since = "1.0.0")]
+pub const MAX: char = '\u{10ffff}';
+
+/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
+/// decoding error.
+///
+/// It can occur, for example, when giving ill-formed UTF-8 bytes to
+/// [`String::from_utf8_lossy`](../../std/string/struct.String.html#method.from_utf8_lossy).
+#[stable(feature = "decode_utf16", since = "1.9.0")]
+pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
+
+/// Returns an iterator that yields the hexadecimal Unicode escape of a
+/// character, as `char`s.
+///
+/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
+/// its documentation for more.
+///
+/// [`escape_unicode`]: ../../std/primitive.char.html#method.escape_unicode
+/// [`char`]: ../../std/primitive.char.html
+#[derive(Clone, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct EscapeUnicode {
+    c: char,
+    state: EscapeUnicodeState,
+
+    // The index of the next hex digit to be printed (0 if none),
+    // i.e. the number of remaining hex digits to be printed;
+    // increasing from the least significant digit: 0x543210
+    hex_digit_idx: usize,
+}
+
+// The enum values are ordered so that their representation is the
+// same as the remaining length (besides the hexadecimal digits). This
+// likely makes `len()` a single load from memory) and inline-worth.
+#[derive(Clone, Debug)]
+enum EscapeUnicodeState {
+    Done,
+    RightBrace,
+    Value,
+    LeftBrace,
+    Type,
+    Backslash,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EscapeUnicode {
+    type Item = char;
+
+    fn next(&mut self) -> Option<char> {
+        match self.state {
+            EscapeUnicodeState::Backslash => {
+                self.state = EscapeUnicodeState::Type;
+                Some('\\')
+            }
+            EscapeUnicodeState::Type => {
+                self.state = EscapeUnicodeState::LeftBrace;
+                Some('u')
+            }
+            EscapeUnicodeState::LeftBrace => {
+                self.state = EscapeUnicodeState::Value;
+                Some('{')
+            }
+            EscapeUnicodeState::Value => {
+                let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf;
+                let c = from_digit(hex_digit, 16).unwrap();
+                if self.hex_digit_idx == 0 {
+                    self.state = EscapeUnicodeState::RightBrace;
+                } else {
+                    self.hex_digit_idx -= 1;
+                }
+                Some(c)
+            }
+            EscapeUnicodeState::RightBrace => {
+                self.state = EscapeUnicodeState::Done;
+                Some('}')
+            }
+            EscapeUnicodeState::Done => None,
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let n = self.len();
+        (n, Some(n))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    fn last(self) -> Option<char> {
+        match self.state {
+            EscapeUnicodeState::Done => None,
+
+            EscapeUnicodeState::RightBrace |
+            EscapeUnicodeState::Value |
+            EscapeUnicodeState::LeftBrace |
+            EscapeUnicodeState::Type |
+            EscapeUnicodeState::Backslash => Some('}'),
+        }
+    }
+}
+
+#[stable(feature = "exact_size_escape", since = "1.11.0")]
+impl ExactSizeIterator for EscapeUnicode {
+    #[inline]
+    fn len(&self) -> usize {
+        // The match is a single memory access with no branching
+        self.hex_digit_idx + match self.state {
+            EscapeUnicodeState::Done => 0,
+            EscapeUnicodeState::RightBrace => 1,
+            EscapeUnicodeState::Value => 2,
+            EscapeUnicodeState::LeftBrace => 3,
+            EscapeUnicodeState::Type => 4,
+            EscapeUnicodeState::Backslash => 5,
+        }
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl FusedIterator for EscapeUnicode {}
+
+#[stable(feature = "char_struct_display", since = "1.16.0")]
+impl fmt::Display for EscapeUnicode {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for c in self.clone() {
+            f.write_char(c)?;
+        }
+        Ok(())
+    }
+}
+
+/// An iterator that yields the literal escape code of a `char`.
+///
+/// This `struct` is created by the [`escape_default`] method on [`char`]. See
+/// its documentation for more.
+///
+/// [`escape_default`]: ../../std/primitive.char.html#method.escape_default
+/// [`char`]: ../../std/primitive.char.html
+#[derive(Clone, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct EscapeDefault {
+    state: EscapeDefaultState
+}
+
+#[derive(Clone, Debug)]
+enum EscapeDefaultState {
+    Done,
+    Char(char),
+    Backslash(char),
+    Unicode(EscapeUnicode),
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EscapeDefault {
+    type Item = char;
+
+    fn next(&mut self) -> Option<char> {
+        match self.state {
+            EscapeDefaultState::Backslash(c) => {
+                self.state = EscapeDefaultState::Char(c);
+                Some('\\')
+            }
+            EscapeDefaultState::Char(c) => {
+                self.state = EscapeDefaultState::Done;
+                Some(c)
+            }
+            EscapeDefaultState::Done => None,
+            EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let n = self.len();
+        (n, Some(n))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    fn nth(&mut self, n: usize) -> Option<char> {
+        match self.state {
+            EscapeDefaultState::Backslash(c) if n == 0 => {
+                self.state = EscapeDefaultState::Char(c);
+                Some('\\')
+            },
+            EscapeDefaultState::Backslash(c) if n == 1 => {
+                self.state = EscapeDefaultState::Done;
+                Some(c)
+            },
+            EscapeDefaultState::Backslash(_) => {
+                self.state = EscapeDefaultState::Done;
+                None
+            },
+            EscapeDefaultState::Char(c) => {
+                self.state = EscapeDefaultState::Done;
+
+                if n == 0 {
+                    Some(c)
+                } else {
+                    None
+                }
+            },
+            EscapeDefaultState::Done => return None,
+            EscapeDefaultState::Unicode(ref mut i) => return i.nth(n),
+        }
+    }
+
+    fn last(self) -> Option<char> {
+        match self.state {
+            EscapeDefaultState::Unicode(iter) => iter.last(),
+            EscapeDefaultState::Done => None,
+            EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c),
+        }
+    }
+}
+
+#[stable(feature = "exact_size_escape", since = "1.11.0")]
+impl ExactSizeIterator for EscapeDefault {
+    fn len(&self) -> usize {
+        match self.state {
+            EscapeDefaultState::Done => 0,
+            EscapeDefaultState::Char(_) => 1,
+            EscapeDefaultState::Backslash(_) => 2,
+            EscapeDefaultState::Unicode(ref iter) => iter.len(),
+        }
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl FusedIterator for EscapeDefault {}
+
+#[stable(feature = "char_struct_display", since = "1.16.0")]
+impl fmt::Display for EscapeDefault {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for c in self.clone() {
+            f.write_char(c)?;
+        }
+        Ok(())
+    }
+}
+
+/// An iterator that yields the literal escape code of a `char`.
+///
+/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
+/// documentation for more.
+///
+/// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug
+/// [`char`]: ../../std/primitive.char.html
+#[stable(feature = "char_escape_debug", since = "1.20.0")]
+#[derive(Clone, Debug)]
+pub struct EscapeDebug(EscapeDefault);
+
+#[stable(feature = "char_escape_debug", since = "1.20.0")]
+impl Iterator for EscapeDebug {
+    type Item = char;
+    fn next(&mut self) -> Option<char> { self.0.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+}
+
+#[stable(feature = "char_escape_debug", since = "1.20.0")]
+impl ExactSizeIterator for EscapeDebug { }
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl FusedIterator for EscapeDebug {}
+
+#[stable(feature = "char_escape_debug", since = "1.20.0")]
+impl fmt::Display for EscapeDebug {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
+/// Returns an iterator that yields the lowercase equivalent of a `char`.
+///
+/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
+/// its documentation for more.
+///
+/// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase
+/// [`char`]: ../../std/primitive.char.html
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug, Clone)]
+pub struct ToLowercase(CaseMappingIter);
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for ToLowercase {
+    type Item = char;
+    fn next(&mut self) -> Option<char> {
+        self.0.next()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl FusedIterator for ToLowercase {}
+
+/// Returns an iterator that yields the uppercase equivalent of a `char`.
+///
+/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
+/// its documentation for more.
+///
+/// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase
+/// [`char`]: ../../std/primitive.char.html
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug, Clone)]
+pub struct ToUppercase(CaseMappingIter);
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for ToUppercase {
+    type Item = char;
+    fn next(&mut self) -> Option<char> {
+        self.0.next()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl FusedIterator for ToUppercase {}
+
+#[derive(Debug, Clone)]
+enum CaseMappingIter {
+    Three(char, char, char),
+    Two(char, char),
+    One(char),
+    Zero,
+}
+
+impl CaseMappingIter {
+    fn new(chars: [char; 3]) -> CaseMappingIter {
+        if chars[2] == '\0' {
+            if chars[1] == '\0' {
+                CaseMappingIter::One(chars[0])  // Including if chars[0] == '\0'
+            } else {
+                CaseMappingIter::Two(chars[0], chars[1])
+            }
+        } else {
+            CaseMappingIter::Three(chars[0], chars[1], chars[2])
+        }
+    }
+}
+
+impl Iterator for CaseMappingIter {
+    type Item = char;
+    fn next(&mut self) -> Option<char> {
+        match *self {
+            CaseMappingIter::Three(a, b, c) => {
+                *self = CaseMappingIter::Two(b, c);
+                Some(a)
+            }
+            CaseMappingIter::Two(b, c) => {
+                *self = CaseMappingIter::One(c);
+                Some(b)
+            }
+            CaseMappingIter::One(c) => {
+                *self = CaseMappingIter::Zero;
+                Some(c)
+            }
+            CaseMappingIter::Zero => None,
+        }
+    }
+}
+
+impl fmt::Display for CaseMappingIter {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            CaseMappingIter::Three(a, b, c) => {
+                f.write_char(a)?;
+                f.write_char(b)?;
+                f.write_char(c)
+            }
+            CaseMappingIter::Two(b, c) => {
+                f.write_char(b)?;
+                f.write_char(c)
+            }
+            CaseMappingIter::One(c) => {
+                f.write_char(c)
+            }
+            CaseMappingIter::Zero => Ok(()),
+        }
+    }
+}
+
+#[stable(feature = "char_struct_display", since = "1.16.0")]
+impl fmt::Display for ToLowercase {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
+#[stable(feature = "char_struct_display", since = "1.16.0")]
+impl fmt::Display for ToUppercase {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index cf9abb26d3e..5ebd9e4334c 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -63,7 +63,6 @@
 #![no_core]
 #![deny(missing_docs)]
 #![deny(missing_debug_implementations)]
-#![deny(warnings)]
 
 #![feature(allow_internal_unstable)]
 #![feature(asm)]
@@ -76,6 +75,7 @@
 #![feature(custom_attribute)]
 #![feature(doc_cfg)]
 #![feature(doc_spotlight)]
+#![feature(extern_types)]
 #![feature(fn_must_use)]
 #![feature(fundamental)]
 #![feature(intrinsics)]
@@ -181,12 +181,20 @@ pub mod hash;
 pub mod fmt;
 pub mod time;
 
+pub mod unicode;
+
 /* Heap memory allocator trait */
 #[allow(missing_docs)]
-pub mod heap;
+pub mod alloc;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
+/// Use the `alloc` module instead.
+pub mod heap {
+    pub use alloc::*;
+}
 
 // note: does not need to be public
-mod char_private;
 mod iter_private;
 mod tuple;
 mod unit;
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index dcda404721c..35d70609c19 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -644,6 +644,32 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`,
+returning `None` if `rhs == 0` or the division results in overflow.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!((", stringify!($SelfT),
+"::min_value() + 1).checked_div_euc(-1), Some(", stringify!($Max), "));
+assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euc(-1), None);
+assert_eq!((1", stringify!($SelfT), ").checked_div_euc(0), None);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn checked_div_euc(self, rhs: Self) -> Option<Self> {
+                if rhs == 0 || (self == Self::min_value() && rhs == -1) {
+                    None
+                } else {
+                    Some(self.div_euc(rhs))
+                }
+            }
+        }
+
+        doc_comment! {
             concat!("Checked integer remainder. Computes `self % rhs`, returning `None` if
 `rhs == 0` or the division results in overflow.
 
@@ -671,6 +697,33 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` if
+`rhs == 0` or the division results in overflow.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+use std::", stringify!($SelfT), ";
+
+assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1));
+assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None);
+assert_eq!(", stringify!($SelfT), "::MIN.checked_mod_euc(-1), None);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn checked_mod_euc(self, rhs: Self) -> Option<Self> {
+                if rhs == 0 || (self == Self::min_value() && rhs == -1) {
+                    None
+                } else {
+                    Some(self.mod_euc(rhs))
+                }
+            }
+        }
+
+        doc_comment! {
             concat!("Checked negation. Computes `-self`, returning `None` if `self == MIN`.
 
 # Examples
@@ -1004,6 +1057,34 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`,
+wrapping around at the boundary of the type.
+
+Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value
+for the type). This is equivalent to `-MIN`, a positive value that is too large to represent in the
+type. In this case, this method returns `MIN` itself.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10);
+assert_eq!((-128i8).wrapping_div_euc(-1), -128);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn wrapping_div_euc(self, rhs: Self) -> Self {
+                self.overflowing_div_euc(rhs).0
+            }
+        }
+
+        doc_comment! {
             concat!("Wrapping (modular) remainder. Computes `self % rhs`, wrapping around at the
 boundary of the type.
 
@@ -1032,6 +1113,33 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`, wrapping around at the
+boundary of the type.
+
+Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value
+for the type). In this case, this method returns 0.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0);
+assert_eq!((-128i8).wrapping_mod_euc(-1), 0);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn wrapping_mod_euc(self, rhs: Self) -> Self {
+                self.overflowing_mod_euc(rhs).0
+            }
+        }
+
+        doc_comment! {
             concat!("Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
 of the type.
 
@@ -1297,6 +1405,39 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`.
+
+Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
+occur. If an overflow would occur then `self` is returned.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+use std::", stringify!($SelfT), ";
+
+assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false));
+assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euc(-1), (", stringify!($SelfT),
+"::MIN, true));
+```"),
+            #[inline]
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) {
+                if self == Self::min_value() && rhs == -1 {
+                    (self, true)
+                } else {
+                    (self.div_euc(rhs), false)
+                }
+            }
+        }
+
+        doc_comment! {
             concat!("Calculates the remainder when `self` is divided by `rhs`.
 
 Returns a tuple of the remainder after dividing along with a boolean indicating whether an
@@ -1328,6 +1469,40 @@ $EndFeature, "
             }
         }
 
+
+        doc_comment! {
+            concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division.
+
+Returns a tuple of the remainder after dividing along with a boolean indicating whether an
+arithmetic overflow would occur. If an overflow would occur then 0 is returned.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+use std::", stringify!($SelfT), ";
+
+assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false));
+assert_eq!(", stringify!($SelfT), "::MIN.overflowing_mod_euc(-1), (0, true));
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) {
+                if self == Self::min_value() && rhs == -1 {
+                    (0, true)
+                } else {
+                    (self.mod_euc(rhs), false)
+                }
+            }
+        }
+
+
         doc_comment! {
             concat!("Negates self, overflowing if this is equal to the minimum value.
 
@@ -1523,6 +1698,80 @@ $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Calculates the quotient of Euclidean division of `self` by `rhs`.
+
+This computes the integer `n` such that `self = n * rhs + self.mod_euc(rhs)`.
+In other words, the result is `self / rhs` rounded to the integer `n`
+such that `self >= n * rhs`.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+let a: ", stringify!($SelfT), " = 7; // or any other integer type
+let b = 4;
+
+assert_eq!(a.div_euc(b), 1); // 7 >= 4 * 1
+assert_eq!(a.div_euc(-b), -1); // 7 >= -4 * -1
+assert_eq!((-a).div_euc(b), -2); // -7 >= 4 * -2
+assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            pub fn div_euc(self, rhs: Self) -> Self {
+                let q = self / rhs;
+                if self % rhs < 0 {
+                    return if rhs > 0 { q - 1 } else { q + 1 }
+                }
+                q
+            }
+        }
+
+
+        doc_comment! {
+            concat!("Calculates the remainder `self mod rhs` by Euclidean division.
+
+In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+let a: ", stringify!($SelfT), " = 7; // or any other integer type
+let b = 4;
+
+assert_eq!(a.mod_euc(b), 3);
+assert_eq!((-a).mod_euc(b), 1);
+assert_eq!(a.mod_euc(-b), 3);
+assert_eq!((-a).mod_euc(-b), 1);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            pub fn mod_euc(self, rhs: Self) -> Self {
+                let r = self % rhs;
+                if r < 0 {
+                    r + rhs.abs()
+                } else {
+                    r
+                }
+            }
+        }
+
+        doc_comment! {
             concat!("Computes the absolute value of `self`.
 
 # Overflow behavior
@@ -2110,6 +2359,31 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, returning `None`
+if `rhs == 0`.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64));
+assert_eq!(1", stringify!($SelfT), ".checked_div_euc(0), None);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn checked_div_euc(self, rhs: Self) -> Option<Self> {
+                if rhs == 0 {
+                    None
+                } else {
+                    Some(self.div_euc(rhs))
+                }
+            }
+        }
+
+
+        doc_comment! {
             concat!("Checked integer remainder. Computes `self % rhs`, returning `None`
 if `rhs == 0`.
 
@@ -2133,6 +2407,30 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
         }
 
         doc_comment! {
+            concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None`
+if `rhs == 0`.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1));
+assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn checked_mod_euc(self, rhs: Self) -> Option<Self> {
+                if rhs == 0 {
+                    None
+                } else {
+                    Some(self.mod_euc(rhs))
+                }
+            }
+        }
+
+        doc_comment! {
             concat!("Checked negation. Computes `-self`, returning `None` unless `self ==
 0`.
 
@@ -2412,6 +2710,28 @@ Basic usage:
         }
 
         doc_comment! {
+            concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`.
+Wrapped division on unsigned types is just normal division.
+There's no way wrapping could ever happen.
+This function exists, so that all operations
+are accounted for in the wrapping operations.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn wrapping_div_euc(self, rhs: Self) -> Self {
+                self / rhs
+            }
+        }
+
+        doc_comment! {
             concat!("Wrapping (modular) remainder. Computes `self % rhs`.
 Wrapped remainder calculation on unsigned types is
 just the regular remainder calculation.
@@ -2433,6 +2753,29 @@ Basic usage:
             }
         }
 
+        doc_comment! {
+            concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`.
+Wrapped modulo calculation on unsigned types is
+just the regular remainder calculation.
+There's no way wrapping could ever happen.
+This function exists, so that all operations
+are accounted for in the wrapping operations.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0);
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            pub fn wrapping_mod_euc(self, rhs: Self) -> Self {
+                self % rhs
+            }
+        }
+
         /// Wrapping (modular) negation. Computes `-self`,
         /// wrapping around at the boundary of the type.
         ///
@@ -2667,6 +3010,33 @@ Basic usage
         }
 
         doc_comment! {
+            concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`.
+
+Returns a tuple of the divisor along with a boolean indicating
+whether an arithmetic overflow would occur. Note that for unsigned
+integers overflow never occurs, so the second value is always
+`false`.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage
+
+```
+#![feature(euclidean_division)]
+assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false));
+```"),
+            #[inline]
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) {
+                (self / rhs, false)
+            }
+        }
+
+        doc_comment! {
             concat!("Calculates the remainder when `self` is divided by `rhs`.
 
 Returns a tuple of the remainder after dividing along with a boolean
@@ -2693,6 +3063,33 @@ Basic usage
         }
 
         doc_comment! {
+            concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division.
+
+Returns a tuple of the modulo after dividing along with a boolean
+indicating whether an arithmetic overflow would occur. Note that for
+unsigned integers overflow never occurs, so the second value is
+always `false`.
+
+# Panics
+
+This function will panic if `rhs` is 0.
+
+# Examples
+
+Basic usage
+
+```
+#![feature(euclidean_division)]
+assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false));
+```"),
+            #[inline]
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) {
+                (self % rhs, false)
+            }
+        }
+
+        doc_comment! {
             concat!("Negates self in an overflowing fashion.
 
 Returns `!self + 1` using wrapping operations to return the value
@@ -2849,6 +3246,49 @@ Basic usage:
         }
     }
 
+            doc_comment! {
+            concat!("Performs Euclidean division.
+
+For unsigned types, this is just the same as `self / rhs`.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(7", stringify!($SelfT), ".div_euc(4), 1); // or any other integer type
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            pub fn div_euc(self, rhs: Self) -> Self {
+                self / rhs
+            }
+        }
+
+
+        doc_comment! {
+            concat!("Calculates the remainder `self mod rhs` by Euclidean division.
+
+For unsigned types, this is just the same as `self % rhs`.
+
+# Examples
+
+Basic usage:
+
+```
+#![feature(euclidean_division)]
+assert_eq!(7", stringify!($SelfT), ".mod_euc(4), 3); // or any other integer type
+```"),
+            #[unstable(feature = "euclidean_division", issue = "49048")]
+            #[inline]
+            #[rustc_inherit_overflow_checks]
+            pub fn mod_euc(self, rhs: Self) -> Self {
+                self % rhs
+            }
+        }
+
         doc_comment! {
             concat!("Returns `true` if and only if `self == 2^k` for some `k`.
 
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 61ef6798b2e..0dfdabee031 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -628,8 +628,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```rust
-    /// #![feature(option_filter)]
-    ///
     /// fn is_even(n: &i32) -> bool {
     ///     n % 2 == 0
     /// }
@@ -639,7 +637,7 @@ impl<T> Option<T> {
     /// assert_eq!(Some(4).filter(is_even), Some(4));
     /// ```
     #[inline]
-    #[unstable(feature = "option_filter", issue = "45860")]
+    #[stable(feature = "option_filter", since = "1.27.0")]
     pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
         if let Some(x) = self {
             if predicate(&x) {
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index d43496c387c..cc3ad71117a 100644
--- a/src/libcore/prelude/v1.rs
+++ b/src/libcore/prelude/v1.rs
@@ -62,6 +62,3 @@ pub use slice::SliceExt;
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use str::StrExt;
-#[stable(feature = "core_prelude", since = "1.4.0")]
-#[doc(no_inline)]
-pub use char::CharExt;
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 5a54de06b5e..4a7d7c410eb 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -677,6 +677,7 @@ impl<T: ?Sized> *const T {
     ///
     /// ```
     /// #![feature(offset_to)]
+    /// #![allow(deprecated)]
     ///
     /// fn main() {
     ///     let a = [0; 5];
@@ -689,14 +690,15 @@ impl<T: ?Sized> *const T {
     /// }
     /// ```
     #[unstable(feature = "offset_to", issue = "41079")]
+    #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \
+        opposite argument order.  If you're writing unsafe code, consider `offset_from`.")]
     #[inline]
     pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
         let size = mem::size_of::<T>();
         if size == 0 {
             None
         } else {
-            let diff = (other as isize).wrapping_sub(self as isize);
-            Some(diff / size as isize)
+            Some(other.wrapping_offset_from(self))
         }
     }
 
@@ -1442,6 +1444,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// ```
     /// #![feature(offset_to)]
+    /// #![allow(deprecated)]
     ///
     /// fn main() {
     ///     let mut a = [0; 5];
@@ -1454,14 +1457,15 @@ impl<T: ?Sized> *mut T {
     /// }
     /// ```
     #[unstable(feature = "offset_to", issue = "41079")]
+    #[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \
+        opposite argument order.  If you're writing unsafe code, consider `offset_from`.")]
     #[inline]
     pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
         let size = mem::size_of::<T>();
         if size == 0 {
             None
         } else {
-            let diff = (other as isize).wrapping_sub(self as isize);
-            Some(diff / size as isize)
+            Some(other.wrapping_offset_from(self))
         }
     }
 
@@ -2746,6 +2750,14 @@ impl<T: ?Sized> NonNull<T> {
             NonNull::new_unchecked(self.as_ptr() as *mut U)
         }
     }
+
+    /// Cast to an `Opaque` pointer
+    #[unstable(feature = "allocator_api", issue = "32838")]
+    pub fn as_opaque(self) -> NonNull<::alloc::Opaque> {
+        unsafe {
+            NonNull::new_unchecked(self.as_ptr() as _)
+        }
+    }
 }
 
 #[stable(feature = "nonnull", since = "1.25.0")]
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 0f1b7cb8fcc..0a22028da81 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1185,7 +1185,7 @@ macro_rules! iterator {
 
             #[inline]
             fn size_hint(&self) -> (usize, Option<usize>) {
-                let exact = ptrdistance(self.ptr, self.end);
+                let exact = unsafe { ptrdistance(self.ptr, self.end) };
                 (exact, Some(exact))
             }
 
@@ -1593,10 +1593,11 @@ unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
 // Return the number of elements of `T` from `start` to `end`.
 // Return the arithmetic difference if `T` is zero size.
 #[inline(always)]
-fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
-    match start.offset_to(end) {
-        Some(x) => x as usize,
-        None => (end as usize).wrapping_sub(start as usize),
+unsafe fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
+    if mem::size_of::<T>() == 0 {
+        (end as usize).wrapping_sub(start as usize)
+    } else {
+        end.offset_from(start) as usize
     }
 }
 
diff --git a/src/libstd_unicode/lossy.rs b/src/libcore/str/lossy.rs
index cc8e93308a5..30b7267da7c 100644
--- a/src/libstd_unicode/lossy.rs
+++ b/src/libcore/str/lossy.rs
@@ -8,12 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::str as core_str;
-use core::fmt;
-use core::fmt::Write;
 use char;
-use core::mem;
-
+use str as core_str;
+use fmt;
+use fmt::Write;
+use mem;
 
 /// Lossy UTF-8 string.
 #[unstable(feature = "str_internals", issue = "0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 1185b7acaae..f1fe23092de 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -19,13 +19,17 @@ use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 
 use char;
 use fmt;
-use iter::{Map, Cloned, FusedIterator, TrustedLen};
+use iter::{Map, Cloned, FusedIterator, TrustedLen, Filter};
 use iter_private::TrustedRandomAccess;
 use slice::{self, SliceIndex};
 use mem;
 
 pub mod pattern;
 
+#[unstable(feature = "str_internals", issue = "0")]
+#[allow(missing_docs)]
+pub mod lossy;
+
 /// A trait to abstract the idea of creating a new instance of a type from a
 /// string.
 ///
@@ -2212,6 +2216,18 @@ pub trait StrExt {
     fn is_empty(&self) -> bool;
     #[stable(feature = "core", since = "1.6.0")]
     fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
+    #[stable(feature = "split_whitespace", since = "1.1.0")]
+    fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
+    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
+    fn is_whitespace(&self) -> bool;
+    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
+    fn is_alphanumeric(&self) -> bool;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trim(&self) -> &str;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trim_left(&self) -> &str;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trim_right(&self) -> &str;
 }
 
 // truncate `&str` to length at most equal to `max`
@@ -2532,6 +2548,36 @@ impl StrExt for str {
 
     #[inline]
     fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
+
+    #[inline]
+    fn split_whitespace(&self) -> SplitWhitespace {
+        SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
+    }
+
+    #[inline]
+    fn is_whitespace(&self) -> bool {
+        self.chars().all(|c| c.is_whitespace())
+    }
+
+    #[inline]
+    fn is_alphanumeric(&self) -> bool {
+        self.chars().all(|c| c.is_alphanumeric())
+    }
+
+    #[inline]
+    fn trim(&self) -> &str {
+        self.trim_matches(|c: char| c.is_whitespace())
+    }
+
+    #[inline]
+    fn trim_left(&self) -> &str {
+        self.trim_left_matches(|c: char| c.is_whitespace())
+    }
+
+    #[inline]
+    fn trim_right(&self) -> &str {
+        self.trim_right_matches(|c: char| c.is_whitespace())
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2547,3 +2593,75 @@ impl<'a> Default for &'a str {
     /// Creates an empty str
     fn default() -> &'a str { "" }
 }
+
+/// An iterator over the non-whitespace substrings of a string,
+/// separated by any amount of whitespace.
+///
+/// This struct is created by the [`split_whitespace`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
+/// [`str`]: ../../std/primitive.str.html
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+#[derive(Clone, Debug)]
+pub struct SplitWhitespace<'a> {
+    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
+}
+
+#[derive(Clone)]
+struct IsWhitespace;
+
+impl FnOnce<(char, )> for IsWhitespace {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl FnMut<(char, )> for IsWhitespace {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
+        arg.0.is_whitespace()
+    }
+}
+
+#[derive(Clone)]
+struct IsNotEmpty;
+
+impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
+        !arg.0.is_empty()
+    }
+}
+
+
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+impl<'a> Iterator for SplitWhitespace<'a> {
+    type Item = &'a str;
+
+    fn next(&mut self) -> Option<&'a str> {
+        self.inner.next()
+    }
+}
+
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.inner.next_back()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<'a> FusedIterator for SplitWhitespace<'a> {}
diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs
index f634fabe503..a3667b3f3fe 100644
--- a/src/libcore/tests/atomic.rs
+++ b/src/libcore/tests/atomic.rs
@@ -104,8 +104,10 @@ static S_UINT: AtomicUsize = AtomicUsize::new(0);
 
 #[test]
 fn static_init() {
-    assert!(!S_FALSE.load(SeqCst));
-    assert!(S_TRUE.load(SeqCst));
-    assert!(S_INT.load(SeqCst) == 0);
-    assert!(S_UINT.load(SeqCst) == 0);
+    // Note that we're not really testing the mutability here but it's important
+    // on Android at the moment (#49775)
+    assert!(!S_FALSE.swap(true, SeqCst));
+    assert!(S_TRUE.swap(false, SeqCst));
+    assert!(S_INT.fetch_add(1, SeqCst) == 0);
+    assert!(S_UINT.fetch_add(1, SeqCst) == 0);
 }
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 971759dcdd0..149269263dc 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(ascii_ctype)]
 #![feature(box_syntax)]
 #![feature(core_float)]
@@ -35,6 +33,7 @@
 #![feature(sort_internals)]
 #![feature(specialization)]
 #![feature(step_trait)]
+#![feature(str_internals)]
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_trait)]
@@ -70,4 +69,5 @@ mod ptr;
 mod result;
 mod slice;
 mod str;
+mod str_lossy;
 mod tuple;
diff --git a/src/libstd_unicode/tests/lossy.rs b/src/libcore/tests/str_lossy.rs
index e05d0668556..69e28256da9 100644
--- a/src/libstd_unicode/tests/lossy.rs
+++ b/src/libcore/tests/str_lossy.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std_unicode::lossy::*;
+use core::str::lossy::*;
 
 #[test]
 fn chunks() {
diff --git a/src/libstd_unicode/bool_trie.rs b/src/libcore/unicode/bool_trie.rs
index 3e45b08f399..3e45b08f399 100644
--- a/src/libstd_unicode/bool_trie.rs
+++ b/src/libcore/unicode/bool_trie.rs
diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs
new file mode 100644
index 00000000000..b6b033adc04
--- /dev/null
+++ b/src/libcore/unicode/mod.rs
@@ -0,0 +1,27 @@
+// 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.
+
+#![unstable(feature = "unicode_internals", issue = "0")]
+#![allow(missing_docs)]
+
+mod bool_trie;
+pub(crate) mod printable;
+pub(crate) mod tables;
+pub(crate) mod version;
+
+// For use in liballoc, not re-exported in libstd.
+pub mod derived_property {
+    pub use unicode::tables::derived_property::{Case_Ignorable, Cased};
+}
+
+// For use in libsyntax
+pub mod property {
+    pub use unicode::tables::property::Pattern_White_Space;
+}
diff --git a/src/etc/char_private.py b/src/libcore/unicode/printable.py
index cfe5b01e934..9410dafbbc3 100644
--- a/src/etc/char_private.py
+++ b/src/libcore/unicode/printable.py
@@ -187,7 +187,7 @@ def main():
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NOTE: The following code was generated by "src/etc/char_private.py",
+// NOTE: The following code was generated by "src/libcore/unicode/printable.py",
 //       do not edit directly!
 
 fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
diff --git a/src/libcore/char_private.rs b/src/libcore/unicode/printable.rs
index e6803745ab5..4426c32eebc 100644
--- a/src/libcore/char_private.rs
+++ b/src/libcore/unicode/printable.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NOTE: The following code was generated by "src/etc/char_private.py",
+// NOTE: The following code was generated by "src/libcore/unicode/printable.py",
 //       do not edit directly!
 
 fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
diff --git a/src/libstd_unicode/tables.rs b/src/libcore/unicode/tables.rs
index b53953b62a7..3fbbc011bc4 100644
--- a/src/libstd_unicode/tables.rs
+++ b/src/libcore/unicode/tables.rs
@@ -12,11 +12,12 @@
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
-use version::UnicodeVersion;
-use bool_trie::{BoolTrie, SmallBoolTrie};
+use unicode::version::UnicodeVersion;
+use unicode::bool_trie::{BoolTrie, SmallBoolTrie};
 
 /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
-/// `CharExt` and `UnicodeStrPrelude` traits are based on.
+/// `char` and `str` methods are based on.
+#[unstable(feature = "unicode_version", issue = "49726")]
 pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
     major: 10,
     minor: 0,
@@ -1138,9 +1139,6 @@ pub mod property {
 }
 
 pub mod conversions {
-    use core::option::Option;
-    use core::option::Option::{Some, None};
-
     pub fn to_lower(c: char) -> [char; 3] {
         match bsearch_case_table(c, to_lowercase_table) {
             None        => [c, '\0', '\0'],
diff --git a/src/libstd_unicode/unicode.py b/src/libcore/unicode/unicode.py
index a8629493086..75ec01944bf 100755
--- a/src/libstd_unicode/unicode.py
+++ b/src/libcore/unicode/unicode.py
@@ -39,8 +39,8 @@ preamble = '''// Copyright 2012-2016 The Rust Project Developers. See the COPYRI
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
-use version::UnicodeVersion;
-use bool_trie::{BoolTrie, SmallBoolTrie};
+use unicode::version::UnicodeVersion;
+use unicode::bool_trie::{BoolTrie, SmallBoolTrie};
 '''
 
 # Mapping taken from Table 12 from:
@@ -408,9 +408,6 @@ def emit_property_module(f, mod, tbl, emit):
 def emit_conversions_module(f, to_upper, to_lower, to_title):
     f.write("pub mod conversions {")
     f.write("""
-    use core::option::Option;
-    use core::option::Option::{Some, None};
-
     pub fn to_lower(c: char) -> [char; 3] {
         match bsearch_case_table(c, to_lowercase_table) {
             None        => [c, '\\0', '\\0'],
@@ -473,7 +470,8 @@ if __name__ == "__main__":
             unicode_version = re.search(pattern, readme.read()).groups()
         rf.write("""
 /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
-/// `CharExt` and `UnicodeStrPrelude` traits are based on.
+/// `char` and `str` methods are based on.
+#[unstable(feature = "unicode_version", issue = "49726")]
 pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
     major: %s,
     minor: %s,
diff --git a/src/libstd_unicode/version.rs b/src/libcore/unicode/version.rs
index d82a749d917..59ebf5f5012 100644
--- a/src/libstd_unicode/version.rs
+++ b/src/libcore/unicode/version.rs
@@ -12,6 +12,7 @@
 ///
 /// See also: <http://www.unicode.org/versions/>
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+#[unstable(feature = "unicode_version", issue = "49726")]
 pub struct UnicodeVersion {
     /// Major version.
     pub major: u32,
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 0f45f965104..a551b1b770a 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -19,7 +19,6 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
-#![deny(warnings)]
 
 pub use self::Piece::*;
 pub use self::Position::*;
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index d8c366d2413..158d0101515 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -287,7 +287,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(allow(unused_variables), deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(str_escape)]
 
diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs
index 5f768ef4399..43c5bbbc618 100644
--- a/src/libpanic_abort/lib.rs
+++ b/src/libpanic_abort/lib.rs
@@ -19,7 +19,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
-#![deny(warnings)]
 #![panic_runtime]
 #![allow(unused_features)]
 
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index a5c227cb401..9321d6917d1 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -28,7 +28,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
-#![deny(warnings)]
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 6aa5572721d..e171216523a 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -24,7 +24,6 @@
 //! See [the book](../book/first-edition/procedural-macros.html) for more.
 
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
-#![deny(warnings)]
 #![deny(missing_docs)]
 #![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",
@@ -141,9 +140,16 @@ impl From<TokenTree> for TokenStream {
 #[unstable(feature = "proc_macro", issue = "38356")]
 impl iter::FromIterator<TokenTree> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
+        trees.into_iter().map(TokenStream::from).collect()
+    }
+}
+
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl iter::FromIterator<TokenStream> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
         let mut builder = tokenstream::TokenStreamBuilder::new();
-        for tree in trees {
-            builder.push(tree.to_internal());
+        for stream in streams {
+            builder.push(stream.0);
         }
         TokenStream(builder.build())
     }
diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs
index 278e0f9a26e..5496df1342f 100644
--- a/src/librustc/benches/lib.rs
+++ b/src/librustc/benches/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(test)]
 
 extern crate test;
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index 1247db55f58..118125a19dd 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -389,7 +389,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             hir::ExprType(ref e, _) |
             hir::ExprUnary(_, ref e) |
             hir::ExprField(ref e, _) |
-            hir::ExprTupField(ref e, _) |
             hir::ExprYield(ref e) |
             hir::ExprRepeat(ref e, _) => {
                 self.straightline(expr, pred, Some(&**e).into_iter())
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 7c5318a96f5..1b907073238 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -500,6 +500,7 @@ define_dep_nodes!( <'tcx>
     [] GenericsOfItem(DefId),
     [] PredicatesOfItem(DefId),
     [] InferredOutlivesOf(DefId),
+    [] InferredOutlivesCrate(CrateNum),
     [] SuperPredicatesOfItem(DefId),
     [] TraitDefOfItem(DefId),
     [] AdtDefOfItem(DefId),
@@ -632,6 +633,7 @@ define_dep_nodes!( <'tcx>
     [input] MaybeUnusedTraitImport(DefId),
     [input] MaybeUnusedExternCrates,
     [eval_always] StabilityIndex,
+    [eval_always] AllTraits,
     [input] AllCrateNums,
     [] ExportedSymbols(CrateNum),
     [eval_always] CollectAndPartitionTranslationItems,
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 9f51eb8c35a..be9f8b8dac5 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -658,6 +658,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
         PatKind::Struct(ref qpath, ref fields, _) => {
             visitor.visit_qpath(qpath, pattern.id, pattern.span);
             for field in fields {
+                visitor.visit_id(field.node.id);
                 visitor.visit_name(field.span, field.node.name);
                 visitor.visit_pat(&field.node.pat)
             }
@@ -959,6 +960,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprStruct(ref qpath, ref fields, ref optional_base) => {
             visitor.visit_qpath(qpath, expression.id, expression.span);
             for field in fields {
+                visitor.visit_id(field.id);
                 visitor.visit_name(field.name.span, field.name.node);
                 visitor.visit_expr(&field.expr)
             }
@@ -1025,9 +1027,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_name(name.span, name.node);
         }
-        ExprTupField(ref subexpression, _) => {
-            visitor.visit_expr(subexpression);
-        }
         ExprIndex(ref main_expression, ref index_expression) => {
             visitor.visit_expr(main_expression);
             visitor.visit_expr(index_expression)
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b13c289394a..fee076acb20 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2100,6 +2100,7 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_field(&mut self, f: &Field) -> hir::Field {
         hir::Field {
+            id: self.next_id().node_id,
             name: respan(f.ident.span, self.lower_ident(f.ident)),
             expr: P(self.lower_expr(&f.expr)),
             span: f.span,
@@ -2863,6 +2864,7 @@ impl<'a> LoweringContext<'a> {
                     .map(|f| Spanned {
                         span: f.span,
                         node: hir::FieldPat {
+                            id: self.next_id().node_id,
                             name: self.lower_ident(f.node.ident),
                             pat: self.lower_pat(&f.node.pat),
                             is_shorthand: f.node.is_shorthand,
@@ -3010,7 +3012,28 @@ impl<'a> LoweringContext<'a> {
                 )
             }),
             ExprKind::Catch(ref body) => {
-                self.with_catch_scope(body.id, |this| hir::ExprBlock(this.lower_block(body, true)))
+                self.with_catch_scope(body.id, |this| {
+                    let unstable_span =
+                        this.allow_internal_unstable(CompilerDesugaringKind::Catch, body.span);
+                    let mut block = this.lower_block(body, true).into_inner();
+                    let tail = block.expr.take().map_or_else(
+                        || {
+                            let LoweredNodeId { node_id, hir_id } = this.next_id();
+                            let span = this.sess.codemap().end_point(unstable_span);
+                            hir::Expr {
+                                id: node_id,
+                                span,
+                                node: hir::ExprTup(hir_vec![]),
+                                attrs: ThinVec::new(),
+                                hir_id,
+                            }
+                        },
+                        |x: P<hir::Expr>| x.into_inner(),
+                    );
+                    block.expr = Some(this.wrap_in_try_constructor(
+                        "from_ok", tail, unstable_span));
+                    hir::ExprBlock(P(block))
+                })
             }
             ExprKind::Match(ref expr, ref arms) => hir::ExprMatch(
                 P(self.lower_expr(expr)),
@@ -3074,7 +3097,6 @@ impl<'a> LoweringContext<'a> {
                 P(self.lower_expr(el)),
                 respan(ident.span, self.lower_ident(ident)),
             ),
-            ExprKind::TupField(ref el, ident) => hir::ExprTupField(P(self.lower_expr(el)), ident),
             ExprKind::Index(ref el, ref er) => {
                 hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
             }
@@ -3539,12 +3561,8 @@ impl<'a> LoweringContext<'a> {
 
                         self.expr_call(e.span, from, hir_vec![err_expr])
                     };
-                    let from_err_expr = {
-                        let path = &["ops", "Try", "from_error"];
-                        let from_err = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
-                        P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
-                    };
-
+                    let from_err_expr =
+                        self.wrap_in_try_constructor("from_error", from_expr, unstable_span);
                     let thin_attrs = ThinVec::from(attrs);
                     let catch_scope = self.catch_scopes.last().map(|x| *x);
                     let ret_expr = if let Some(catch_node) = catch_scope {
@@ -3725,6 +3743,7 @@ impl<'a> LoweringContext<'a> {
 
     fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
         hir::Field {
+            id: self.next_id().node_id,
             name: Spanned { node: name, span },
             span,
             expr,
@@ -4079,6 +4098,18 @@ impl<'a> LoweringContext<'a> {
             )
         }
     }
+
+    fn wrap_in_try_constructor(
+        &mut self,
+        method: &'static str,
+        e: hir::Expr,
+        unstable_span: Span,
+    ) -> P<hir::Expr> {
+        let path = &["ops", "Try", method];
+        let from_err = P(self.expr_std_path(unstable_span, path,
+                                            ThinVec::new()));
+        P(self.expr_call(e.span, from_err, hir_vec![e]))
+    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index e8bcbfbb77a..1e348e3a31c 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -33,10 +33,11 @@ use hir::svh::Svh;
 use util::nodemap::{DefIdMap, FxHashMap};
 
 use arena::TypedArena;
-use std::cell::RefCell;
 use std::io;
 use ty::TyCtxt;
 
+use rustc_data_structures::sync::Lock;
+
 pub mod blocks;
 mod collector;
 mod def_collector;
@@ -264,7 +265,7 @@ pub struct Map<'hir> {
     definitions: &'hir Definitions,
 
     /// Bodies inlined from other crates are cached here.
-    inlined_bodies: RefCell<DefIdMap<&'hir Body>>,
+    inlined_bodies: Lock<DefIdMap<&'hir Body>>,
 
     /// The reverse mapping of `node_to_hir_id`.
     hir_to_node_id: FxHashMap<HirId, NodeId>,
@@ -927,8 +928,13 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body {
+        let mut inlined_bodies = self.inlined_bodies.borrow_mut();
+        if let Some(&b) = inlined_bodies.get(&def_id) {
+            debug_assert_eq!(&body, b);
+            return b;
+        }
         let body = self.forest.inlined_bodies.alloc(body);
-        self.inlined_bodies.borrow_mut().insert(def_id, body);
+        inlined_bodies.insert(def_id, body);
         body
     }
 
@@ -1189,7 +1195,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
         map,
         hir_to_node_id,
         definitions,
-        inlined_bodies: RefCell::new(DefIdMap()),
+        inlined_bodies: Lock::new(DefIdMap()),
     };
 
     hir_id_validator::check_crate(&map);
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index be8cceb6118..e6080fad91d 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -827,6 +827,7 @@ impl Pat {
 /// except is_shorthand is true
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct FieldPat {
+    pub id: NodeId,
     /// The identifier for the field
     pub name: Name,
     /// The pattern the field is destructured to
@@ -1172,6 +1173,7 @@ pub struct Arm {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Field {
+    pub id: NodeId,
     pub name: Spanned<Name>,
     pub expr: P<Expr>,
     pub span: Span,
@@ -1276,7 +1278,6 @@ impl Expr {
             ExprAssign(..) => ExprPrecedence::Assign,
             ExprAssignOp(..) => ExprPrecedence::AssignOp,
             ExprField(..) => ExprPrecedence::Field,
-            ExprTupField(..) => ExprPrecedence::TupField,
             ExprIndex(..) => ExprPrecedence::Index,
             ExprPath(..) => ExprPrecedence::Path,
             ExprAddrOf(..) => ExprPrecedence::AddrOf,
@@ -1363,12 +1364,8 @@ pub enum Expr_ {
     ///
     /// For example, `a += 1`.
     ExprAssignOp(BinOp, P<Expr>, P<Expr>),
-    /// Access of a named struct field (`obj.foo`)
+    /// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct or tuple field
     ExprField(P<Expr>, Spanned<Name>),
-    /// Access of an unnamed field of a struct or tuple-struct
-    ///
-    /// For example, `foo.0`.
-    ExprTupField(P<Expr>, Spanned<usize>),
     /// An indexing operation (`foo[2]`)
     ExprIndex(P<Expr>, P<Expr>),
 
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index ff501f30c89..d3f2458ef87 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1201,8 +1201,7 @@ impl<'a> State<'a> {
     fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) -> io::Result<()> {
         let prec =
             match func.node {
-                hir::ExprField(..) |
-                hir::ExprTupField(..) => parser::PREC_FORCE_PAREN,
+                hir::ExprField(..) => parser::PREC_FORCE_PAREN,
                 _ => parser::PREC_POSTFIX,
             };
 
@@ -1405,11 +1404,6 @@ impl<'a> State<'a> {
                 self.s.word(".")?;
                 self.print_name(name.node)?;
             }
-            hir::ExprTupField(ref expr, id) => {
-                self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
-                self.s.word(".")?;
-                self.print_usize(id.node)?;
-            }
             hir::ExprIndex(ref expr, ref index) => {
                 self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
                 self.s.word("[")?;
@@ -2376,7 +2370,6 @@ fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
         hir::ExprCast(ref x, _) |
         hir::ExprType(ref x, _) |
         hir::ExprField(ref x, _) |
-        hir::ExprTupField(ref x, _) |
         hir::ExprIndex(ref x, _) => {
             // &X { y: 1 }, X { y: 1 }.y
             contains_exterior_struct_lit(&x)
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 38b284fd646..4a001802eac 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -420,11 +420,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Pat {
 }
 
 impl_stable_hash_for_spanned!(hir::FieldPat);
-impl_stable_hash_for!(struct hir::FieldPat {
-    name,
-    pat,
-    is_shorthand
-});
+
+impl<'a> HashStable<StableHashingContext<'a>> for hir::FieldPat {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::FieldPat {
+            id: _,
+            name,
+            ref pat,
+            is_shorthand,
+        } = *self;
+
+        name.hash_stable(hcx, hasher);
+        pat.hash_stable(hcx, hasher);
+        is_shorthand.hash_stable(hcx, hasher);
+    }
+}
 
 impl_stable_hash_for!(enum hir::BindingAnnotation {
     Unannotated,
@@ -507,12 +519,24 @@ impl_stable_hash_for!(struct hir::Arm {
     body
 });
 
-impl_stable_hash_for!(struct hir::Field {
-    name,
-    expr,
-    span,
-    is_shorthand
-});
+impl<'a> HashStable<StableHashingContext<'a>> for hir::Field {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let hir::Field {
+            id: _,
+            name,
+            ref expr,
+            span,
+            is_shorthand,
+        } = *self;
+
+        name.hash_stable(hcx, hasher);
+        expr.hash_stable(hcx, hasher);
+        span.hash_stable(hcx, hasher);
+        is_shorthand.hash_stable(hcx, hasher);
+    }
+}
 
 impl_stable_hash_for_spanned!(ast::Name);
 
@@ -569,7 +593,6 @@ impl_stable_hash_for!(enum hir::Expr_ {
     ExprAssign(lhs, rhs),
     ExprAssignOp(op, lhs, rhs),
     ExprField(owner, field_name),
-    ExprTupField(owner, idx),
     ExprIndex(lhs, rhs),
     ExprPath(path),
     ExprAddrOf(mutability, sub),
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 3bb4c86e7c2..4ac678aaa05 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -372,7 +372,8 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
 
 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
     DotFill,
-    QuestionMark
+    QuestionMark,
+    Catch
 });
 
 impl_stable_hash_for!(enum ::syntax_pos::FileName {
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index af4d3429bb1..41cfac2674b 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -1100,6 +1100,20 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::CrateVariancesMap {
     }
 }
 
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::CratePredicatesMap<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        let ty::CratePredicatesMap {
+            ref predicates,
+            // This is just an irrelevant helper value.
+            empty_predicate: _,
+        } = *self;
+
+        predicates.hash_stable(hcx, hasher);
+    }
+}
+
 impl_stable_hash_for!(struct ty::AssociatedItem {
     def_id,
     name,
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs
index eb5df697216..725ea9734ab 100644
--- a/src/librustc/infer/anon_types/mod.rs
+++ b/src/librustc/infer/anon_types/mod.rs
@@ -533,10 +533,14 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>
         match r {
             // ignore bound regions that appear in the type (e.g., this
             // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
-            ty::ReLateBound(..) => return r,
+            ty::ReLateBound(..) |
 
             // ignore `'static`, as that can appear anywhere
-            ty::ReStatic => return r,
+            ty::ReStatic |
+
+            // ignore `ReScope`, as that can appear anywhere
+            // See `src/test/run-pass/issue-49556.rs` for example.
+            ty::ReScope(..) => return r,
 
             _ => { }
         }
diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs
index 4357c9a5a77..8ea6eb005a1 100644
--- a/src/librustc/infer/canonical.rs
+++ b/src/librustc/infer/canonical.rs
@@ -36,13 +36,13 @@ use rustc_data_structures::indexed_vec::Idx;
 use serialize::UseSpecializedDecodable;
 use std::fmt::Debug;
 use std::ops::Index;
+use std::sync::atomic::Ordering;
 use syntax::codemap::Span;
 use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
 use ty::subst::{Kind, UnpackedKind};
 use ty::fold::{TypeFoldable, TypeFolder};
 use util::captures::Captures;
-use util::common::CellUsizeExt;
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
@@ -473,7 +473,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     where
         V: Canonicalize<'gcx, 'tcx>,
     {
-        self.tcx.sess.perf_stats.queries_canonicalized.increment();
+        self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
 
         Canonicalizer::canonicalize(
             value,
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 96c23098821..8d314e25197 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 self.msg_span_from_early_bound_and_free_regions(region)
             },
             ty::ReStatic => ("the static lifetime".to_owned(), None),
-            _ => bug!(),
+            _ => bug!("{:?}", region),
         }
     }
 
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index 91df6cabf3a..5e96f4eb576 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::ast;
+use syntax::symbol::InternedString;
 use syntax_pos::Span;
 use ty::{self, Ty};
 
@@ -53,7 +53,7 @@ pub enum TypeVariableOrigin {
     MiscVariable(Span),
     NormalizeProjectionType(Span),
     TypeInference(Span),
-    TypeParameterDefinition(Span, ast::Name),
+    TypeParameterDefinition(Span, InternedString),
 
     /// one of the upvars or closure kind parameters in a `ClosureSubsts`
     /// (before it has been determined)
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 7da664e6d02..a2cefe488c6 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -39,7 +39,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -61,6 +60,7 @@
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(trace_macros)]
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 89a9f303478..0d4fd99995f 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -31,7 +31,7 @@
 pub use self::Level::*;
 pub use self::LintSource::*;
 
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 
 use errors::{DiagnosticBuilder, DiagnosticId};
 use hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -287,8 +287,9 @@ pub trait EarlyLintPass: LintPass {
 }
 
 /// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
-pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
+pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
+                                                                           + sync::Sync + 'static>;
 
 /// Identifies a lint known to the compiler.
 #[derive(Clone, Copy, Debug)]
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index add9b621596..41334a37dbe 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -401,7 +401,7 @@ pub fn used_crates(tcx: TyCtxt, prefer: LinkagePreference)
         .collect::<Vec<_>>();
     let mut ordering = tcx.postorder_cnums(LOCAL_CRATE);
     Lrc::make_mut(&mut ordering).reverse();
-    libs.sort_by_key(|&(a, _)| {
+    libs.sort_by_cached_key(|&(a, _)| {
         ordering.iter().position(|x| *x == a)
     });
     libs
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index abd52624c30..9ec3d2e2460 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -13,7 +13,7 @@
 // from live codes are live, and everything else is dead.
 
 use hir::map as hir_map;
-use hir::{self, Item_, PatKind};
+use hir::{self, PatKind};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::itemlikevisit::ItemLikeVisitor;
 
@@ -99,22 +99,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         self.check_def_id(self.tables.type_dependent_defs()[id].def_id());
     }
 
-    fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
+    fn handle_field_access(&mut self, lhs: &hir::Expr, node_id: ast::NodeId) {
         match self.tables.expr_ty_adjusted(lhs).sty {
             ty::TyAdt(def, _) => {
-                self.insert_def_id(def.non_enum_variant().field_named(name).did);
-            }
-            _ => span_bug!(lhs.span, "named field access on non-ADT"),
-        }
-    }
-
-    fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
-        match self.tables.expr_ty_adjusted(lhs).sty {
-            ty::TyAdt(def, _) => {
-                self.insert_def_id(def.non_enum_variant().fields[idx].did);
+                let index = self.tcx.field_index(node_id, self.tables);
+                self.insert_def_id(def.non_enum_variant().fields[index].did);
             }
             ty::TyTuple(..) => {}
-            _ => span_bug!(lhs.span, "numeric field access on non-ADT"),
+            _ => span_bug!(lhs.span, "named field access on non-ADT"),
         }
     }
 
@@ -128,7 +120,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             if let PatKind::Wild = pat.node.pat.node {
                 continue;
             }
-            self.insert_def_id(variant.field_named(pat.node.name).did);
+            let index = self.tcx.field_index(pat.node.id, self.tables);
+            self.insert_def_id(variant.fields[index].did);
         }
     }
 
@@ -191,18 +184,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         self.inherited_pub_visibility = had_inherited_pub_visibility;
     }
 
-    fn mark_as_used_if_union(&mut self, did: DefId, fields: &hir::HirVec<hir::Field>) {
-        if let Some(node_id) = self.tcx.hir.as_local_node_id(did) {
-            if let Some(hir_map::NodeItem(item)) = self.tcx.hir.find(node_id) {
-                if let Item_::ItemUnion(ref variant, _) = item.node {
-                    if variant.fields().len() > 1 {
-                        for field in variant.fields() {
-                            if fields.iter().find(|x| x.name.node == field.name).is_some() {
-                                self.live_symbols.insert(field.id);
-                            }
-                        }
-                    }
-                }
+    fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &hir::HirVec<hir::Field>) {
+        if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did.is_local() {
+            for field in fields {
+                let index = self.tcx.field_index(field.id, self.tables);
+                self.insert_def_id(adt.non_enum_variant().fields[index].did);
             }
         }
     }
@@ -242,17 +228,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
             hir::ExprMethodCall(..) => {
                 self.lookup_and_handle_method(expr.hir_id);
             }
-            hir::ExprField(ref lhs, ref name) => {
-                self.handle_field_access(&lhs, name.node);
-            }
-            hir::ExprTupField(ref lhs, idx) => {
-                self.handle_tup_field_access(&lhs, idx.node);
+            hir::ExprField(ref lhs, ..) => {
+                self.handle_field_access(&lhs, expr.id);
             }
             hir::ExprStruct(_, ref fields, _) => {
-                if let ty::TypeVariants::TyAdt(ref def, _) = self.tables.expr_ty(expr).sty {
-                    if def.is_union() {
-                        self.mark_as_used_if_union(def.did, fields);
-                    }
+                if let ty::TypeVariants::TyAdt(ref adt, _) = self.tables.expr_ty(expr).sty {
+                    self.mark_as_used_if_union(adt, fields);
                 }
             }
             _ => ()
@@ -408,7 +389,7 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     // Seed entry point
-    if let Some((id, _)) = *tcx.sess.entry_fn.borrow() {
+    if let Some((id, _, _)) = *tcx.sess.entry_fn.borrow() {
         worklist.push(id);
     }
 
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index e7055827c49..e7fc8d633c8 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -94,13 +94,14 @@ pub enum Linkage {
 
 pub fn calculate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let sess = &tcx.sess;
-    let mut fmts = sess.dependency_formats.borrow_mut();
+    let mut fmts = FxHashMap();
     for &ty in sess.crate_types.borrow().iter() {
         let linkage = calculate_type(tcx, ty);
         verify_ok(tcx, &linkage);
         fmts.insert(ty, linkage);
     }
     sess.abort_if_errors();
+    sess.dependency_formats.set(fmts);
 }
 
 fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -222,7 +223,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     //
     // Things like allocators and panic runtimes may not have been activated
     // quite yet, so do so here.
-    activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
+    activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
                           &|cnum| tcx.is_panic_runtime(cnum));
     activate_injected_allocator(sess, &mut ret);
 
@@ -301,7 +302,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyLis
     // Our allocator/panic runtime may not have been linked above if it wasn't
     // explicitly linked, which is the case for any injected dependency. Handle
     // that here and activate them.
-    activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
+    activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
                           &|cnum| tcx.is_panic_runtime(cnum));
     activate_injected_allocator(sess, &mut ret);
 
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 37d79f408f3..ebc79646662 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -63,12 +63,13 @@ pub fn find_entry_point(session: &Session,
     });
     if !any_exe {
         // No need to find a main function
+        session.entry_fn.set(None);
         return
     }
 
     // If the user wants no main function at all, then stop here.
     if attr::contains_name(&hir_map.krate().attrs, "no_main") {
-        session.entry_type.set(Some(config::EntryNone));
+        session.entry_fn.set(None);
         return
     }
 
@@ -153,17 +154,15 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
 }
 
 fn configure_main(this: &mut EntryContext, crate_name: &str) {
-    if this.start_fn.is_some() {
-        *this.session.entry_fn.borrow_mut() = this.start_fn;
-        this.session.entry_type.set(Some(config::EntryStart));
-    } else if this.attr_main_fn.is_some() {
-        *this.session.entry_fn.borrow_mut() = this.attr_main_fn;
-        this.session.entry_type.set(Some(config::EntryMain));
-    } else if this.main_fn.is_some() {
-        *this.session.entry_fn.borrow_mut() = this.main_fn;
-        this.session.entry_type.set(Some(config::EntryMain));
+    if let Some((node_id, span)) = this.start_fn {
+        this.session.entry_fn.set(Some((node_id, span, config::EntryStart)));
+    } else if let Some((node_id, span)) = this.attr_main_fn {
+        this.session.entry_fn.set(Some((node_id, span, config::EntryMain)));
+    } else if let Some((node_id, span)) = this.main_fn {
+        this.session.entry_fn.set(Some((node_id, span, config::EntryMain)));
     } else {
         // No main function
+        this.session.entry_fn.set(None);
         let mut err = struct_err!(this.session, E0601,
             "`main` function not found in crate `{}`", crate_name);
         if !this.non_main_fns.is_empty() {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 28524678e99..2cc5a4a8fe6 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -404,10 +404,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 self.select_from_expr(&base);
             }
 
-            hir::ExprTupField(ref base, _) => {         // base.<n>
-                self.select_from_expr(&base);
-            }
-
             hir::ExprIndex(ref lhs, ref rhs) => {       // lhs[rhs]
                 self.select_from_expr(&lhs);
                 self.consume_expr(&rhs);
@@ -663,11 +659,15 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         match with_cmt.ty.sty {
             ty::TyAdt(adt, substs) if adt.is_struct() => {
                 // Consume those fields of the with expression that are needed.
-                for with_field in &adt.non_enum_variant().fields {
-                    if !contains_field_named(with_field, fields) {
+                for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
+                    let is_mentioned = fields.iter().any(|f| {
+                        self.tcx().field_index(f.id, self.mc.tables) == f_index
+                    });
+                    if !is_mentioned {
                         let cmt_field = self.mc.cat_field(
                             &*with_expr,
                             with_cmt.clone(),
+                            f_index,
                             with_field.name,
                             with_field.ty(self.tcx(), substs)
                         );
@@ -691,14 +691,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         // walk the with expression so that complex expressions
         // are properly handled.
         self.walk_expr(with_expr);
-
-        fn contains_field_named(field: &ty::FieldDef,
-                                fields: &[hir::Field])
-                                -> bool
-        {
-            fields.iter().any(
-                |f| f.name.node == field.name)
-        }
     }
 
     // Invoke the appropriate delegate calls for anything that gets
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 966353b53a9..11dc2a81885 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -476,7 +476,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
       }
 
       // otherwise, live nodes are not required:
-      hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
+      hir::ExprIndex(..) | hir::ExprField(..) |
       hir::ExprArray(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) |
       hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) |
       hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(..) |
@@ -912,10 +912,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
               self.propagate_through_expr(&e, succ)
           }
 
-          hir::ExprTupField(ref e, _) => {
-              self.propagate_through_expr(&e, succ)
-          }
-
           hir::ExprClosure(.., blk_id, _, _) => {
               debug!("{} is an ExprClosure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
 
@@ -1226,7 +1222,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         match expr.node {
             hir::ExprPath(_) => succ,
             hir::ExprField(ref e, _) => self.propagate_through_expr(&e, succ),
-            hir::ExprTupField(ref e, _) => self.propagate_through_expr(&e, succ),
             _ => self.propagate_through_expr(expr, succ)
         }
     }
@@ -1419,7 +1414,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
       // no correctness conditions related to liveness
       hir::ExprCall(..) | hir::ExprMethodCall(..) | hir::ExprIf(..) |
       hir::ExprMatch(..) | hir::ExprWhile(..) | hir::ExprLoop(..) |
-      hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
+      hir::ExprIndex(..) | hir::ExprField(..) |
       hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprBinary(..) |
       hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) |
       hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 5875e5e4097..6f41f07dce8 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -62,7 +62,6 @@
 
 pub use self::PointerKind::*;
 pub use self::InteriorKind::*;
-pub use self::FieldName::*;
 pub use self::MutabilityCategory::*;
 pub use self::AliasableReason::*;
 pub use self::Note::*;
@@ -81,10 +80,11 @@ use ty::fold::TypeFoldable;
 use hir::{MutImmutable, MutMutable, PatKind};
 use hir::pat_util::EnumerateAndAdjustIterator;
 use hir;
-use syntax::ast;
+use syntax::ast::{self, Name};
 use syntax_pos::Span;
 
 use std::fmt;
+use std::hash::{Hash, Hasher};
 use rustc_data_structures::sync::Lrc;
 use std::rc::Rc;
 use util::nodemap::ItemLocalSet;
@@ -129,14 +129,25 @@ pub enum PointerKind<'tcx> {
 // base without a pointer dereference", e.g. a field
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum InteriorKind {
-    InteriorField(FieldName),
+    InteriorField(FieldIndex),
     InteriorElement(InteriorOffsetKind),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub enum FieldName {
-    NamedField(ast::Name),
-    PositionalField(usize)
+// Contains index of a field that is actually used for loan path comparisons and
+// string representation of the field that should be used only for diagnostics.
+#[derive(Clone, Copy, Eq)]
+pub struct FieldIndex(pub usize, pub Name);
+
+impl PartialEq for FieldIndex {
+    fn eq(&self, rhs: &Self) -> bool {
+        self.0 == rhs.0
+    }
+}
+
+impl Hash for FieldIndex {
+    fn hash<H: Hasher>(&self, h: &mut H) {
+        self.0.hash(h)
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
@@ -198,7 +209,7 @@ pub enum ImmutabilityBlame<'tcx> {
 }
 
 impl<'tcx> cmt_<'tcx> {
-    fn resolve_field(&self, field_name: FieldName) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)>
+    fn resolve_field(&self, field_index: usize) -> Option<(&'tcx ty::AdtDef, &'tcx ty::FieldDef)>
     {
         let adt_def = match self.ty.sty {
             ty::TyAdt(def, _) => def,
@@ -215,11 +226,7 @@ impl<'tcx> cmt_<'tcx> {
                 &adt_def.variants[0]
             }
         };
-        let field_def = match field_name {
-            NamedField(name) => variant_def.field_named(name),
-            PositionalField(idx) => &variant_def.fields[idx]
-        };
-        Some((adt_def, field_def))
+        Some((adt_def, &variant_def.fields[field_index]))
     }
 
     pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
@@ -230,8 +237,8 @@ impl<'tcx> cmt_<'tcx> {
                 match base_cmt.cat {
                     Categorization::Local(node_id) =>
                         Some(ImmutabilityBlame::LocalDeref(node_id)),
-                    Categorization::Interior(ref base_cmt, InteriorField(field_name)) => {
-                        base_cmt.resolve_field(field_name).map(|(adt_def, field_def)| {
+                    Categorization::Interior(ref base_cmt, InteriorField(field_index)) => {
+                        base_cmt.resolve_field(field_index.0).map(|(adt_def, field_def)| {
                             ImmutabilityBlame::AdtFieldDeref(adt_def, field_def)
                         })
                     }
@@ -646,12 +653,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                    expr.id,
                    expr,
                    base_cmt);
-            Ok(self.cat_field(expr, base_cmt, f_name.node, expr_ty))
-          }
-
-          hir::ExprTupField(ref base, idx) => {
-            let base_cmt = self.cat_expr(&base)?;
-            Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
+            let f_index = self.tcx.field_index(expr.id, self.tables);
+            Ok(self.cat_field(expr, base_cmt, f_index, f_name.node, expr_ty))
           }
 
           hir::ExprIndex(ref base, _) => {
@@ -979,14 +982,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     pub fn cat_field<N:ast_node>(&self,
                                  node: &N,
                                  base_cmt: cmt<'tcx>,
-                                 f_name: ast::Name,
+                                 f_index: usize,
+                                 f_name: Name,
                                  f_ty: Ty<'tcx>)
                                  -> cmt<'tcx> {
         let ret = Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
             mutbl: base_cmt.mutbl.inherit(),
-            cat: Categorization::Interior(base_cmt, InteriorField(NamedField(f_name))),
+            cat: Categorization::Interior(base_cmt, InteriorField(FieldIndex(f_index, f_name))),
             ty: f_ty,
             note: NoteNone
         });
@@ -994,24 +998,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         ret
     }
 
-    pub fn cat_tup_field<N:ast_node>(&self,
-                                     node: &N,
-                                     base_cmt: cmt<'tcx>,
-                                     f_idx: usize,
-                                     f_ty: Ty<'tcx>)
-                                     -> cmt<'tcx> {
-        let ret = Rc::new(cmt_ {
-            id: node.id(),
-            span: node.span(),
-            mutbl: base_cmt.mutbl.inherit(),
-            cat: Categorization::Interior(base_cmt, InteriorField(PositionalField(f_idx))),
-            ty: f_ty,
-            note: NoteNone
-        });
-        debug!("cat_tup_field ret {:?}", ret);
-        ret
-    }
-
     fn cat_overloaded_place(&self,
                              expr: &hir::Expr,
                              base: &hir::Expr,
@@ -1292,8 +1278,8 @@ 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 subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
-                                                   InteriorField(PositionalField(i)));
+                let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
+                let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
                 self.cat_pattern_(subcmt, &subpat, op)?;
             }
           }
@@ -1315,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 cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty);
+                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);
                 self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
             }
           }
@@ -1332,8 +1319,8 @@ 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 subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
-                                                   InteriorField(PositionalField(i)));
+                let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
+                let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior);
                 self.cat_pattern_(subcmt, &subpat, op)?;
             }
           }
@@ -1516,12 +1503,9 @@ impl<'tcx> cmt_<'tcx> {
                     }
                 }
             }
-            Categorization::Interior(_, InteriorField(NamedField(_))) => {
+            Categorization::Interior(_, InteriorField(..)) => {
                 "field".to_string()
             }
-            Categorization::Interior(_, InteriorField(PositionalField(_))) => {
-                "anonymous field".to_string()
-            }
             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index)) => {
                 "indexed content".to_string()
             }
@@ -1554,8 +1538,7 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
 impl fmt::Debug for InteriorKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            InteriorField(NamedField(fld)) => write!(f, "{}", fld),
-            InteriorField(PositionalField(i)) => write!(f, "#{}", i),
+            InteriorField(FieldIndex(_, info)) => write!(f, "{}", info),
             InteriorElement(..) => write!(f, "[]"),
         }
     }
diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs
index 6c87f750376..077a20315a2 100644
--- a/src/librustc/middle/recursion_limit.rs
+++ b/src/librustc/middle/recursion_limit.rs
@@ -18,17 +18,17 @@
 use session::Session;
 use syntax::ast;
 
-use std::cell::Cell;
+use rustc_data_structures::sync::Once;
 
 pub fn update_limits(sess: &Session, krate: &ast::Crate) {
     update_limit(sess, krate, &sess.recursion_limit, "recursion_limit",
-                 "recursion limit");
+                 "recursion limit", 64);
     update_limit(sess, krate, &sess.type_length_limit, "type_length_limit",
-                 "type length limit");
+                 "type length limit", 1048576);
 }
 
-fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Cell<usize>,
-                name: &str, description: &str) {
+fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Once<usize>,
+                name: &str, description: &str, default: usize) {
     for attr in &krate.attrs {
         if !attr.check_name(name) {
             continue;
@@ -45,4 +45,5 @@ fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Cell<usize>,
                   "malformed {} attribute, expected #![{}=\"N\"]",
                   description, name);
     }
+    limit.set(default);
 }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 7e1b7c08c3d..42483c83f4b 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -1307,7 +1307,6 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>,
                 hir::ExprAddrOf(_, ref subexpr) |
                 hir::ExprUnary(hir::UnDeref, ref subexpr) |
                 hir::ExprField(ref subexpr, _) |
-                hir::ExprTupField(ref subexpr, _) |
                 hir::ExprIndex(ref subexpr, _) => {
                     expr = &subexpr;
                 }
diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs
index 9b75c19a875..1ed5a22257c 100644
--- a/src/librustc/mir/cache.rs
+++ b/src/librustc/mir/cache.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cell::{Ref, RefCell};
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::sync::{RwLock, ReadGuard};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use ich::StableHashingContext;
@@ -19,7 +19,7 @@ use rustc_serialize as serialize;
 
 #[derive(Clone, Debug)]
 pub struct Cache {
-    predecessors: RefCell<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
+    predecessors: RwLock<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
 }
 
 
@@ -46,7 +46,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for Cache {
 impl Cache {
     pub fn new() -> Self {
         Cache {
-            predecessors: RefCell::new(None)
+            predecessors: RwLock::new(None)
         }
     }
 
@@ -55,12 +55,12 @@ impl Cache {
         *self.predecessors.borrow_mut() = None;
     }
 
-    pub fn predecessors(&self, mir: &Mir) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self, mir: &Mir) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         if self.predecessors.borrow().is_none() {
             *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
         }
 
-        Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
+        ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
     }
 }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 9ed4e6a8e00..33f52ab09c8 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -34,7 +34,7 @@ use util::ppaux;
 use std::slice;
 use hir::{self, InlineAsm};
 use std::borrow::{Cow};
-use std::cell::Ref;
+use rustc_data_structures::sync::ReadGuard;
 use std::fmt::{self, Debug, Formatter, Write};
 use std::{iter, mem, u32};
 use std::ops::{Index, IndexMut};
@@ -187,13 +187,13 @@ impl<'tcx> Mir<'tcx> {
     }
 
     #[inline]
-    pub fn predecessors(&self) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         self.cache.predecessors(self)
     }
 
     #[inline]
-    pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
-        Ref::map(self.predecessors(), |p| &p[bb])
+    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
+        ReadGuard::map(self.predecessors(), |p| &p[bb])
     }
 
     #[inline]
diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs
index 64f405e0f24..df4060e71e5 100644
--- a/src/librustc/session/code_stats.rs
+++ b/src/librustc/session/code_stats.rs
@@ -62,6 +62,7 @@ pub struct TypeSizeInfo {
     pub type_description: String,
     pub align: u64,
     pub overall_size: u64,
+    pub packed: bool,
     pub opt_discr_size: Option<u64>,
     pub variants: Vec<VariantInfo>,
 }
@@ -79,6 +80,7 @@ impl CodeStats {
                                          type_desc: S,
                                          align: Align,
                                          overall_size: Size,
+                                         packed: bool,
                                          opt_discr_size: Option<Size>,
                                          variants: Vec<VariantInfo>) {
         let info = TypeSizeInfo {
@@ -86,6 +88,7 @@ impl CodeStats {
             type_description: type_desc.to_string(),
             align: align.abi(),
             overall_size: overall_size.bytes(),
+            packed: packed,
             opt_discr_size: opt_discr_size.map(|s| s.bytes()),
             variants,
         };
@@ -153,24 +156,26 @@ impl CodeStats {
                 for field in fields.iter() {
                     let FieldInfo { ref name, offset, size, align } = *field;
 
-                    // Include field alignment in output only if it caused padding injection
-                    if min_offset != offset {
-                        if offset > min_offset {
-                            let pad = offset - min_offset;
-                            println!("print-type-size {}padding: {} bytes",
-                                     indent, pad);
-                            println!("print-type-size {}field `.{}`: {} bytes, \
-                                      alignment: {} bytes",
-                                     indent, name, size, align);
-                        } else {
-                            println!("print-type-size {}field `.{}`: {} bytes, \
-                                      offset: {} bytes, \
-                                      alignment: {} bytes",
-                                     indent, name, size, offset, align);
-                        }
-                    } else {
+                    if offset > min_offset {
+                        let pad = offset - min_offset;
+                        println!("print-type-size {}padding: {} bytes",
+                                 indent, pad);
+                    }
+
+                    if offset < min_offset {
+                        // if this happens something is very wrong
+                        println!("print-type-size {}field `.{}`: {} bytes, \
+                                  offset: {} bytes, \
+                                  alignment: {} bytes",
+                                 indent, name, size, offset, align);
+                    } else if info.packed || offset == min_offset {
                         println!("print-type-size {}field `.{}`: {} bytes",
                                  indent, name, size);
+                    } else {
+                        // Include field alignment in output only if it caused padding injection
+                        println!("print-type-size {}field `.{}`: {} bytes, \
+                                  alignment: {} bytes",
+                                 indent, name, size, align);
                     }
 
                     min_offset = offset + size;
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index a07370e1e42..8b6a8fea4ca 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -614,13 +614,11 @@ impl Options {
 
 // The type of entry function, so
 // users can have their own entry
-// functions that don't start a
-// scheduler
+// functions
 #[derive(Copy, Clone, PartialEq)]
 pub enum EntryFnType {
     EntryMain,
     EntryStart,
-    EntryNone,
 }
 
 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
@@ -1861,6 +1859,13 @@ pub fn build_session_options_and_crate_config(
         );
     }
 
+    if debugging_opts.query_threads.unwrap_or(1) > 1 && debugging_opts.fuel.is_some() {
+        early_error(
+            error_format,
+            "Optimization fuel is incompatible with multiple query threads",
+        );
+    }
+
     if codegen_units == Some(0) {
         early_error(
             error_format,
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 77cf50a8341..8f2043fdfc6 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -22,11 +22,11 @@ use middle::dependency_format;
 use session::search_paths::PathKind;
 use session::config::{DebugInfoLevel, OutputType};
 use ty::tls;
-use util::nodemap::{FxHashMap, FxHashSet};
+use util::nodemap::{FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
 use util::common::ProfileQueriesMsg;
 
-use rustc_data_structures::sync::{Lrc, Lock};
+use rustc_data_structures::sync::{Lrc, Lock, LockCell, OneThread, Once};
 
 use syntax::ast::NodeId;
 use errors::{self, DiagnosticBuilder, DiagnosticId};
@@ -46,15 +46,16 @@ use rustc_back::target::{Target, TargetTriple};
 use rustc_data_structures::flock;
 use jobserver::Client;
 
+use std;
 use std::cell::{self, Cell, RefCell};
 use std::collections::HashMap;
 use std::env;
 use std::fmt;
 use std::io::Write;
 use std::path::{Path, PathBuf};
-use std::sync::{Once, ONCE_INIT};
 use std::time::Duration;
 use std::sync::mpsc;
+use std::sync::atomic::{AtomicUsize, Ordering};
 
 mod code_stats;
 pub mod config;
@@ -69,10 +70,9 @@ pub struct Session {
     pub opts: config::Options,
     pub parse_sess: ParseSess,
     /// For a library crate, this is always none
-    pub entry_fn: RefCell<Option<(NodeId, Span)>>,
-    pub entry_type: Cell<Option<config::EntryFnType>>,
-    pub plugin_registrar_fn: Cell<Option<ast::NodeId>>,
-    pub derive_registrar_fn: Cell<Option<ast::NodeId>>,
+    pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
+    pub plugin_registrar_fn: Once<Option<ast::NodeId>>,
+    pub derive_registrar_fn: Once<Option<ast::NodeId>>,
     pub default_sysroot: Option<PathBuf>,
     /// The name of the root source file of the crate, in the local file system.
     /// `None` means that there is no source file.
@@ -80,50 +80,54 @@ pub struct Session {
     /// The directory the compiler has been executed in plus a flag indicating
     /// if the value stored here has been affected by path remapping.
     pub working_dir: (PathBuf, bool),
-    pub lint_store: RefCell<lint::LintStore>,
-    pub buffered_lints: RefCell<Option<lint::LintBuffer>>,
+
+    // FIXME: lint_store and buffered_lints are not thread-safe,
+    // but are only used in a single thread
+    pub lint_store: OneThread<RefCell<lint::LintStore>>,
+    pub buffered_lints: OneThread<RefCell<Option<lint::LintBuffer>>>,
+
     /// Set of (DiagnosticId, Option<Span>, message) tuples tracking
     /// (sub)diagnostics that have been set once, but should not be set again,
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: RefCell<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
-    pub plugin_llvm_passes: RefCell<Vec<String>>,
-    pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
-    pub crate_types: RefCell<Vec<config::CrateType>>,
-    pub dependency_formats: RefCell<dependency_format::Dependencies>,
+    pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
+    pub plugin_attributes: OneThread<RefCell<Vec<(String, AttributeType)>>>,
+    pub crate_types: Once<Vec<config::CrateType>>,
+    pub dependency_formats: Once<dependency_format::Dependencies>,
     /// The crate_disambiguator is constructed out of all the `-C metadata`
     /// arguments passed to the compiler. Its value together with the crate-name
     /// forms a unique global identifier for the crate. It is used to allow
     /// multiple crates with the same name to coexist. See the
     /// trans::back::symbol_names module for more information.
-    pub crate_disambiguator: RefCell<Option<CrateDisambiguator>>,
+    pub crate_disambiguator: Once<CrateDisambiguator>,
 
-    features: RefCell<Option<feature_gate::Features>>,
+    features: Once<feature_gate::Features>,
 
     /// The maximum recursion limit for potentially infinitely recursive
     /// operations such as auto-dereference and monomorphization.
-    pub recursion_limit: Cell<usize>,
+    pub recursion_limit: Once<usize>,
 
     /// The maximum length of types during monomorphization.
-    pub type_length_limit: Cell<usize>,
+    pub type_length_limit: Once<usize>,
 
     /// The maximum number of stackframes allowed in const eval
-    pub const_eval_stack_frame_limit: Cell<usize>,
+    pub const_eval_stack_frame_limit: usize,
     /// The maximum number miri steps per constant
-    pub const_eval_step_limit: Cell<usize>,
+    pub const_eval_step_limit: usize,
 
     /// The metadata::creader module may inject an allocator/panic_runtime
     /// dependency if it didn't already find one, and this tracks what was
     /// injected.
-    pub injected_allocator: Cell<Option<CrateNum>>,
-    pub allocator_kind: Cell<Option<AllocatorKind>>,
-    pub injected_panic_runtime: Cell<Option<CrateNum>>,
+    pub injected_allocator: Once<Option<CrateNum>>,
+    pub allocator_kind: Once<Option<AllocatorKind>>,
+    pub injected_panic_runtime: Once<Option<CrateNum>>,
 
     /// Map from imported macro spans (which consist of
     /// the localized span for the macro body) to the
     /// macro name and definition span in the source crate.
-    pub imported_macro_spans: RefCell<HashMap<Span, (String, Span)>>,
+    pub imported_macro_spans: OneThread<RefCell<HashMap<Span, (String, Span)>>>,
 
-    incr_comp_session: RefCell<IncrCompSession>,
+    incr_comp_session: OneThread<RefCell<IncrCompSession>>,
 
     /// A cache of attributes ignored by StableHashingContext
     pub ignored_attr_names: FxHashSet<Symbol>,
@@ -135,53 +139,42 @@ pub struct Session {
     pub perf_stats: PerfStats,
 
     /// Data about code being compiled, gathered during compilation.
-    pub code_stats: RefCell<CodeStats>,
+    pub code_stats: Lock<CodeStats>,
 
-    next_node_id: Cell<ast::NodeId>,
+    next_node_id: OneThread<Cell<ast::NodeId>>,
 
     /// If -zfuel=crate=n is specified, Some(crate).
     optimization_fuel_crate: Option<String>,
     /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
-    optimization_fuel_limit: Cell<u64>,
+    optimization_fuel_limit: LockCell<u64>,
     /// We're rejecting all further optimizations.
-    out_of_fuel: Cell<bool>,
+    out_of_fuel: LockCell<bool>,
 
     // The next two are public because the driver needs to read them.
     /// If -zprint-fuel=crate, Some(crate).
     pub print_fuel_crate: Option<String>,
     /// Always set to zero and incremented so that we can print fuel expended by a crate.
-    pub print_fuel: Cell<u64>,
+    pub print_fuel: LockCell<u64>,
 
     /// Loaded up early on in the initialization of this `Session` to avoid
     /// false positives about a job server in our environment.
     pub jobserver_from_env: Option<Client>,
 
     /// Metadata about the allocators for the current crate being compiled
-    pub has_global_allocator: Cell<bool>,
+    pub has_global_allocator: Once<bool>,
 }
 
 pub struct PerfStats {
-    /// The accumulated time needed for computing the SVH of the crate
-    pub svh_time: Cell<Duration>,
-    /// The accumulated time spent on computing incr. comp. hashes
-    pub incr_comp_hashes_time: Cell<Duration>,
-    /// The number of incr. comp. hash computations performed
-    pub incr_comp_hashes_count: Cell<u64>,
-    /// The number of bytes hashed when computing ICH values
-    pub incr_comp_bytes_hashed: Cell<u64>,
     /// The accumulated time spent on computing symbol hashes
-    pub symbol_hash_time: Cell<Duration>,
+    pub symbol_hash_time: Lock<Duration>,
     /// The accumulated time spent decoding def path tables from metadata
-    pub decode_def_path_tables_time: Cell<Duration>,
+    pub decode_def_path_tables_time: Lock<Duration>,
     /// Total number of values canonicalized queries constructed.
-    pub queries_canonicalized: Cell<usize>,
-    /// Number of times we canonicalized a value and found that the
-    /// result had already been canonicalized.
-    pub canonicalized_values_allocated: Cell<usize>,
+    pub queries_canonicalized: AtomicUsize,
     /// Number of times this query is invoked.
-    pub normalize_ty_after_erasing_regions: Cell<usize>,
+    pub normalize_ty_after_erasing_regions: AtomicUsize,
     /// Number of times this query is invoked.
-    pub normalize_projection_ty: Cell<usize>,
+    pub normalize_projection_ty: AtomicUsize,
 }
 
 /// Enum to support dispatch of one-time diagnostics (in Session.diag_once)
@@ -209,10 +202,7 @@ impl From<&'static lint::Lint> for DiagnosticMessageId {
 
 impl Session {
     pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
-        match *self.crate_disambiguator.borrow() {
-            Some(value) => value,
-            None => bug!("accessing disambiguator before initialization"),
-        }
+        *self.crate_disambiguator.get()
     }
 
     pub fn struct_span_warn<'a, S: Into<MultiSpan>>(
@@ -539,18 +529,12 @@ impl Session {
     /// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents
     /// dependency tracking. Use tcx.features() instead.
     #[inline]
-    pub fn features_untracked(&self) -> cell::Ref<feature_gate::Features> {
-        let features = self.features.borrow();
-
-        if features.is_none() {
-            bug!("Access to Session::features before it is initialized");
-        }
-
-        cell::Ref::map(features, |r| r.as_ref().unwrap())
+    pub fn features_untracked(&self) -> &feature_gate::Features {
+        self.features.get()
     }
 
     pub fn init_features(&self, features: feature_gate::Features) {
-        *(self.features.borrow_mut()) = Some(features);
+        self.features.set(features);
     }
 
     /// Calculates the flavor of LTO to use for this compilation.
@@ -835,51 +819,25 @@ impl Session {
 
     pub fn print_perf_stats(&self) {
         println!(
-            "Total time spent computing SVHs:               {}",
-            duration_to_secs_str(self.perf_stats.svh_time.get())
-        );
-        println!(
-            "Total time spent computing incr. comp. hashes: {}",
-            duration_to_secs_str(self.perf_stats.incr_comp_hashes_time.get())
-        );
-        println!(
-            "Total number of incr. comp. hashes computed:   {}",
-            self.perf_stats.incr_comp_hashes_count.get()
-        );
-        println!(
-            "Total number of bytes hashed for incr. comp.:  {}",
-            self.perf_stats.incr_comp_bytes_hashed.get()
-        );
-        if self.perf_stats.incr_comp_hashes_count.get() != 0 {
-            println!(
-                "Average bytes hashed per incr. comp. HIR node: {}",
-                self.perf_stats.incr_comp_bytes_hashed.get()
-                    / self.perf_stats.incr_comp_hashes_count.get()
-            );
-        } else {
-            println!("Average bytes hashed per incr. comp. HIR node: N/A");
-        }
-        println!(
             "Total time spent computing symbol hashes:      {}",
-            duration_to_secs_str(self.perf_stats.symbol_hash_time.get())
+            duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock())
         );
         println!(
             "Total time spent decoding DefPath tables:      {}",
-            duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())
+            duration_to_secs_str(*self.perf_stats.decode_def_path_tables_time.lock())
         );
         println!("Total queries canonicalized:                   {}",
-                 self.perf_stats.queries_canonicalized.get());
-        println!("Total canonical values interned:               {}",
-                 self.perf_stats.canonicalized_values_allocated.get());
+                 self.perf_stats.queries_canonicalized.load(Ordering::Relaxed));
         println!("normalize_ty_after_erasing_regions:            {}",
-                 self.perf_stats.normalize_ty_after_erasing_regions.get());
+                 self.perf_stats.normalize_ty_after_erasing_regions.load(Ordering::Relaxed));
         println!("normalize_projection_ty:                       {}",
-                 self.perf_stats.normalize_projection_ty.get());
+                 self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed));
     }
 
     /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
     /// This expends fuel if applicable, and records fuel if applicable.
     pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+        assert!(self.query_threads() == 1);
         let mut ret = true;
         match self.optimization_fuel_crate {
             Some(ref c) if c == crate_name => {
@@ -1109,9 +1067,9 @@ pub fn build_session_(
 
     let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
     let optimization_fuel_limit =
-        Cell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
+        LockCell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
     let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
-    let print_fuel = Cell::new(0);
+    let print_fuel = LockCell::new(0);
 
     let working_dir = match env::current_dir() {
         Ok(dir) => dir,
@@ -1127,52 +1085,46 @@ pub fn build_session_(
         opts: sopts,
         parse_sess: p_s,
         // For a library crate, this is always none
-        entry_fn: RefCell::new(None),
-        entry_type: Cell::new(None),
-        plugin_registrar_fn: Cell::new(None),
-        derive_registrar_fn: Cell::new(None),
+        entry_fn: Once::new(),
+        plugin_registrar_fn: Once::new(),
+        derive_registrar_fn: Once::new(),
         default_sysroot,
         local_crate_source_file,
         working_dir,
-        lint_store: RefCell::new(lint::LintStore::new()),
-        buffered_lints: RefCell::new(Some(lint::LintBuffer::new())),
+        lint_store: OneThread::new(RefCell::new(lint::LintStore::new())),
+        buffered_lints: OneThread::new(RefCell::new(Some(lint::LintBuffer::new()))),
         one_time_diagnostics: RefCell::new(FxHashSet()),
-        plugin_llvm_passes: RefCell::new(Vec::new()),
-        plugin_attributes: RefCell::new(Vec::new()),
-        crate_types: RefCell::new(Vec::new()),
-        dependency_formats: RefCell::new(FxHashMap()),
-        crate_disambiguator: RefCell::new(None),
-        features: RefCell::new(None),
-        recursion_limit: Cell::new(64),
-        type_length_limit: Cell::new(1048576),
-        const_eval_stack_frame_limit: Cell::new(100),
-        const_eval_step_limit: Cell::new(1_000_000),
-        next_node_id: Cell::new(NodeId::new(1)),
-        injected_allocator: Cell::new(None),
-        allocator_kind: Cell::new(None),
-        injected_panic_runtime: Cell::new(None),
-        imported_macro_spans: RefCell::new(HashMap::new()),
-        incr_comp_session: RefCell::new(IncrCompSession::NotInitialized),
+        plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
+        plugin_attributes: OneThread::new(RefCell::new(Vec::new())),
+        crate_types: Once::new(),
+        dependency_formats: Once::new(),
+        crate_disambiguator: Once::new(),
+        features: Once::new(),
+        recursion_limit: Once::new(),
+        type_length_limit: Once::new(),
+        const_eval_stack_frame_limit: 100,
+        const_eval_step_limit: 1_000_000,
+        next_node_id: OneThread::new(Cell::new(NodeId::new(1))),
+        injected_allocator: Once::new(),
+        allocator_kind: Once::new(),
+        injected_panic_runtime: Once::new(),
+        imported_macro_spans: OneThread::new(RefCell::new(HashMap::new())),
+        incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         ignored_attr_names: ich::compute_ignored_attr_names(),
         profile_channel: Lock::new(None),
         perf_stats: PerfStats {
-            svh_time: Cell::new(Duration::from_secs(0)),
-            incr_comp_hashes_time: Cell::new(Duration::from_secs(0)),
-            incr_comp_hashes_count: Cell::new(0),
-            incr_comp_bytes_hashed: Cell::new(0),
-            symbol_hash_time: Cell::new(Duration::from_secs(0)),
-            decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
-            queries_canonicalized: Cell::new(0),
-            canonicalized_values_allocated: Cell::new(0),
-            normalize_ty_after_erasing_regions: Cell::new(0),
-            normalize_projection_ty: Cell::new(0),
+            symbol_hash_time: Lock::new(Duration::from_secs(0)),
+            decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
+            queries_canonicalized: AtomicUsize::new(0),
+            normalize_ty_after_erasing_regions: AtomicUsize::new(0),
+            normalize_projection_ty: AtomicUsize::new(0),
         },
-        code_stats: RefCell::new(CodeStats::new()),
+        code_stats: Lock::new(CodeStats::new()),
         optimization_fuel_crate,
         optimization_fuel_limit,
         print_fuel_crate,
         print_fuel,
-        out_of_fuel: Cell::new(false),
+        out_of_fuel: LockCell::new(false),
         // Note that this is unsafe because it may misinterpret file descriptors
         // on Unix as jobserver file descriptors. We hopefully execute this near
         // the beginning of the process though to ensure we don't get false
@@ -1184,13 +1136,13 @@ pub fn build_session_(
         // per-process.
         jobserver_from_env: unsafe {
             static mut GLOBAL_JOBSERVER: *mut Option<Client> = 0 as *mut _;
-            static INIT: Once = ONCE_INIT;
+            static INIT: std::sync::Once = std::sync::ONCE_INIT;
             INIT.call_once(|| {
                 GLOBAL_JOBSERVER = Box::into_raw(Box::new(Client::from_env()));
             });
             (*GLOBAL_JOBSERVER).clone()
         },
-        has_global_allocator: Cell::new(false),
+        has_global_allocator: Once::new(),
     };
 
     sess
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index d2bde14732b..2af4c3f9fd4 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -378,7 +378,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
 
         for param in generics.types.iter() {
-            let name = param.name.as_str().to_string();
+            let name = param.name.to_string();
             let ty = trait_ref.substs.type_for_def(param);
             let ty_str = ty.to_string();
             flags.push((name.clone(),
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index b30fb2ce016..32fd93cf20a 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -23,13 +23,12 @@ use infer::outlives::env::OutlivesEnvironment;
 use middle::region;
 use middle::const_val::ConstEvalErr;
 use ty::subst::Substs;
-use ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, ToPredicate};
+use ty::{self, AdtKind, Slice, Ty, TyCtxt, TypeFoldable, ToPredicate};
 use ty::error::{ExpectedFound, TypeError};
 use infer::{InferCtxt};
 
 use rustc_data_structures::sync::Lrc;
 use std::rc::Rc;
-use std::convert::From;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -280,37 +279,39 @@ pub enum QuantifierKind {
     Existential,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Goal<'tcx> {
-    // FIXME: use interned refs instead of `Box`
-    Implies(Vec<Clause<'tcx>>, Box<Goal<'tcx>>),
-    And(Box<Goal<'tcx>>, Box<Goal<'tcx>>),
-    Not(Box<Goal<'tcx>>),
+    Implies(&'tcx Slice<Clause<'tcx>>, &'tcx Goal<'tcx>),
+    And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>),
+    Not(&'tcx Goal<'tcx>),
     DomainGoal(DomainGoal<'tcx>),
-    Quantified(QuantifierKind, Box<ty::Binder<Goal<'tcx>>>)
-}
-
-impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
-    fn from(domain_goal: DomainGoal<'tcx>) -> Self {
-        Goal::DomainGoal(domain_goal)
-    }
+    Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>)
 }
 
-impl<'tcx> From<PolyDomainGoal<'tcx>> for Goal<'tcx> {
-    fn from(domain_goal: PolyDomainGoal<'tcx>) -> Self {
+impl<'tcx> Goal<'tcx> {
+    pub fn from_poly_domain_goal<'a>(
+        domain_goal: PolyDomainGoal<'tcx>,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ) -> Goal<'tcx> {
         match domain_goal.no_late_bound_regions() {
             Some(p) => p.into(),
             None => Goal::Quantified(
                 QuantifierKind::Universal,
-                Box::new(domain_goal.map_bound(|p| p.into()))
+                domain_goal.map_bound(|p| tcx.mk_goal(Goal::from(p)))
             ),
         }
     }
 }
 
+impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
+    fn from(domain_goal: DomainGoal<'tcx>) -> Self {
+        Goal::DomainGoal(domain_goal)
+    }
+}
+
 /// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
 /// Harrop Formulas".
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Clause<'tcx> {
     Implies(ProgramClause<'tcx>),
     ForAll(ty::Binder<ProgramClause<'tcx>>),
@@ -322,13 +323,13 @@ pub enum Clause<'tcx> {
 /// it with the reverse implication operator `:-` to emphasize the way
 /// that programs are actually solved (via backchaining, which starts
 /// with the goal to solve and proceeds from there).
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct ProgramClause<'tcx> {
     /// This goal will be considered true...
     pub goal: DomainGoal<'tcx>,
 
     /// ...if we can prove these hypotheses (there may be no hypotheses at all):
-    pub hypotheses: Vec<Goal<'tcx>>,
+    pub hypotheses: &'tcx Slice<Goal<'tcx>>,
 }
 
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index a1018cb946a..405dafdff2b 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -289,7 +289,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
         let trait_str = tcx.item_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
         let generic_map = generics.types.iter().map(|param| {
-            (param.name.as_str().to_string(),
+            (param.name.to_string(),
              trait_ref.substs.type_for_def(param).to_string())
         }).collect::<FxHashMap<String, String>>();
 
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 2a62d0b5ee3..9f21ea14d0f 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -345,7 +345,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
                     Reveal::UserFacing => ty,
 
                     Reveal::All => {
-                        let recursion_limit = self.tcx().sess.recursion_limit.get();
+                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
                         if self.depth >= recursion_limit {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
@@ -566,7 +566,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
                     found cache entry: in-progress");
 
             // But for now, let's classify this as an overflow:
-            let recursion_limit = selcx.tcx().sess.recursion_limit.get();
+            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
             let obligation = Obligation::with_depth(cause.clone(),
                                                     recursion_limit,
                                                     param_env,
@@ -848,7 +848,7 @@ fn project_type<'cx, 'gcx, 'tcx>(
     debug!("project(obligation={:?})",
            obligation);
 
-    let recursion_limit = selcx.tcx().sess.recursion_limit.get();
+    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
         selcx.infcx().report_overflow_error(&obligation, true);
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 63f50cff4c2..5e0a4ca3305 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -109,7 +109,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
                     Reveal::UserFacing => ty,
 
                     Reveal::All => {
-                        let recursion_limit = self.tcx().sess.recursion_limit.get();
+                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
                         if self.anon_depth >= recursion_limit {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 58c591bf935..51493f26194 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -997,7 +997,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     {
         // Watch out for overflow. This intentionally bypasses (and does
         // not update) the cache.
-        let recursion_limit = self.infcx.tcx.sess.recursion_limit.get();
+        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);
         }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 865a9a34aaa..523cd42940e 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc_data_structures::accumulate_vec::AccumulateVec;
 use traits;
 use traits::project::Normalized;
 use ty::{self, Lift, TyCtxt};
@@ -557,6 +558,28 @@ EnumTypeFoldableImpl! {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Goal<'tcx>> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
+        folder.tcx().intern_goals(&v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        let v = (**self).fold_with(folder);
+        folder.tcx().mk_goal(v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        (**self).visit_with(visitor)
+    }
+}
+
 BraceStructTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
         goal,
@@ -570,3 +593,14 @@ EnumTypeFoldableImpl! {
         (traits::Clause::ForAll)(clause),
     }
 }
+
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Clause<'tcx>> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
+        folder.tcx().intern_clauses(&v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs
index c118b7a4692..3ba79d91964 100644
--- a/src/librustc/ty/cast.rs
+++ b/src/librustc/ty/cast.rs
@@ -20,7 +20,6 @@ use syntax::ast;
 pub enum IntTy {
     U(ast::UintTy),
     I,
-    Ivar,
     CEnum,
     Bool,
     Char
@@ -64,7 +63,7 @@ impl<'tcx> CastTy<'tcx> {
             ty::TyBool => Some(CastTy::Int(IntTy::Bool)),
             ty::TyChar => Some(CastTy::Int(IntTy::Char)),
             ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
-            ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::Ivar)),
+            ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)),
             ty::TyInfer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float),
             ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
             ty::TyFloat(_) => Some(CastTy::Float),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 69b33efdb35..88a2619c7e3 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -38,6 +38,7 @@ use ty::subst::{Kind, Substs};
 use ty::ReprOptions;
 use ty::Instance;
 use traits;
+use traits::{Clause, Goal};
 use ty::{self, Ty, TypeAndMut};
 use ty::{TyS, TypeVariants, Slice};
 use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const};
@@ -50,7 +51,7 @@ use ty::maps;
 use ty::steal::Steal;
 use ty::BindingMode;
 use ty::CanonicalTy;
-use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
+use util::nodemap::{DefIdSet, ItemLocalMap};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
@@ -58,7 +59,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
                                            StableVec};
 use arena::{TypedArena, DroplessArena};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, Lock};
 use std::any::Any;
 use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
@@ -71,11 +72,11 @@ use std::iter;
 use std::sync::mpsc;
 use std::sync::Arc;
 use syntax::abi;
-use syntax::ast::{self, Name, NodeId};
+use syntax::ast::{self, NodeId};
 use syntax::attr;
 use syntax::codemap::MultiSpan;
 use syntax::feature_gate;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::{Symbol, keywords, InternedString};
 use syntax_pos::Span;
 
 use hir;
@@ -125,34 +126,40 @@ impl<'tcx> GlobalArenas<'tcx> {
     }
 }
 
+type InternedSet<'tcx, T> = Lock<FxHashSet<Interned<'tcx, T>>>;
+
 pub struct CtxtInterners<'tcx> {
     /// The arena that types, regions, etc are allocated from
     arena: &'tcx DroplessArena,
 
     /// Specifically use a speedy hash algorithm for these hash sets,
     /// they're accessed quite often.
-    type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
-    type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
-    substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
-    canonical_var_infos: RefCell<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
-    region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
-    existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
-    predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
-    const_: RefCell<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
+    type_: InternedSet<'tcx, TyS<'tcx>>,
+    type_list: InternedSet<'tcx, Slice<Ty<'tcx>>>,
+    substs: InternedSet<'tcx, Substs<'tcx>>,
+    canonical_var_infos: InternedSet<'tcx, Slice<CanonicalVarInfo>>,
+    region: InternedSet<'tcx, RegionKind>,
+    existential_predicates: InternedSet<'tcx, Slice<ExistentialPredicate<'tcx>>>,
+    predicates: InternedSet<'tcx, Slice<Predicate<'tcx>>>,
+    const_: InternedSet<'tcx, Const<'tcx>>,
+    clauses: InternedSet<'tcx, Slice<Clause<'tcx>>>,
+    goals: InternedSet<'tcx, Slice<Goal<'tcx>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
     fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
         CtxtInterners {
             arena,
-            type_: RefCell::new(FxHashSet()),
-            type_list: RefCell::new(FxHashSet()),
-            substs: RefCell::new(FxHashSet()),
-            region: RefCell::new(FxHashSet()),
-            existential_predicates: RefCell::new(FxHashSet()),
-            canonical_var_infos: RefCell::new(FxHashSet()),
-            predicates: RefCell::new(FxHashSet()),
-            const_: RefCell::new(FxHashSet()),
+            type_: Default::default(),
+            type_list: Default::default(),
+            substs: Default::default(),
+            region: Default::default(),
+            existential_predicates: Default::default(),
+            canonical_var_infos: Default::default(),
+            predicates: Default::default(),
+            const_: Default::default(),
+            clauses: Default::default(),
+            goals: Default::default(),
         }
     }
 
@@ -346,6 +353,12 @@ pub struct TypeckTables<'tcx> {
     /// method calls, including those of overloaded operators.
     type_dependent_defs: ItemLocalMap<Def>,
 
+    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
+    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
+    /// about the field you also need definition of the variant to which the field
+    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
+    field_indices: ItemLocalMap<usize>,
+
     /// Stores the canonicalized types provided by the user. See also `UserAssertTy` statement in
     /// MIR.
     user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
@@ -426,6 +439,7 @@ impl<'tcx> TypeckTables<'tcx> {
         TypeckTables {
             local_id_root,
             type_dependent_defs: ItemLocalMap(),
+            field_indices: ItemLocalMap(),
             user_provided_tys: ItemLocalMap(),
             node_types: ItemLocalMap(),
             node_substs: ItemLocalMap(),
@@ -468,6 +482,20 @@ impl<'tcx> TypeckTables<'tcx> {
         }
     }
 
+    pub fn field_indices(&self) -> LocalTableInContext<usize> {
+        LocalTableInContext {
+            local_id_root: self.local_id_root,
+            data: &self.field_indices
+        }
+    }
+
+    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<usize> {
+        LocalTableInContextMut {
+            local_id_root: self.local_id_root,
+            data: &mut self.field_indices
+        }
+    }
+
     pub fn user_provided_tys(&self) -> LocalTableInContext<CanonicalTy<'tcx>> {
         LocalTableInContext {
             local_id_root: self.local_id_root,
@@ -706,6 +734,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
         let ty::TypeckTables {
             local_id_root,
             ref type_dependent_defs,
+            ref field_indices,
             ref user_provided_tys,
             ref node_types,
             ref node_substs,
@@ -726,6 +755,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
 
         hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
             type_dependent_defs.hash_stable(hcx, hasher);
+            field_indices.hash_stable(hcx, hasher);
             user_provided_tys.hash_stable(hcx, hasher);
             node_types.hash_stable(hcx, hasher);
             node_substs.hash_stable(hcx, hasher);
@@ -888,21 +918,11 @@ pub struct GlobalCtxt<'tcx> {
     /// Used to prevent layout from recursing too deeply.
     pub layout_depth: Cell<usize>,
 
-    /// Map from function to the `#[derive]` mode that it's defining. Only used
-    /// by `proc-macro` crates.
-    pub derive_macros: RefCell<NodeMap<Symbol>>,
-
-    stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
+    stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
 
     pub interpret_interner: InterpretInterner<'tcx>,
 
-    layout_interner: RefCell<FxHashSet<&'tcx LayoutDetails>>,
-
-    /// A vector of every trait accessible in the whole crate
-    /// (i.e. including those from subcrates). This is used only for
-    /// error reporting, and so is lazily initialized and generally
-    /// shouldn't taint the common path (hence the RefCell).
-    pub all_traits: RefCell<Option<Vec<DefId>>>,
+    layout_interner: Lock<FxHashSet<&'tcx LayoutDetails>>,
 
     /// A general purpose channel to throw data out the back towards LLVM worker
     /// threads.
@@ -910,7 +930,7 @@ pub struct GlobalCtxt<'tcx> {
     /// This is intended to only get used during the trans phase of the compiler
     /// when satisfying the query for a particular codegen unit. Internally in
     /// the query it'll send data along this channel to get processed later.
-    pub tx_to_llvm_workers: mpsc::Sender<Box<dyn Any + Send>>,
+    pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>,
 
     output_filenames: Arc<OutputFilenames>,
 }
@@ -918,7 +938,7 @@ pub struct GlobalCtxt<'tcx> {
 /// Everything needed to efficiently work with interned allocations
 #[derive(Debug, Default)]
 pub struct InterpretInterner<'tcx> {
-    inner: RefCell<InterpretInternerInner<'tcx>>,
+    inner: Lock<InterpretInternerInner<'tcx>>,
 }
 
 #[derive(Debug, Default)]
@@ -1278,13 +1298,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             evaluation_cache: traits::EvaluationCache::new(),
             crate_name: Symbol::intern(crate_name),
             data_layout,
-            layout_interner: RefCell::new(FxHashSet()),
+            layout_interner: Lock::new(FxHashSet()),
             layout_depth: Cell::new(0),
-            derive_macros: RefCell::new(NodeMap()),
-            stability_interner: RefCell::new(FxHashSet()),
+            stability_interner: Lock::new(FxHashSet()),
             interpret_interner: Default::default(),
-            all_traits: RefCell::new(None),
-            tx_to_llvm_workers: tx,
+            tx_to_llvm_workers: Lock::new(tx),
             output_filenames: Arc::new(output_filenames.clone()),
         };
 
@@ -2088,6 +2106,20 @@ impl<'tcx: 'lcx, 'lcx> Borrow<Const<'lcx>> for Interned<'tcx, Const<'tcx>> {
     }
 }
 
+impl<'tcx: 'lcx, 'lcx> Borrow<[Clause<'lcx>]>
+for Interned<'tcx, Slice<Clause<'tcx>>> {
+    fn borrow<'a>(&'a self) -> &'a [Clause<'lcx>] {
+        &self.0[..]
+    }
+}
+
+impl<'tcx: 'lcx, 'lcx> Borrow<[Goal<'lcx>]>
+for Interned<'tcx, Slice<Goal<'tcx>>> {
+    fn borrow<'a>(&'a self) -> &'a [Goal<'lcx>] {
+        &self.0[..]
+    }
+}
+
 macro_rules! intern_method {
     ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
                                             $alloc_method:ident,
@@ -2185,7 +2217,9 @@ slice_interners!(
     existential_predicates: _intern_existential_predicates(ExistentialPredicate),
     predicates: _intern_predicates(Predicate),
     type_list: _intern_type_list(Ty),
-    substs: _intern_substs(Kind)
+    substs: _intern_substs(Kind),
+    clauses: _intern_clauses(Clause),
+    goals: _intern_goals(Goal)
 );
 
 // This isn't a perfect fit: CanonicalVarInfo slices are always
@@ -2430,12 +2464,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn mk_param(self,
                     index: u32,
-                    name: Name) -> Ty<'tcx> {
+                    name: InternedString) -> Ty<'tcx> {
         self.mk_ty(TyParam(ParamTy { idx: index, name: name }))
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(0, keywords::SelfType.name())
+        self.mk_param(0, keywords::SelfType.name().as_str())
     }
 
     pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
@@ -2490,6 +2524,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice<Clause<'tcx>> {
+        if ts.len() == 0 {
+            Slice::empty()
+        } else {
+            self._intern_clauses(ts)
+        }
+    }
+
+    pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> &'tcx Slice<Goal<'tcx>> {
+        if ts.len() == 0 {
+            Slice::empty()
+        } else {
+            self._intern_goals(ts)
+        }
+    }
+
     pub fn mk_fn_sig<I>(self,
                         inputs: I,
                         output: I::Item,
@@ -2536,6 +2586,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
     }
 
+    pub fn mk_clauses<I: InternAs<[Clause<'tcx>],
+        &'tcx Slice<Clause<'tcx>>>>(self, iter: I) -> I::Output {
+        iter.intern_with(|xs| self.intern_clauses(xs))
+    }
+
+    pub fn mk_goals<I: InternAs<[Goal<'tcx>],
+        &'tcx Slice<Goal<'tcx>>>>(self, iter: I) -> I::Output {
+        iter.intern_with(|xs| self.intern_goals(xs))
+    }
+
+    pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal {
+        &self.mk_goals(iter::once(goal))[0]
+    }
+
     pub fn lint_node<S: Into<MultiSpan>>(self,
                                          lint: &'static Lint,
                                          id: NodeId,
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 5f9c305d92f..35ada4a7227 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -12,7 +12,7 @@ pub use self::Integer::*;
 pub use self::Primitive::*;
 
 use session::{self, DataTypeKind, Session};
-use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
+use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
 
 use syntax::ast::{self, FloatTy, IntTy, UintTy};
 use syntax::attr;
@@ -344,8 +344,8 @@ impl AddAssign for Size {
 /// a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct Align {
-    abi: u8,
-    pref: u8,
+    abi_pow2: u8,
+    pref_pow2: u8,
 }
 
 impl Align {
@@ -377,17 +377,17 @@ impl Align {
         };
 
         Ok(Align {
-            abi: log2(abi)?,
-            pref: log2(pref)?,
+            abi_pow2: log2(abi)?,
+            pref_pow2: log2(pref)?,
         })
     }
 
     pub fn abi(self) -> u64 {
-        1 << self.abi
+        1 << self.abi_pow2
     }
 
     pub fn pref(self) -> u64 {
-        1 << self.pref
+        1 << self.pref_pow2
     }
 
     pub fn abi_bits(self) -> u64 {
@@ -400,15 +400,15 @@ impl Align {
 
     pub fn min(self, other: Align) -> Align {
         Align {
-            abi: cmp::min(self.abi, other.abi),
-            pref: cmp::min(self.pref, other.pref),
+            abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2),
+            pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2),
         }
     }
 
     pub fn max(self, other: Align) -> Align {
         Align {
-            abi: cmp::max(self.abi, other.abi),
-            pref: cmp::max(self.pref, other.pref),
+            abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2),
+            pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2),
         }
     }
 }
@@ -898,7 +898,7 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     let (param_env, ty) = query.into_parts();
 
-    let rec_limit = tcx.sess.recursion_limit.get();
+    let rec_limit = *tcx.sess.recursion_limit.get();
     let depth = tcx.layout_depth.get();
     if depth > rec_limit {
         tcx.sess.fatal(
@@ -974,6 +974,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 bug!("struct cannot be packed and aligned");
             }
 
+            let pack = {
+                let pack = repr.pack as u64;
+                Align::from_bytes(pack, pack).unwrap()
+            };
+
             let mut align = if packed {
                 dl.i8_align
             } else {
@@ -984,8 +989,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             let mut offsets = vec![Size::from_bytes(0); fields.len()];
             let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
 
-            // Anything with repr(C) or repr(packed) doesn't optimize.
-            let mut optimize = (repr.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty();
+            let mut optimize = !repr.inhibit_struct_field_reordering_opt();
             if let StructKind::Prefixed(_, align) = kind {
                 optimize &= align.abi() == 1;
             }
@@ -997,6 +1001,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     fields.len()
                 };
                 let optimizing = &mut inverse_memory_index[..end];
+                let field_align = |f: &TyLayout| {
+                    if packed { f.align.min(pack).abi() } else { f.align.abi() }
+                };
                 match kind {
                     StructKind::AlwaysSized |
                     StructKind::MaybeUnsized => {
@@ -1004,11 +1011,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                             // Place ZSTs first to avoid "interesting offsets",
                             // especially with only one or two non-ZST fields.
                             let f = &fields[x as usize];
-                            (!f.is_zst(), cmp::Reverse(f.align.abi()))
-                        })
+                            (!f.is_zst(), cmp::Reverse(field_align(f)))
+                        });
                     }
                     StructKind::Prefixed(..) => {
-                        optimizing.sort_by_key(|&x| fields[x as usize].align.abi());
+                        optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
                     }
                 }
             }
@@ -1022,7 +1029,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             let mut offset = Size::from_bytes(0);
 
             if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
-                if !packed {
+                if packed {
+                    let prefix_align = prefix_align.min(pack);
+                    align = align.max(prefix_align);
+                } else {
                     align = align.max(prefix_align);
                 }
                 offset = prefix_size.abi_align(prefix_align);
@@ -1044,7 +1054,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
 
                 // Invariant: offset < dl.obj_size_bound() <= 1<<61
-                if !packed {
+                if packed {
+                    let field_pack = field.align.min(pack);
+                    offset = offset.abi_align(field_pack);
+                    align = align.max(field_pack);
+                }
+                else {
                     offset = offset.abi_align(field.align);
                     align = align.max(field.align);
                 }
@@ -1377,7 +1392,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                         bug!("Union cannot be packed and aligned");
                     }
 
-                    let mut align = if def.repr.packed() {
+                    let pack = {
+                        let pack = def.repr.pack as u64;
+                        Align::from_bytes(pack, pack).unwrap()
+                    };
+
+                    let mut align = if packed {
                         dl.i8_align
                     } else {
                         dl.aggregate_align
@@ -1393,7 +1413,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     for field in &variants[0] {
                         assert!(!field.is_unsized());
 
-                        if !packed {
+                        if packed {
+                            let field_pack = field.align.min(pack);
+                            align = align.max(field_pack);
+                        } else {
                             align = align.max(field.align);
                         }
                         size = cmp::max(size, field.size);
@@ -1471,10 +1494,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
                     // Find one non-ZST variant.
                     'variants: for (v, fields) in variants.iter().enumerate() {
+                        if fields.iter().any(|f| f.abi == Abi::Uninhabited) {
+                            continue 'variants;
+                        }
                         for f in fields {
-                            if f.abi == Abi::Uninhabited {
-                                continue 'variants;
-                            }
                             if !f.is_zst() {
                                 if dataful_variant.is_none() {
                                     dataful_variant = Some(v);
@@ -1740,12 +1763,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
     fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
         // (delay format until we actually need it)
-        let record = |kind, opt_discr_size, variants| {
+        let record = |kind, packed, opt_discr_size, variants| {
             let type_desc = format!("{:?}", layout.ty);
             self.tcx.sess.code_stats.borrow_mut().record_type_size(kind,
                                                                    type_desc,
                                                                    layout.align,
                                                                    layout.size,
+                                                                   packed,
                                                                    opt_discr_size,
                                                                    variants);
         };
@@ -1758,7 +1782,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
             ty::TyClosure(..) => {
                 debug!("print-type-size t: `{:?}` record closure", layout.ty);
-                record(DataTypeKind::Closure, None, vec![]);
+                record(DataTypeKind::Closure, false, None, vec![]);
                 return;
             }
 
@@ -1769,6 +1793,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
         };
 
         let adt_kind = adt_def.adt_kind();
+        let adt_packed = adt_def.repr.packed();
 
         let build_variant_info = |n: Option<ast::Name>,
                                   flds: &[ast::Name],
@@ -1821,6 +1846,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     let fields: Vec<_> =
                         variant_def.fields.iter().map(|f| f.name).collect();
                     record(adt_kind.into(),
+                           adt_packed,
                            None,
                            vec![build_variant_info(Some(variant_def.name),
                                                    &fields,
@@ -1828,7 +1854,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 } else {
                     // (This case arises for *empty* enums; so give it
                     // zero variants.)
-                    record(adt_kind.into(), None, vec![]);
+                    record(adt_kind.into(), adt_packed, None, vec![]);
                 }
             }
 
@@ -1845,7 +1871,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                                             layout.for_variant(self, i))
                     })
                     .collect();
-                record(adt_kind.into(), match layout.variants {
+                record(adt_kind.into(), adt_packed, match layout.variants {
                     Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)),
                     _ => None
                 }, variant_infos);
@@ -2518,8 +2544,8 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive {
 });
 
 impl_stable_hash_for!(struct ::ty::layout::Align {
-    abi,
-    pref
+    abi_pow2,
+    pref_pow2
 });
 
 impl_stable_hash_for!(struct ::ty::layout::Size {
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index 16866636cd9..664c84f5986 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -155,6 +155,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("computing the inferred outlives predicates for items in this crate")
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
     fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
         format!("generating MIR shim for `{}`",
@@ -586,6 +592,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::all_traits<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("fetching all foreign and local traits")
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> {
     fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
         format!("fetching all foreign CrateNum instances")
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 5a23a3b952a..d317f5a494b 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -39,7 +39,7 @@ use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
 use traits::Clause;
-use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
+use ty::{self, CrateInherentImpls, ParamEnvAnd, Slice, Ty, TyCtxt};
 use ty::steal::Steal;
 use ty::subst::Substs;
 use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
@@ -102,6 +102,7 @@ define_maps! { <'tcx>
     /// associated generics and predicates.
     [] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
     [] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
+    [] fn explicit_predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
 
     /// Maps from the def-id of a trait to the list of
     /// super-predicates. This is a subset of the full list of
@@ -139,7 +140,11 @@ define_maps! { <'tcx>
     [] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
 
     /// Maps from def-id of a type to its (inferred) outlives.
-    [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Vec<ty::Predicate<'tcx>>,
+    [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
+
+    /// Maps from def-id of a type to its (inferred) outlives.
+    [] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
+        -> Lrc<ty::CratePredicatesMap<'tcx>>,
 
     /// Maps from an impl/trait def-id to a list of the def-ids of its items
     [] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Lrc<Vec<DefId>>,
@@ -386,6 +391,11 @@ define_maps! { <'tcx>
     [] fn stability_index: stability_index_node(CrateNum) -> Lrc<stability::Index<'tcx>>,
     [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
 
+    /// A vector of every trait accessible in the whole crate
+    /// (i.e. including those from subcrates). This is used only for
+    /// error reporting.
+    [] fn all_traits: all_traits_node(CrateNum) -> Lrc<Vec<DefId>>,
+
     [] fn exported_symbols: ExportedSymbols(CrateNum)
         -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>>,
     [] fn collect_and_partition_translation_items:
@@ -435,7 +445,7 @@ define_maps! { <'tcx>
 
     [] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
 
-    [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<Vec<Clause<'tcx>>>,
+    [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
 
     [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
     [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
@@ -575,6 +585,10 @@ fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::AllCrateNums
 }
 
+fn all_traits_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::AllTraits
+}
+
 fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::CollectAndPartitionTranslationItems
 }
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 232b300e754..efe7a56d800 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -671,7 +671,16 @@ macro_rules! define_maps {
                                map: LockGuard<'_, QueryMap<$tcx, Self>>,
                                dep_node: DepNode)
                                -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
-                debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node));
+                // 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,
@@ -998,6 +1007,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
         DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
         DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
+        DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
         DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
         DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
         DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
@@ -1115,6 +1125,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         }
         DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
         DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
+        DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
         DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
         DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
         DepKind::CollectAndPartitionTranslationItems => {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index b920553ec36..6618f9bc2f5 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -50,7 +50,7 @@ use std::vec::IntoIter;
 use std::mem;
 use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
 use syntax::attr;
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::Mark;
 use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
@@ -712,7 +712,7 @@ pub struct FloatVarValue(pub ast::FloatTy);
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub struct TypeParameterDef {
-    pub name: Name,
+    pub name: InternedString,
     pub def_id: DefId,
     pub index: u32,
     pub has_default: bool,
@@ -956,6 +956,22 @@ pub enum Predicate<'tcx> {
     ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
 }
 
+/// The crate outlives map is computed during typeck and contains the
+/// outlives of every item in the local crate. You should not use it
+/// directly, because to do so will make your pass dependent on the
+/// HIR of every item in the local crate. Instead, use
+/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
+/// item.
+pub struct CratePredicatesMap<'tcx> {
+    /// For each struct with outlive bounds, maps to a vector of the
+    /// predicate of its outlive bounds. If an item has no outlives
+    /// bounds, it will have no entry.
+    pub predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+
+    /// An empty vector, useful for cloning.
+    pub empty_predicate: Lrc<Vec<ty::Predicate<'tcx>>>,
+}
+
 impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
     fn as_ref(&self) -> &Predicate<'tcx> {
         self
@@ -1623,15 +1639,13 @@ bitflags! {
     #[derive(RustcEncodable, RustcDecodable, Default)]
     pub struct ReprFlags: u8 {
         const IS_C               = 1 << 0;
-        const IS_PACKED          = 1 << 1;
-        const IS_SIMD            = 1 << 2;
-        const IS_TRANSPARENT     = 1 << 3;
+        const IS_SIMD            = 1 << 1;
+        const IS_TRANSPARENT     = 1 << 2;
         // Internal only for now. If true, don't reorder fields.
-        const IS_LINEAR          = 1 << 4;
+        const IS_LINEAR          = 1 << 3;
 
         // Any of these flags being set prevent field reordering optimisation.
         const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits |
-                                   ReprFlags::IS_PACKED.bits |
                                    ReprFlags::IS_SIMD.bits |
                                    ReprFlags::IS_LINEAR.bits;
     }
@@ -1648,11 +1662,13 @@ impl_stable_hash_for!(struct ReprFlags {
 pub struct ReprOptions {
     pub int: Option<attr::IntType>,
     pub align: u32,
+    pub pack: u32,
     pub flags: ReprFlags,
 }
 
 impl_stable_hash_for!(struct ReprOptions {
     align,
+    pack,
     int,
     flags
 });
@@ -1662,11 +1678,19 @@ impl ReprOptions {
         let mut flags = ReprFlags::empty();
         let mut size = None;
         let mut max_align = 0;
+        let mut min_pack = 0;
         for attr in tcx.get_attrs(did).iter() {
             for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
                 flags.insert(match r {
                     attr::ReprC => ReprFlags::IS_C,
-                    attr::ReprPacked => ReprFlags::IS_PACKED,
+                    attr::ReprPacked(pack) => {
+                        min_pack = if min_pack > 0 {
+                            cmp::min(pack, min_pack)
+                        } else {
+                            pack
+                        };
+                        ReprFlags::empty()
+                    },
                     attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
                     attr::ReprSimd => ReprFlags::IS_SIMD,
                     attr::ReprInt(i) => {
@@ -1685,7 +1709,7 @@ impl ReprOptions {
         if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) {
             flags.insert(ReprFlags::IS_LINEAR);
         }
-        ReprOptions { int: size, align: max_align, flags: flags }
+        ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags }
     }
 
     #[inline]
@@ -1693,7 +1717,7 @@ impl ReprOptions {
     #[inline]
     pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) }
     #[inline]
-    pub fn packed(&self) -> bool { self.flags.contains(ReprFlags::IS_PACKED) }
+    pub fn packed(&self) -> bool { self.pack > 0 }
     #[inline]
     pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) }
     #[inline]
@@ -1709,6 +1733,12 @@ impl ReprOptions {
     pub fn inhibit_enum_layout_opt(&self) -> bool {
         self.c() || self.int.is_some()
     }
+
+    /// Returns true if this `#[repr()]` should inhibit struct field reordering
+    /// optimizations, such as with repr(C) or repr(packed(1)).
+    pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
+        !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
+    }
 }
 
 impl<'a, 'gcx, 'tcx> AdtDef {
@@ -2077,32 +2107,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     }
 }
 
-impl<'a, 'gcx, 'tcx> VariantDef {
-    #[inline]
-    pub fn find_field_named(&self, name: ast::Name) -> Option<&FieldDef> {
-        self.index_of_field_named(name).map(|index| &self.fields[index])
-    }
-
-    pub fn index_of_field_named(&self, name: ast::Name) -> Option<usize> {
-        if let Some(index) = self.fields.iter().position(|f| f.name == name) {
-            return Some(index);
-        }
-        let mut ident = name.to_ident();
-        while ident.span.ctxt() != SyntaxContext::empty() {
-            ident.span.remove_mark();
-            if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) {
-                return Some(field);
-            }
-        }
-        None
-    }
-
-    #[inline]
-    pub fn field_named(&self, name: ast::Name) -> &FieldDef {
-        self.find_field_named(name).unwrap()
-    }
-}
-
 impl<'a, 'gcx, 'tcx> FieldDef {
     pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
         tcx.type_of(self.did).subst(tcx, subst)
@@ -2369,6 +2373,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn field_index(self, node_id: NodeId, tables: &TypeckTables) -> usize {
+        let hir_id = self.hir.node_to_hir_id(node_id);
+        tables.field_indices().get(hir_id).cloned().expect("no index for a field")
+    }
+
+    pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
+        variant.fields.iter().position(|field| {
+            self.adjust_ident(ident.modern(), variant.did, DUMMY_NODE_ID).0 == field.name.to_ident()
+        })
+    }
+
     pub fn associated_items(
         self,
         def_id: DefId,
diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs
index 0b081888881..842c0d65734 100644
--- a/src/librustc/ty/steal.rs
+++ b/src/librustc/ty/steal.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cell::{Ref, RefCell};
+use rustc_data_structures::sync::{RwLock, ReadGuard};
 use std::mem;
 
 /// The `Steal` struct is intended to used as the value for a query.
@@ -32,25 +32,25 @@ use std::mem;
 ///
 /// FIXME(#41710) -- what is the best way to model linear queries?
 pub struct Steal<T> {
-    value: RefCell<Option<T>>
+    value: RwLock<Option<T>>
 }
 
 impl<T> Steal<T> {
     pub fn new(value: T) -> Self {
         Steal {
-            value: RefCell::new(Some(value))
+            value: RwLock::new(Some(value))
         }
     }
 
-    pub fn borrow(&self) -> Ref<T> {
-        Ref::map(self.value.borrow(), |opt| match *opt {
+    pub fn borrow(&self) -> ReadGuard<T> {
+        ReadGuard::map(self.value.borrow(), |opt| match *opt {
             None => bug!("attempted to read from stolen value"),
             Some(ref v) => v
         })
     }
 
     pub fn steal(&self) -> T {
-        let value_ref = &mut *self.value.borrow_mut();
+        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
         let value = mem::replace(value_ref, None);
         value.expect("attempt to read from stolen value")
     }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index ed04d41ba14..7a9174cbfaf 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -24,7 +24,7 @@ use std::iter;
 use std::cmp::Ordering;
 use syntax::abi;
 use syntax::ast::{self, Name};
-use syntax::symbol::keywords;
+use syntax::symbol::{keywords, InternedString};
 
 use serialize;
 
@@ -864,16 +864,16 @@ impl<'tcx> PolyFnSig<'tcx> {
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct ParamTy {
     pub idx: u32,
-    pub name: Name,
+    pub name: InternedString,
 }
 
 impl<'a, 'gcx, 'tcx> ParamTy {
-    pub fn new(index: u32, name: Name) -> ParamTy {
+    pub fn new(index: u32, name: InternedString) -> ParamTy {
         ParamTy { idx: index, name: name }
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, keywords::SelfType.name())
+        ParamTy::new(0, keywords::SelfType.name().as_str())
     }
 
     pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
@@ -885,7 +885,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn is_self(&self) -> bool {
-        if self.name == keywords::SelfType.name() {
+        if self.name == keywords::SelfType.name().as_str() {
             assert_eq!(self.idx, 0);
             true
         } else {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 22f851a908b..77eff49d19f 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -33,7 +33,7 @@ use rustc_data_structures::fx::FxHashMap;
 use std::{cmp, fmt};
 use std::hash::Hash;
 use std::intrinsics;
-use syntax::ast::{self, Name};
+use syntax::ast;
 use syntax::attr::{self, SignedInt, UnsignedInt};
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -270,42 +270,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         false
     }
 
-    /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
-    /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
-    pub fn positional_element_ty(self,
-                                 ty: Ty<'tcx>,
-                                 i: usize,
-                                 variant: Option<DefId>) -> Option<Ty<'tcx>> {
-        match (&ty.sty, variant) {
-            (&TyAdt(adt, substs), Some(vid)) => {
-                adt.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
-            }
-            (&TyAdt(adt, substs), None) => {
-                // Don't use `non_enum_variant`, this may be a univariant enum.
-                adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
-            }
-            (&TyTuple(ref v), None) => v.get(i).cloned(),
-            _ => None,
-        }
-    }
-
-    /// Returns the type of element at field `n` in struct or struct-like type `t`.
-    /// For an enum `t`, `variant` must be some def id.
-    pub fn named_element_ty(self,
-                            ty: Ty<'tcx>,
-                            n: Name,
-                            variant: Option<DefId>) -> Option<Ty<'tcx>> {
-        match (&ty.sty, variant) {
-            (&TyAdt(adt, substs), Some(vid)) => {
-                adt.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
-            }
-            (&TyAdt(adt, substs), None) => {
-                adt.non_enum_variant().find_field_named(n).map(|f| f.ty(self, substs))
-            }
-            _ => return None
-        }
-    }
-
     /// Returns the deeply last field of nested structures, or the same type,
     /// if not a structure at all. Corresponds to the only possible unsized
     /// field, and its type can be used to determine unsizing strategy.
@@ -729,7 +693,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
             }
             TyParam(p) => {
                 self.hash(p.idx);
-                self.hash(p.name.as_str());
+                self.hash(p.name);
             }
             TyProjection(ref data) => {
                 self.def_id(data.item_def_id);
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 32ec837f031..bb6aa654c29 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -10,6 +10,8 @@
 
 #![allow(non_camel_case_types)]
 
+use rustc_data_structures::sync::Lock;
+
 use std::cell::{RefCell, Cell};
 use std::collections::HashMap;
 use std::ffi::CString;
@@ -236,13 +238,14 @@ pub fn to_readable_str(mut val: usize) -> String {
     groups.join("_")
 }
 
-pub fn record_time<T, F>(accu: &Cell<Duration>, f: F) -> T where
+pub fn record_time<T, F>(accu: &Lock<Duration>, f: F) -> T where
     F: FnOnce() -> T,
 {
     let start = Instant::now();
     let rv = f();
     let duration = start.elapsed();
-    accu.set(duration + accu.get());
+    let mut accu = accu.lock();
+    *accu = *accu + duration;
     rv
 }
 
@@ -382,13 +385,3 @@ fn test_to_readable_str() {
     assert_eq!("1_000_000", to_readable_str(1_000_000));
     assert_eq!("1_234_567", to_readable_str(1_234_567));
 }
-
-pub trait CellUsizeExt {
-    fn increment(&self);
-}
-
-impl CellUsizeExt for Cell<usize> {
-    fn increment(&self) {
-        self.set(self.get() + 1);
-    }
-}
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index ee38cca7828..305502e7f06 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -11,7 +11,7 @@
 use rustc::middle::allocator::AllocatorKind;
 use rustc_errors;
 use syntax::abi::Abi;
-use syntax::ast::{Crate, Attribute, LitKind, StrStyle, ExprKind};
+use syntax::ast::{Crate, Attribute, LitKind, StrStyle};
 use syntax::ast::{Unsafety, Constness, Generics, Mutability, Ty, Mac, Arg};
 use syntax::ast::{self, Ident, Item, ItemKind, TyKind, VisibilityKind, Expr};
 use syntax::attr;
@@ -88,7 +88,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
             span,
             kind: AllocatorKind::Global,
             global: item.ident,
-            alloc: Ident::from_str("alloc"),
+            core: Ident::from_str("core"),
             cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
         };
         let super_path = f.cx.path(f.span, vec![
@@ -96,7 +96,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
             f.global,
         ]);
         let mut items = vec![
-            f.cx.item_extern_crate(f.span, f.alloc),
+            f.cx.item_extern_crate(f.span, f.core),
             f.cx.item_use_simple(
                 f.span,
                 respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
@@ -126,7 +126,7 @@ struct AllocFnFactory<'a> {
     span: Span,
     kind: AllocatorKind,
     global: Ident,
-    alloc: Ident,
+    core: Ident,
     cx: ExtCtxt<'a>,
 }
 
@@ -143,8 +143,7 @@ impl<'a> AllocFnFactory<'a> {
             self.arg_ty(ty, &mut abi_args, mk)
         }).collect();
         let result = self.call_allocator(method.name, args);
-        let (output_ty, output_expr) =
-            self.ret_ty(&method.output, &mut abi_args, mk, result);
+        let (output_ty, output_expr) = self.ret_ty(&method.output, result);
         let kind = ItemKind::Fn(self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
                                 Unsafety::Unsafe,
                                 dummy_spanned(Constness::NotConst),
@@ -159,16 +158,15 @@ impl<'a> AllocFnFactory<'a> {
 
     fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
         let method = self.cx.path(self.span, vec![
-            self.alloc,
-            Ident::from_str("heap"),
-            Ident::from_str("Alloc"),
+            self.core,
+            Ident::from_str("alloc"),
+            Ident::from_str("GlobalAlloc"),
             Ident::from_str(method),
         ]);
         let method = self.cx.expr_path(method);
         let allocator = self.cx.path_ident(self.span, self.global);
         let allocator = self.cx.expr_path(allocator);
         let allocator = self.cx.expr_addr_of(self.span, allocator);
-        let allocator = self.cx.expr_mut_addr_of(self.span, allocator);
         args.insert(0, allocator);
 
         self.cx.expr_call(self.span, method, args)
@@ -205,8 +203,8 @@ impl<'a> AllocFnFactory<'a> {
                 args.push(self.cx.arg(self.span, align, ty_usize));
 
                 let layout_new = self.cx.path(self.span, vec![
-                    self.alloc,
-                    Ident::from_str("heap"),
+                    self.core,
+                    Ident::from_str("alloc"),
                     Ident::from_str("Layout"),
                     Ident::from_str("from_size_align_unchecked"),
                 ]);
@@ -219,240 +217,38 @@ impl<'a> AllocFnFactory<'a> {
                 layout
             }
 
-            AllocatorTy::LayoutRef => {
-                let ident = ident();
-                args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
-
-                // Convert our `arg: *const u8` via:
-                //
-                //      &*(arg as *const Layout)
-                let expr = self.cx.expr_ident(self.span, ident);
-                let expr = self.cx.expr_cast(self.span, expr, self.layout_ptr());
-                let expr = self.cx.expr_deref(self.span, expr);
-                self.cx.expr_addr_of(self.span, expr)
-            }
-
-            AllocatorTy::AllocErr => {
-                // We're creating:
-                //
-                //      (*(arg as *const AllocErr)).clone()
+            AllocatorTy::Ptr => {
                 let ident = ident();
                 args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
-                let expr = self.cx.expr_ident(self.span, ident);
-                let expr = self.cx.expr_cast(self.span, expr, self.alloc_err_ptr());
-                let expr = self.cx.expr_deref(self.span, expr);
-                self.cx.expr_method_call(
-                    self.span,
-                    expr,
-                    Ident::from_str("clone"),
-                    Vec::new()
-                )
+                let arg = self.cx.expr_ident(self.span, ident);
+                self.cx.expr_cast(self.span, arg, self.ptr_opaque())
             }
 
-            AllocatorTy::Ptr => {
+            AllocatorTy::Usize => {
                 let ident = ident();
-                args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
+                args.push(self.cx.arg(self.span, ident, self.usize()));
                 self.cx.expr_ident(self.span, ident)
             }
 
             AllocatorTy::ResultPtr |
-            AllocatorTy::ResultExcess |
-            AllocatorTy::ResultUnit |
             AllocatorTy::Bang |
-            AllocatorTy::UsizePair |
             AllocatorTy::Unit => {
                 panic!("can't convert AllocatorTy to an argument")
             }
         }
     }
 
-    fn ret_ty(&self,
-              ty: &AllocatorTy,
-              args: &mut Vec<Arg>,
-              ident: &mut FnMut() -> Ident,
-              expr: P<Expr>) -> (P<Ty>, P<Expr>)
-    {
+    fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
         match *ty {
-            AllocatorTy::UsizePair => {
-                // We're creating:
-                //
-                //      let arg = #expr;
-                //      *min = arg.0;
-                //      *max = arg.1;
-
-                let min = ident();
-                let max = ident();
-
-                args.push(self.cx.arg(self.span, min, self.ptr_usize()));
-                args.push(self.cx.arg(self.span, max, self.ptr_usize()));
-
-                let ident = ident();
-                let stmt = self.cx.stmt_let(self.span, false, ident, expr);
-                let min = self.cx.expr_ident(self.span, min);
-                let max = self.cx.expr_ident(self.span, max);
-                let layout = self.cx.expr_ident(self.span, ident);
-                let assign_min = self.cx.expr(self.span, ExprKind::Assign(
-                    self.cx.expr_deref(self.span, min),
-                    self.cx.expr_tup_field_access(self.span, layout.clone(), 0),
-                ));
-                let assign_min = self.cx.stmt_semi(assign_min);
-                let assign_max = self.cx.expr(self.span, ExprKind::Assign(
-                    self.cx.expr_deref(self.span, max),
-                    self.cx.expr_tup_field_access(self.span, layout.clone(), 1),
-                ));
-                let assign_max = self.cx.stmt_semi(assign_max);
-
-                let stmts = vec![stmt, assign_min, assign_max];
-                let block = self.cx.block(self.span, stmts);
-                let ty_unit = self.cx.ty(self.span, TyKind::Tup(Vec::new()));
-                (ty_unit, self.cx.expr_block(block))
-            }
-
-            AllocatorTy::ResultExcess => {
-                // We're creating:
-                //
-                //      match #expr {
-                //          Ok(ptr) => {
-                //              *excess = ptr.1;
-                //              ptr.0
-                //          }
-                //          Err(e) => {
-                //              ptr::write(err_ptr, e);
-                //              0 as *mut u8
-                //          }
-                //      }
-
-                let excess_ptr = ident();
-                args.push(self.cx.arg(self.span, excess_ptr, self.ptr_usize()));
-                let excess_ptr = self.cx.expr_ident(self.span, excess_ptr);
-
-                let err_ptr = ident();
-                args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8()));
-                let err_ptr = self.cx.expr_ident(self.span, err_ptr);
-                let err_ptr = self.cx.expr_cast(self.span,
-                                                err_ptr,
-                                                self.alloc_err_ptr());
-
-                let name = ident();
-                let ok_expr = {
-                    let ptr = self.cx.expr_ident(self.span, name);
-                    let write = self.cx.expr(self.span, ExprKind::Assign(
-                        self.cx.expr_deref(self.span, excess_ptr),
-                        self.cx.expr_tup_field_access(self.span, ptr.clone(), 1),
-                    ));
-                    let write = self.cx.stmt_semi(write);
-                    let ret = self.cx.expr_tup_field_access(self.span,
-                                                            ptr.clone(),
-                                                            0);
-                    let ret = self.cx.stmt_expr(ret);
-                    let block = self.cx.block(self.span, vec![write, ret]);
-                    self.cx.expr_block(block)
-                };
-                let pat = self.cx.pat_ident(self.span, name);
-                let ok = self.cx.path_ident(self.span, Ident::from_str("Ok"));
-                let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]);
-                let ok = self.cx.arm(self.span, vec![ok], ok_expr);
-
-                let name = ident();
-                let err_expr = {
-                    let err = self.cx.expr_ident(self.span, name);
-                    let write = self.cx.path(self.span, vec![
-                        self.alloc,
-                        Ident::from_str("heap"),
-                        Ident::from_str("__core"),
-                        Ident::from_str("ptr"),
-                        Ident::from_str("write"),
-                    ]);
-                    let write = self.cx.expr_path(write);
-                    let write = self.cx.expr_call(self.span, write,
-                                                  vec![err_ptr, err]);
-                    let write = self.cx.stmt_semi(write);
-                    let null = self.cx.expr_usize(self.span, 0);
-                    let null = self.cx.expr_cast(self.span, null, self.ptr_u8());
-                    let null = self.cx.stmt_expr(null);
-                    let block = self.cx.block(self.span, vec![write, null]);
-                    self.cx.expr_block(block)
-                };
-                let pat = self.cx.pat_ident(self.span, name);
-                let err = self.cx.path_ident(self.span, Ident::from_str("Err"));
-                let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]);
-                let err = self.cx.arm(self.span, vec![err], err_expr);
-
-                let expr = self.cx.expr_match(self.span, expr, vec![ok, err]);
-                (self.ptr_u8(), expr)
-            }
-
             AllocatorTy::ResultPtr => {
                 // We're creating:
                 //
-                //      match #expr {
-                //          Ok(ptr) => ptr,
-                //          Err(e) => {
-                //              ptr::write(err_ptr, e);
-                //              0 as *mut u8
-                //          }
-                //      }
-
-                let err_ptr = ident();
-                args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8()));
-                let err_ptr = self.cx.expr_ident(self.span, err_ptr);
-                let err_ptr = self.cx.expr_cast(self.span,
-                                                err_ptr,
-                                                self.alloc_err_ptr());
-
-                let name = ident();
-                let ok_expr = self.cx.expr_ident(self.span, name);
-                let pat = self.cx.pat_ident(self.span, name);
-                let ok = self.cx.path_ident(self.span, Ident::from_str("Ok"));
-                let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]);
-                let ok = self.cx.arm(self.span, vec![ok], ok_expr);
+                //      #expr as *mut u8
 
-                let name = ident();
-                let err_expr = {
-                    let err = self.cx.expr_ident(self.span, name);
-                    let write = self.cx.path(self.span, vec![
-                        self.alloc,
-                        Ident::from_str("heap"),
-                        Ident::from_str("__core"),
-                        Ident::from_str("ptr"),
-                        Ident::from_str("write"),
-                    ]);
-                    let write = self.cx.expr_path(write);
-                    let write = self.cx.expr_call(self.span, write,
-                                                  vec![err_ptr, err]);
-                    let write = self.cx.stmt_semi(write);
-                    let null = self.cx.expr_usize(self.span, 0);
-                    let null = self.cx.expr_cast(self.span, null, self.ptr_u8());
-                    let null = self.cx.stmt_expr(null);
-                    let block = self.cx.block(self.span, vec![write, null]);
-                    self.cx.expr_block(block)
-                };
-                let pat = self.cx.pat_ident(self.span, name);
-                let err = self.cx.path_ident(self.span, Ident::from_str("Err"));
-                let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]);
-                let err = self.cx.arm(self.span, vec![err], err_expr);
-
-                let expr = self.cx.expr_match(self.span, expr, vec![ok, err]);
+                let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
                 (self.ptr_u8(), expr)
             }
 
-            AllocatorTy::ResultUnit => {
-                // We're creating:
-                //
-                //      #expr.is_ok() as u8
-
-                let cast = self.cx.expr_method_call(
-                    self.span,
-                    expr,
-                    Ident::from_str("is_ok"),
-                    Vec::new()
-                );
-                let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
-                let u8 = self.cx.ty_path(u8);
-                let cast = self.cx.expr_cast(self.span, cast, u8.clone());
-                (u8, cast)
-            }
-
             AllocatorTy::Bang => {
                 (self.cx.ty(self.span, TyKind::Never), expr)
             }
@@ -461,44 +257,32 @@ impl<'a> AllocFnFactory<'a> {
                 (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr)
             }
 
-            AllocatorTy::AllocErr |
             AllocatorTy::Layout |
-            AllocatorTy::LayoutRef |
+            AllocatorTy::Usize |
             AllocatorTy::Ptr => {
                 panic!("can't convert AllocatorTy to an output")
             }
         }
     }
 
+    fn usize(&self) -> P<Ty> {
+        let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
+        self.cx.ty_path(usize)
+    }
+
     fn ptr_u8(&self) -> P<Ty> {
         let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
         let ty_u8 = self.cx.ty_path(u8);
         self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
     }
 
-    fn ptr_usize(&self) -> P<Ty> {
-        let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
-        let ty_usize = self.cx.ty_path(usize);
-        self.cx.ty_ptr(self.span, ty_usize, Mutability::Mutable)
-    }
-
-    fn layout_ptr(&self) -> P<Ty> {
-        let layout = self.cx.path(self.span, vec![
-            self.alloc,
-            Ident::from_str("heap"),
-            Ident::from_str("Layout"),
-        ]);
-        let layout = self.cx.ty_path(layout);
-        self.cx.ty_ptr(self.span, layout, Mutability::Mutable)
-    }
-
-    fn alloc_err_ptr(&self) -> P<Ty> {
-        let err = self.cx.path(self.span, vec![
-            self.alloc,
-            Ident::from_str("heap"),
-            Ident::from_str("AllocErr"),
+    fn ptr_opaque(&self) -> P<Ty> {
+        let opaque = self.cx.path(self.span, vec![
+            self.core,
+            Ident::from_str("alloc"),
+            Ident::from_str("Opaque"),
         ]);
-        let err = self.cx.ty_path(err);
-        self.cx.ty_ptr(self.span, err, Mutability::Mutable)
+        let ty_opaque = self.cx.ty_path(opaque);
+        self.cx.ty_ptr(self.span, ty_opaque, Mutability::Mutable)
     }
 }
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index e17fce5a2ec..706eab72d44 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(rustc_private)]
 
 extern crate rustc;
@@ -27,7 +25,7 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
     },
     AllocatorMethod {
         name: "oom",
-        inputs: &[AllocatorTy::AllocErr],
+        inputs: &[],
         output: AllocatorTy::Bang,
     },
     AllocatorMethod {
@@ -36,13 +34,8 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
         output: AllocatorTy::Unit,
     },
     AllocatorMethod {
-        name: "usable_size",
-        inputs: &[AllocatorTy::LayoutRef],
-        output: AllocatorTy::UsizePair,
-    },
-    AllocatorMethod {
         name: "realloc",
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
+        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
         output: AllocatorTy::ResultPtr,
     },
     AllocatorMethod {
@@ -50,26 +43,6 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
         inputs: &[AllocatorTy::Layout],
         output: AllocatorTy::ResultPtr,
     },
-    AllocatorMethod {
-        name: "alloc_excess",
-        inputs: &[AllocatorTy::Layout],
-        output: AllocatorTy::ResultExcess,
-    },
-    AllocatorMethod {
-        name: "realloc_excess",
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
-        output: AllocatorTy::ResultExcess,
-    },
-    AllocatorMethod {
-        name: "grow_in_place",
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
-        output: AllocatorTy::ResultUnit,
-    },
-    AllocatorMethod {
-        name: "shrink_in_place",
-        inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
-        output: AllocatorTy::ResultUnit,
-    },
 ];
 
 pub struct AllocatorMethod {
@@ -79,14 +52,10 @@ pub struct AllocatorMethod {
 }
 
 pub enum AllocatorTy {
-    AllocErr,
     Bang,
     Layout,
-    LayoutRef,
     Ptr,
-    ResultExcess,
     ResultPtr,
-    ResultUnit,
     Unit,
-    UsizePair,
+    Usize,
 }
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index 276f6cd09bf..0f051ea5981 100644
--- a/src/librustc_apfloat/lib.rs
+++ b/src/librustc_apfloat/lib.rs
@@ -43,7 +43,6 @@
 #![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/")]
-#![deny(warnings)]
 #![forbid(unsafe_code)]
 
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index 9baee267709..027a9c45555 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -24,7 +24,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![feature(const_fn)]
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index 5cfbe49f77f..e3adb51433b 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -107,8 +107,9 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                     ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
                         RestrictionResult::Safe => RestrictionResult::Safe,
                         RestrictionResult::SafeIf(base_lp, mut base_vec) => {
-                            for field in &adt_def.non_enum_variant().fields {
-                                let field = InteriorKind::InteriorField(mc::NamedField(field.name));
+                            for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
+                                let field =
+                                    InteriorKind::InteriorField(mc::FieldIndex(i, field.name));
                                 let field_ty = if field == interior {
                                     cmt.ty
                                 } else {
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 93d6247eeae..6d832d4060a 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -128,7 +128,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
     // Note that `mir_validated` is a "stealable" result; the
     // thief, `optimized_mir()`, forces borrowck, so we know that
     // is not yet stolen.
-    tcx.mir_validated(owner_def_id).borrow();
+    ty::maps::queries::mir_validated::ensure(tcx, owner_def_id);
 
     // option dance because you can't capture an uninitialized variable
     // by mut-ref.
@@ -370,7 +370,7 @@ const DOWNCAST_PRINTED_OPERATOR: &'static str = " as ";
 // is tracked is irrelevant here.)
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum InteriorKind {
-    InteriorField(mc::FieldName),
+    InteriorField(mc::FieldIndex),
     InteriorElement,
 }
 
@@ -1336,18 +1336,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 out.push(')');
             }
 
-            LpExtend(ref lp_base, _, LpInterior(_, InteriorField(fname))) => {
+            LpExtend(ref lp_base, _, LpInterior(_, InteriorField(mc::FieldIndex(_, info)))) => {
                 self.append_autoderefd_loan_path_to_string(&lp_base, out);
-                match fname {
-                    mc::NamedField(fname) => {
-                        out.push('.');
-                        out.push_str(&fname.as_str());
-                    }
-                    mc::PositionalField(idx) => {
-                        out.push('.');
-                        out.push_str(&idx.to_string());
-                    }
-                }
+                out.push('.');
+                out.push_str(&info.as_str());
             }
 
             LpExtend(ref lp_base, _, LpInterior(_, InteriorElement)) => {
@@ -1422,8 +1414,7 @@ impl DataFlowOperator for LoanDataFlowOperator {
 impl<'tcx> fmt::Debug for InteriorKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            InteriorField(mc::NamedField(fld)) => write!(f, "{}", fld),
-            InteriorField(mc::PositionalField(i)) => write!(f, "#{}", i),
+            InteriorField(mc::FieldIndex(_, info)) => write!(f, "{}", info),
             InteriorElement => write!(f, "[]"),
         }
     }
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index a90dcd1072f..1f4050a5b36 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -21,7 +21,6 @@ use rustc::middle::dataflow::DataFlowOperator;
 use rustc::middle::dataflow::KillFrom;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::expr_use_visitor::MutateMode;
-use rustc::middle::mem_categorization as mc;
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
@@ -343,8 +342,8 @@ impl<'a, 'tcx> MoveData<'tcx> {
             if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
                     = (&base_lp.ty.sty, lp_elem) {
                 if adt_def.is_union() {
-                    for field in &adt_def.non_enum_variant().fields {
-                        let field = InteriorKind::InteriorField(mc::NamedField(field.name));
+                    for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
+                        let field = InteriorKind::InteriorField(mc::FieldIndex(i, field.name));
                         if field != interior {
                             let sibling_lp_kind =
                                 LpExtend(base_lp.clone(), mutbl, LpInterior(opt_variant_id, field));
@@ -395,8 +394,8 @@ impl<'a, 'tcx> MoveData<'tcx> {
         if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
             if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
                 if adt_def.is_union() {
-                    for field in &adt_def.non_enum_variant().fields {
-                        let field = InteriorKind::InteriorField(mc::NamedField(field.name));
+                    for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() {
+                        let field = InteriorKind::InteriorField(mc::FieldIndex(i, field.name));
                         let field_ty = if field == interior {
                             lp.ty
                         } else {
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 6fe2ac2b0ca..52a357e1a1d 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -11,7 +11,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![allow(non_camel_case_types)]
 
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
index c4c5886d465..499c330be1d 100644
--- a/src/librustc_const_math/lib.rs
+++ b/src/librustc_const_math/lib.rs
@@ -17,7 +17,6 @@
 #![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/")]
-#![deny(warnings)]
 
 extern crate rustc_apfloat;
 
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 1e1628936d5..ba1d73dc268 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -19,7 +19,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(collections_range)]
 #![feature(nonzero)]
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index 184ef136976..3b7d6efbdae 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -29,10 +29,15 @@
 //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync
 //! depending on the value of cfg!(parallel_queries).
 
+use std::collections::HashMap;
+use std::hash::{Hash, BuildHasher};
 use std::cmp::Ordering;
+use std::marker::PhantomData;
 use std::fmt::Debug;
 use std::fmt::Formatter;
 use std::fmt;
+use std;
+use std::ops::{Deref, DerefMut};
 use owning_ref::{Erased, OwningRef};
 
 cfg_if! {
@@ -161,6 +166,8 @@ cfg_if! {
         use parking_lot::Mutex as InnerLock;
         use parking_lot::RwLock as InnerRwLock;
 
+        use std::thread;
+
         pub type MetadataRef = OwningRef<Box<Erased + Send + Sync>, [u8]>;
 
         /// This makes locks panic if they are already held.
@@ -223,6 +230,146 @@ pub fn assert_sync<T: ?Sized + Sync>() {}
 pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
 pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
 
+pub trait HashMapExt<K, V> {
+    /// Same as HashMap::insert, but it may panic if there's already an
+    /// entry for `key` with a value not equal to `value`
+    fn insert_same(&mut self, key: K, value: V);
+}
+
+impl<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S> {
+    fn insert_same(&mut self, key: K, value: V) {
+        self.entry(key).and_modify(|old| assert!(*old == value)).or_insert(value);
+    }
+}
+
+/// A type whose inner value can be written once and then will stay read-only
+// This contains a PhantomData<T> since this type conceptually owns a T outside the Mutex once
+// initialized. This ensures that Once<T> is Sync only if T is. If we did not have PhantomData<T>
+// we could send a &Once<Cell<bool>> to multiple threads and call `get` on it to get access
+// to &Cell<bool> on those threads.
+pub struct Once<T>(Lock<Option<T>>, PhantomData<T>);
+
+impl<T> Once<T> {
+    /// Creates an Once value which is uninitialized
+    #[inline(always)]
+    pub fn new() -> Self {
+        Once(Lock::new(None), PhantomData)
+    }
+
+    /// Consumes the value and returns Some(T) if it was initialized
+    #[inline(always)]
+    pub fn into_inner(self) -> Option<T> {
+        self.0.into_inner()
+    }
+
+    /// Tries to initialize the inner value to `value`.
+    /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it
+    /// otherwise if the inner value was already set it returns `value` back to the caller
+    #[inline]
+    pub fn try_set(&self, value: T) -> Option<T> {
+        let mut lock = self.0.lock();
+        if lock.is_some() {
+            return Some(value);
+        }
+        *lock = Some(value);
+        None
+    }
+
+    /// Tries to initialize the inner value to `value`.
+    /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it
+    /// otherwise if the inner value was already set it asserts that `value` is equal to the inner
+    /// value and then returns `value` back to the caller
+    #[inline]
+    pub fn try_set_same(&self, value: T) -> Option<T> where T: Eq {
+        let mut lock = self.0.lock();
+        if let Some(ref inner) = *lock {
+            assert!(*inner == value);
+            return Some(value);
+        }
+        *lock = Some(value);
+        None
+    }
+
+    /// Tries to initialize the inner value to `value` and panics if it was already initialized
+    #[inline]
+    pub fn set(&self, value: T) {
+        assert!(self.try_set(value).is_none());
+    }
+
+    /// Tries to initialize the inner value by calling the closure while ensuring that no-one else
+    /// can access the value in the mean time by holding a lock for the duration of the closure.
+    /// If the value was already initialized the closure is not called and `false` is returned,
+    /// otherwise if the value from the closure initializes the inner value, `true` is returned
+    #[inline]
+    pub fn init_locking<F: FnOnce() -> T>(&self, f: F) -> bool {
+        let mut lock = self.0.lock();
+        if lock.is_some() {
+            return false;
+        }
+        *lock = Some(f());
+        true
+    }
+
+    /// Tries to initialize the inner value by calling the closure without ensuring that no-one
+    /// else can access it. This mean when this is called from multiple threads, multiple
+    /// closures may concurrently be computing a value which the inner value should take.
+    /// Only one of these closures are used to actually initialize the value.
+    /// If some other closure already set the value,
+    /// we return the value our closure computed wrapped in a `Option`.
+    /// If our closure set the value, `None` is returned.
+    /// If the value is already initialized, the closure is not called and `None` is returned.
+    #[inline]
+    pub fn init_nonlocking<F: FnOnce() -> T>(&self, f: F) -> Option<T> {
+        if self.0.lock().is_some() {
+            None
+        } else {
+            self.try_set(f())
+        }
+    }
+
+    /// Tries to initialize the inner value by calling the closure without ensuring that no-one
+    /// else can access it. This mean when this is called from multiple threads, multiple
+    /// closures may concurrently be computing a value which the inner value should take.
+    /// Only one of these closures are used to actually initialize the value.
+    /// If some other closure already set the value, we assert that it our closure computed
+    /// a value equal to the value aready set and then
+    /// we return the value our closure computed wrapped in a `Option`.
+    /// If our closure set the value, `None` is returned.
+    /// If the value is already initialized, the closure is not called and `None` is returned.
+    #[inline]
+    pub fn init_nonlocking_same<F: FnOnce() -> T>(&self, f: F) -> Option<T> where T: Eq {
+        if self.0.lock().is_some() {
+            None
+        } else {
+            self.try_set_same(f())
+        }
+    }
+
+    /// Tries to get a reference to the inner value, returns `None` if it is not yet initialized
+    #[inline(always)]
+    pub fn try_get(&self) -> Option<&T> {
+        let lock = &*self.0.lock();
+        if let Some(ref inner) = *lock {
+            // This is safe since we won't mutate the inner value
+            unsafe { Some(&*(inner as *const T)) }
+        } else {
+            None
+        }
+    }
+
+    /// Gets reference to the inner value, panics if it is not yet initialized
+    #[inline(always)]
+    pub fn get(&self) -> &T {
+        self.try_get().expect("value was not set")
+    }
+
+    /// Gets reference to the inner value, panics if it is not yet initialized
+    #[inline(always)]
+    pub fn borrow(&self) -> &T {
+        self.get()
+    }
+}
+
 impl<T: Copy + Debug> Debug for LockCell<T> {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         f.debug_struct("LockCell")
@@ -390,6 +537,18 @@ impl<T> RwLock<T> {
 
     #[cfg(not(parallel_queries))]
     #[inline(always)]
+    pub fn try_write(&self) -> Result<WriteGuard<T>, ()> {
+        self.0.try_borrow_mut().map_err(|_| ())
+    }
+
+    #[cfg(parallel_queries)]
+    #[inline(always)]
+    pub fn try_write(&self) -> Result<WriteGuard<T>, ()> {
+        self.0.try_write().ok_or(())
+    }
+
+    #[cfg(not(parallel_queries))]
+    #[inline(always)]
     pub fn write(&self) -> WriteGuard<T> {
         self.0.borrow_mut()
     }
@@ -427,3 +586,54 @@ impl<T: Clone> Clone for RwLock<T> {
         RwLock::new(self.borrow().clone())
     }
 }
+
+/// A type which only allows its inner value to be used in one thread.
+/// It will panic if it is used on multiple threads.
+#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)]
+pub struct OneThread<T> {
+    #[cfg(parallel_queries)]
+    thread: thread::ThreadId,
+    inner: T,
+}
+
+unsafe impl<T> std::marker::Sync for OneThread<T> {}
+unsafe impl<T> std::marker::Send for OneThread<T> {}
+
+impl<T> OneThread<T> {
+    #[inline(always)]
+    fn check(&self) {
+        #[cfg(parallel_queries)]
+        assert_eq!(thread::current().id(), self.thread);
+    }
+
+    #[inline(always)]
+    pub fn new(inner: T) -> Self {
+        OneThread {
+            #[cfg(parallel_queries)]
+            thread: thread::current().id(),
+            inner,
+        }
+    }
+
+    #[inline(always)]
+    pub fn into_inner(value: Self) -> T {
+        value.check();
+        value.inner
+    }
+}
+
+impl<T> Deref for OneThread<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        self.check();
+        &self.inner
+    }
+}
+
+impl<T> DerefMut for OneThread<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        self.check();
+        &mut self.inner
+    }
+}
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index c6ebc992680..4071b804def 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -652,10 +652,11 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
 
-    *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
+    let crate_types = collect_crate_types(sess, &krate.attrs);
+    sess.crate_types.set(crate_types);
 
     let disambiguator = compute_crate_disambiguator(sess);
-    *sess.crate_disambiguator.borrow_mut() = Some(disambiguator);
+    sess.crate_disambiguator.set(disambiguator);
     rustc_incremental::prepare_session_directory(
         sess,
         &crate_name,
@@ -783,7 +784,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         let features = sess.features_untracked();
         let cfg = syntax::ext::expand::ExpansionConfig {
             features: Some(&features),
-            recursion_limit: sess.recursion_limit.get(),
+            recursion_limit: *sess.recursion_limit.get(),
             trace_mac: sess.opts.debugging_opts.trace_macros,
             should_test: sess.opts.test,
             ..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string())
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 6f88b0aecb6..3dec84d174d 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -17,12 +17,12 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(set_stdio)]
 #![feature(rustc_stack_internals)]
 
@@ -83,7 +83,6 @@ use rustc_trans_utils::trans_crate::TransCrate;
 use serialize::json::ToJson;
 
 use std::any::Any;
-use std::cmp::Ordering::Equal;
 use std::cmp::max;
 use std::default::Default;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
@@ -1177,13 +1176,8 @@ Available lint options:
 
     fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
         let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
-        lints.sort_by(|x: &&Lint, y: &&Lint| {
-            match x.default_level(sess).cmp(&y.default_level(sess)) {
-                // The sort doesn't case-fold but it's doubtful we care.
-                Equal => x.name.cmp(y.name),
-                r => r,
-            }
-        });
+        // The sort doesn't case-fold but it's doubtful we care.
+        lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name));
         lints
     }
 
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 9efd8844977..971855ee2d0 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -303,7 +303,7 @@ 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))
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_str())
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index a723e455222..8d5f9ac93f0 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -11,7 +11,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 9e72ede309d..a5e07bcec24 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -13,7 +13,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(fs_read_write)]
 #![feature(specialization)]
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index ad3760eed80..463ec4796e8 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -368,6 +368,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
             hir::ItemStatic(..) => {
+                if attr::find_by_name(&it.attrs, "no_mangle").is_some() {
+                    return;
+                }
                 NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span);
             }
             hir::ItemConst(..) => {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 2cc6708bc03..6f2c51b0f18 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -166,13 +166,24 @@ impl LintPass for NonShorthandFieldPatterns {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
     fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
-        if let PatKind::Struct(_, ref field_pats, _) = pat.node {
+        if let PatKind::Struct(ref qpath, ref field_pats, _) = pat.node {
+            let variant = cx.tables.pat_ty(pat).ty_adt_def()
+                                   .expect("struct pattern type is not an ADT")
+                                   .variant_of_def(cx.tables.qpath_def(qpath, pat.hir_id));
             for fieldpat in field_pats {
                 if fieldpat.node.is_shorthand {
                     continue;
                 }
+                if fieldpat.span.ctxt().outer().expn_info().is_some() {
+                    // Don't lint if this is a macro expansion: macro authors
+                    // shouldn't have to worry about this kind of style issue
+                    // (Issue #49588)
+                    continue;
+                }
                 if let PatKind::Binding(_, _, name, None) = fieldpat.node.pat.node {
-                    if name.node == fieldpat.node.name {
+                    let binding_ident = ast::Ident::new(name.node, name.span);
+                    if cx.tcx.find_field_index(binding_ident, &variant) ==
+                       Some(cx.tcx.field_index(fieldpat.node.id, cx.tables)) {
                         let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
                                      fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant",
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index c915181213d..16e8600f2d8 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -22,7 +22,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![cfg_attr(test, feature(test))]
 #![feature(box_patterns)]
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 16bee5b987e..bf8a087ab55 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -16,7 +16,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![feature(concat_idents)]
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 86f495c5fac..34d9f47bac3 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -614,6 +614,7 @@ impl<'a> CrateLoader<'a> {
         });
         if !any_non_rlib {
             info!("panic runtime injection skipped, only generating rlib");
+            self.sess.injected_panic_runtime.set(None);
             return
         }
 
@@ -646,6 +647,7 @@ impl<'a> CrateLoader<'a> {
         // we just don't need one at all, then we're done here and there's
         // nothing else to do.
         if !needs_panic_runtime || runtime_found {
+            self.sess.injected_panic_runtime.set(None);
             return
         }
 
@@ -812,9 +814,7 @@ impl<'a> CrateLoader<'a> {
 
     fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         let has_global_allocator = has_global_allocator(krate);
-        if has_global_allocator {
-            self.sess.has_global_allocator.set(true);
-        }
+        self.sess.has_global_allocator.set(has_global_allocator);
 
         // Check to see if we actually need an allocator. This desire comes
         // about through the `#![needs_allocator]` attribute and is typically
@@ -825,6 +825,8 @@ impl<'a> CrateLoader<'a> {
             needs_allocator = needs_allocator || data.needs_allocator(self.sess);
         });
         if !needs_allocator {
+            self.sess.injected_allocator.set(None);
+            self.sess.allocator_kind.set(None);
             return
         }
 
@@ -844,6 +846,8 @@ impl<'a> CrateLoader<'a> {
             }
         }
         if !need_lib_alloc && !need_exe_alloc {
+            self.sess.injected_allocator.set(None);
+            self.sess.allocator_kind.set(None);
             return
         }
 
@@ -881,6 +885,7 @@ impl<'a> CrateLoader<'a> {
         });
         if global_allocator.is_some() {
             self.sess.allocator_kind.set(Some(AllocatorKind::Global));
+            self.sess.injected_allocator.set(None);
             return
         }
 
@@ -924,6 +929,9 @@ impl<'a> CrateLoader<'a> {
             };
 
         let allocation_crate_data = exe_allocation_crate_data.or_else(|| {
+            // No allocator was injected
+            self.sess.injected_allocator.set(None);
+
             if attr::contains_name(&krate.attrs, "default_lib_allocator") {
                 // Prefer self as the allocator if there's a collision
                 return None;
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 51088563c7b..2c995d2f5cd 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -163,7 +163,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
     impl_parent => { cdata.get_parent_impl(def_id.index) }
     trait_of_item => { cdata.get_trait_of_item(def_id.index) }
-    item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
+    item_body_nested_bodies => { cdata.item_body_nested_bodies(tcx, def_id.index) }
     const_is_rvalue_promotable_to_static => {
         cdata.const_is_rvalue_promotable_to_static(def_id.index)
     }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 42e208ded49..3ea4ddc2522 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -818,11 +818,14 @@ impl<'a, 'tcx> CrateMetadata {
         tcx.alloc_tables(ast.tables.decode((self, tcx)))
     }
 
-    pub fn item_body_nested_bodies(&self, id: DefIndex) -> ExternBodyNestedBodies {
+    pub fn item_body_nested_bodies(&self,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   id: DefIndex)
+                                   -> ExternBodyNestedBodies {
         if let Some(ref ast) = self.entry(id).ast {
-            let ast = ast.decode(self);
+            let mut ast = ast.decode(self);
             let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
-                                                   .decode(self)
+                                                   .decode((self, tcx.sess))
                                                    .map(|body| (body.id(), body))
                                                    .collect();
             ExternBodyNestedBodies {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 1b208a512e2..22b440eea60 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -459,7 +459,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
         let has_default_lib_allocator =
             attr::contains_name(tcx.hir.krate_attrs(), "default_lib_allocator");
-        let has_global_allocator = tcx.sess.has_global_allocator.get();
+        let has_global_allocator = *tcx.sess.has_global_allocator.get();
         let root = self.lazy(&CrateRoot {
             name: tcx.crate_name(LOCAL_CRATE),
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
@@ -1414,7 +1414,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
 
         // Bring everything into deterministic order for hashing
-        all_impls.sort_unstable_by_key(|&(trait_def_id, _)| {
+        all_impls.sort_by_cached_key(|&(trait_def_id, _)| {
             tcx.def_path_hash(trait_def_id)
         });
 
@@ -1422,7 +1422,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             .into_iter()
             .map(|(trait_def_id, mut impls)| {
                 // Bring everything into deterministic order for hashing
-                impls.sort_unstable_by_key(|&def_index| {
+                impls.sort_by_cached_key(|&def_index| {
                     tcx.hir.definitions().def_path_hash(def_index)
                 });
 
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index e89b5a7fc1b..cbbc9d74228 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -11,7 +11,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(fs_read_write)]
@@ -21,6 +20,7 @@
 #![feature(macro_lifetime_matcher)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(specialization)]
 #![feature(rustc_private)]
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index fe7aedb4127..62acdf76546 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -42,6 +42,7 @@ use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
 use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
 use util::borrowck_errors::{BorrowckErrors, Origin};
+use util::collect_writes::FindAssignments;
 
 use std::iter;
 
@@ -1550,6 +1551,36 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         }
     }
 
+    fn specialized_description(&self, place:&Place<'tcx>) -> Option<String>{
+        if let Some(_name) = self.describe_place(place) {
+            Some(format!("data in a `&` reference"))
+        } else {
+            None
+        }
+    }
+
+    fn get_default_err_msg(&self, place:&Place<'tcx>) -> String{
+        match self.describe_place(place) {
+            Some(name) => format!("immutable item `{}`", name),
+            None => "immutable item".to_owned(),
+        }
+    }
+
+    fn get_secondary_err_msg(&self, place:&Place<'tcx>) -> String{
+        match self.specialized_description(place) {
+            Some(_) => format!("data in a `&` reference"),
+            None => self.get_default_err_msg(place)
+        }
+    }
+
+    fn get_primary_err_msg(&self, place:&Place<'tcx>) -> String{
+        if let Some(name) = self.describe_place(place) {
+            format!("`{}` is a `&` reference, so the data it refers to cannot be written", name)
+        } else {
+            format!("cannot assign through `&`-reference")
+        }
+    }
+
     /// Check the permissions for the given place and read or write kind
     ///
     /// Returns true if an error is reported, false otherwise.
@@ -1576,43 +1607,70 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 self.is_mutable(place, is_local_mutation_allowed)
             {
                 error_reported = true;
-
-                let item_msg = match self.describe_place(place) {
-                    Some(name) => format!("immutable item `{}`", name),
-                    None => "immutable item".to_owned(),
-                };
-
+                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!("Value not mutable causing this error: `{}`", name));
+                        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)
+                                            };
+                                            err_info = Some((
+                                                self.mir.source_info(locations[0]).span,
+                                                    "consider changing this to be a \
+                                                    mutable reference: `&mut`", item_msg,
+                                                    self.get_primary_err_msg(base)));
+                                        }
+                                },
+                            _ => {},
+                            }
+                        },
+                        _ => {},
+                    }
 
-                    let item_msg = match self.describe_place(place) {
-                        Some(name) => format!("immutable item `{}`", name),
-                        None => "immutable item".to_owned(),
-                    };
-
-                    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!("Value not mutable causing this error: `{}`", name));
+                    if let Some((err_help_span, err_help_stmt, 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!(""));
+                        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();
                     }
-
-                    err.emit();
                 }
             }
             Reservation(WriteKind::Move)
@@ -1631,9 +1689,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     );
                 }
             }
-
             Activation(..) => {} // permission checks are done at Reservation point.
-
             Read(ReadKind::Borrow(BorrowKind::Unique))
             | Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
             | Read(ReadKind::Borrow(BorrowKind::Shared))
@@ -2255,3 +2311,4 @@ impl ContextKind {
         }
     }
 }
+
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index dbfb8a6d06e..942e4fb56ca 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -202,11 +202,11 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     });
 
     // Also dump the inference graph constraints as a graphviz file.
-    let _: io::Result<()> = do catch {
+    let _: io::Result<()> = do_catch! {{
         let mut file =
             pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
-        regioncx.dump_graphviz(&mut file)
-    };
+        regioncx.dump_graphviz(&mut file)?;
+    }};
 }
 
 fn dump_annotation<'a, 'gcx, 'tcx>(
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 5b373908480..c0d28280946 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -16,7 +16,7 @@ use hair::cx::to_ref::ToRef;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::interpret::{GlobalId, Value, PrimVal};
-use rustc::ty::{self, AdtKind, VariantDef, Ty};
+use rustc::ty::{self, AdtKind, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::cast::CastKind as TyCastKind;
 use rustc::hir;
@@ -420,12 +420,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ty::TyAdt(adt, substs) => {
                     match adt.adt_kind() {
                         AdtKind::Struct | AdtKind::Union => {
-                            let field_refs = field_refs(&adt.variants[0], fields);
                             ExprKind::Adt {
                                 adt_def: adt,
                                 variant_index: 0,
                                 substs,
-                                fields: field_refs,
+                                fields: field_refs(cx, fields),
                                 base: base.as_ref().map(|base| {
                                     FruInfo {
                                         base: base.to_ref(),
@@ -446,12 +445,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                     assert!(base.is_none());
 
                                     let index = adt.variant_index_with_id(variant_id);
-                                    let field_refs = field_refs(&adt.variants[index], fields);
                                     ExprKind::Adt {
                                         adt_def: adt,
                                         variant_index: index,
                                         substs,
-                                        fields: field_refs,
+                                        fields: field_refs(cx, fields),
                                         base: None,
                                     }
                                 }
@@ -581,24 +579,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 body: block::to_expr_ref(cx, body),
             }
         }
-        hir::ExprField(ref source, name) => {
-            let index = match cx.tables().expr_ty_adjusted(source).sty {
-                ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node),
-                ref ty => span_bug!(expr.span, "field of non-ADT: {:?}", ty),
-            };
-            let index =
-                index.unwrap_or_else(|| {
-                    span_bug!(expr.span, "no index found for field `{}`", name.node)
-                });
-            ExprKind::Field {
-                lhs: source.to_ref(),
-                name: Field::new(index),
-            }
-        }
-        hir::ExprTupField(ref source, index) => {
+        hir::ExprField(ref source, ..) => {
             ExprKind::Field {
                 lhs: source.to_ref(),
-                name: Field::new(index.node as usize),
+                name: Field::new(cx.tcx.field_index(expr.id, cx.tables)),
             }
         }
         hir::ExprCast(ref source, _) => {
@@ -999,13 +983,13 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 }
 
 /// Converts a list of named fields (i.e. for struct-like struct/enum ADTs) into FieldExprRef.
-fn field_refs<'tcx>(variant: &'tcx VariantDef,
-                    fields: &'tcx [hir::Field])
-                    -> Vec<FieldExprRef<'tcx>> {
+fn field_refs<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
+                              fields: &'tcx [hir::Field])
+                              -> Vec<FieldExprRef<'tcx>> {
     fields.iter()
         .map(|field| {
             FieldExprRef {
-                name: Field::new(variant.index_of_field_named(field.name.node).unwrap()),
+                name: Field::new(cx.tcx.field_index(field.id, cx.tables)),
                 expr: field.expr.to_ref(),
             }
         })
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index c3f41e8ac48..8d2b73d6ba0 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -528,28 +528,12 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
             PatKind::Struct(ref qpath, ref fields, _) => {
                 let def = self.tables.qpath_def(qpath, pat.hir_id);
-                let adt_def = match ty.sty {
-                    ty::TyAdt(adt_def, _) => adt_def,
-                    _ => {
-                        span_bug!(
-                            pat.span,
-                            "struct pattern not applied to an ADT");
-                    }
-                };
-                let variant_def = adt_def.variant_of_def(def);
-
                 let subpatterns =
                     fields.iter()
                           .map(|field| {
-                              let index = variant_def.index_of_field_named(field.node.name);
-                              let index = index.unwrap_or_else(|| {
-                                  span_bug!(
-                                      pat.span,
-                                      "no field with name {:?}",
-                                      field.node.name);
-                              });
                               FieldPattern {
-                                  field: Field::new(index),
+                                  field: Field::new(self.tcx.field_index(field.node.id,
+                                                                         self.tables)),
                                   pattern: self.lower_pattern(&field.node.pat),
                               }
                           })
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 3220d4d96b3..58ea8d48e97 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -194,8 +194,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             param_env,
             memory: Memory::new(tcx, memory_data),
             stack: Vec::new(),
-            stack_limit: tcx.sess.const_eval_stack_frame_limit.get(),
-            steps_remaining: tcx.sess.const_eval_step_limit.get(),
+            stack_limit: tcx.sess.const_eval_stack_frame_limit,
+            steps_remaining: tcx.sess.const_eval_step_limit,
         }
     }
 
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 8762e7550cd..a701fe31442 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -14,9 +14,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 */
 
-#![deny(warnings)]
-
 #![feature(slice_patterns)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(from_ref)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -32,6 +31,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(rustc_diagnostic_macros)]
 #![feature(nonzero)]
 #![feature(inclusive_range_fields)]
+#![feature(crate_visibility_modifier)]
+#![cfg_attr(stage0, feature(try_trait))]
 
 extern crate arena;
 #[macro_use]
@@ -53,6 +54,16 @@ extern crate log_settings;
 extern crate rustc_apfloat;
 extern crate byteorder;
 
+#[cfg(stage0)]
+macro_rules! do_catch {
+  ($t:expr) => { (|| ::std::ops::Try::from_ok($t) )() }
+}
+
+#[cfg(not(stage0))]
+macro_rules! do_catch {
+  ($t:expr) => { do catch { $t } }
+}
+
 mod diagnostics;
 
 mod borrow_check;
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 209f6dbfa48..83ef28e4f15 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -325,7 +325,7 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut roots = Vec::new();
 
     {
-        let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _)| {
+        let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _, _)| {
             tcx.hir.local_def_id(node_id)
         });
 
@@ -457,7 +457,7 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
-    if recursion_depth > tcx.sess.recursion_limit.get() {
+    if recursion_depth > *tcx.sess.recursion_limit.get() {
         let error = format!("reached the recursion limit while instantiating `{}`",
                             instance);
         if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
@@ -484,7 +484,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // which means that rustc basically hangs.
     //
     // Bail out in these cases to avoid that bad user experience.
-    let type_length_limit = tcx.sess.type_length_limit.get();
+    let type_length_limit = *tcx.sess.type_length_limit.get();
     if type_length > type_length_limit {
         // The instance name is already known to be too long for rustc. Use
         // `{:.64}` to avoid blasting the user's terminal with thousands of
@@ -1038,7 +1038,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
     /// the return type of `main`. This is not needed when
     /// the user writes their own `start` manually.
     fn push_extra_entry_roots(&mut self) {
-        if self.tcx.sess.entry_type.get() != Some(config::EntryMain) {
+        if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryMain) {
             return
         }
 
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index c2f4359c008..181751f1777 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -92,7 +92,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
         match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => {
                 let entry_def_id =
-                    tcx.sess.entry_fn.borrow().map(|(id, _)| tcx.hir.local_def_id(id));
+                    tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir.local_def_id(id));
                 // If this function isn't inlined or otherwise has explicit
                 // linkage, then we'll be creating a globally shared version.
                 if self.explicit_linkage(tcx).is_some() ||
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index da4cb4ec789..f29f86af4ab 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -112,11 +112,11 @@ use rustc::ty::{self, TyCtxt, InstanceDef};
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use std::collections::hash_map::Entry;
+use std::cmp;
 use syntax::ast::NodeId;
 use syntax::symbol::{Symbol, InternedString};
 use rustc::mir::mono::MonoItem;
 use monomorphize::item::{MonoItemExt, InstantiationMode};
-use core::usize;
 
 pub use rustc::mir::mono::CodegenUnit;
 
@@ -189,11 +189,9 @@ pub trait CodegenUnitExt<'tcx> {
             }, item.symbol_name(tcx))
         }
 
-        let items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
-        let mut items : Vec<_> = items.iter()
-            .map(|il| (il, item_sort_key(tcx, il.0))).collect();
-        items.sort_by(|&(_, ref key1), &(_, ref key2)| key1.cmp(key2));
-        items.into_iter().map(|(&item_linkage, _)| item_linkage).collect()
+        let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
+        items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
+        items
     }
 }
 
@@ -509,7 +507,7 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
     // Merge the two smallest codegen units until the target size is reached.
     while codegen_units.len() > target_cgu_count {
         // Sort small cgus to the back
-        codegen_units.sort_by_key(|cgu| usize::MAX - cgu.size_estimate());
+        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
         let mut smallest = codegen_units.pop().unwrap();
         let second_smallest = codegen_units.last_mut().unwrap();
 
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 5e15348de5e..d6b3e674f8f 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -284,7 +284,8 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx>
+    fn cannot_assign(self, span: Span, desc: &str, o: Origin)
+                     -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0594,
                                   "cannot assign to {}{OGN}",
diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs
new file mode 100644
index 00000000000..f04f9233447
--- /dev/null
+++ b/src/librustc_mir/util/collect_writes.rs
@@ -0,0 +1,67 @@
+// 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::mir::{Local, Location};
+use rustc::mir::Mir;
+use rustc::mir::visit::PlaceContext;
+use rustc::mir::visit::Visitor;
+
+crate trait FindAssignments {
+    // Finds all statements that assign directly to local (i.e., X = ...)
+    // and returns their locations.
+    fn find_assignments(&self, local: Local) -> Vec<Location>;
+}
+
+impl<'tcx> FindAssignments for Mir<'tcx>{
+    fn find_assignments(&self, local: Local) -> Vec<Location>{
+            let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
+            visitor.visit_mir(self);
+            visitor.locations
+    }
+}
+
+// The Visitor walks the MIR to return the assignment statements corresponding
+// to a Local.
+struct FindLocalAssignmentVisitor {
+    needle: Local,
+    locations: Vec<Location>,
+}
+
+impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor {
+    fn visit_local(&mut self,
+                   local: &Local,
+                   place_context: PlaceContext<'tcx>,
+                   location: Location) {
+        if self.needle != *local {
+            return;
+        }
+
+        match place_context {
+            PlaceContext::Store | PlaceContext::Call => {
+                self.locations.push(location);
+            }
+            PlaceContext::AsmOutput |
+            PlaceContext::Drop |
+            PlaceContext::Inspect |
+            PlaceContext::Borrow { .. } |
+            PlaceContext::Projection(..) |
+            PlaceContext::Copy |
+            PlaceContext::Move |
+            PlaceContext::StorageLive |
+            PlaceContext::StorageDead |
+            PlaceContext::Validate => {
+                // TO-DO
+                // self.super_local(local)
+            }
+        }
+    }
+    // TO-DO
+    // fn super_local()
+}
diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs
index eebe5a86018..19cd3766886 100644
--- a/src/librustc_mir/util/mod.rs
+++ b/src/librustc_mir/util/mod.rs
@@ -17,6 +17,7 @@ mod alignment;
 mod graphviz;
 pub(crate) mod pretty;
 pub mod liveness;
+pub mod collect_writes;
 
 pub use self::alignment::is_disaligned;
 pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 4509cace794..a891e372ad8 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -137,7 +137,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
 ) where
     F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
 {
-    let _: io::Result<()> = do catch {
+    let _: io::Result<()> = do_catch! {{
         let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
         writeln!(file, "// MIR for `{}`", node_path)?;
         writeln!(file, "// source = {:?}", source)?;
@@ -150,16 +150,14 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
         extra_data(PassWhere::BeforeCFG, &mut file)?;
         write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?;
         extra_data(PassWhere::AfterCFG, &mut file)?;
-        Ok(())
-    };
+    }};
 
     if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
-        let _: io::Result<()> = do catch {
+        let _: io::Result<()> = do_catch! {{
             let mut file =
                 create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
             write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
-            Ok(())
-        };
+        }};
     }
 }
 
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 1f6cc1f71fc..e65c9de8df1 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -17,7 +17,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 76cbc670969..c5d2f0041a0 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -407,7 +407,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprBlock(_) |
         hir::ExprIndex(..) |
         hir::ExprField(..) |
-        hir::ExprTupField(..) |
         hir::ExprArray(_) |
         hir::ExprType(..) |
         hir::ExprTup(..) => {}
diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs
index 4cc65ee28e8..b57debdd994 100644
--- a/src/librustc_platform_intrinsics/lib.rs
+++ b/src/librustc_platform_intrinsics/lib.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
 #![allow(bad_style)]
 
 pub struct Intrinsic {
diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs
index c0f830f1fbe..622d8e51a6c 100644
--- a/src/librustc_plugin/lib.rs
+++ b/src/librustc_plugin/lib.rs
@@ -63,7 +63,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 #![feature(staged_api)]
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index d951a7f1cc1..ee08e622390 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -11,7 +11,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 
@@ -569,8 +568,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
                     // If the expression uses FRU we need to make sure all the unmentioned fields
                     // are checked for privacy (RFC 736). Rather than computing the set of
                     // unmentioned fields, just check them all.
-                    for variant_field in &variant.fields {
-                        let field = fields.iter().find(|f| f.name.node == variant_field.name);
+                    for (vf_index, variant_field) in variant.fields.iter().enumerate() {
+                        let field = fields.iter().find(|f| {
+                            self.tcx.field_index(f.id, self.tables) == vf_index
+                        });
                         let (use_ctxt, span) = match field {
                             Some(field) => (field.name.node.to_ident().span, field.span),
                             None => (base.span, base.span),
@@ -580,8 +581,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
                 } else {
                     for field in fields {
                         let use_ctxt = field.name.node.to_ident().span;
-                        let field_def = variant.field_named(field.name.node);
-                        self.check_field(use_ctxt, field.span, adt, field_def);
+                        let index = self.tcx.field_index(field.id, self.tables);
+                        self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
                     }
                 }
             }
@@ -599,8 +600,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
                 let variant = adt.variant_of_def(def);
                 for field in fields {
                     let use_ctxt = field.node.name.to_ident().span;
-                    let field_def = variant.field_named(field.node.name);
-                    self.check_field(use_ctxt, field.span, adt, field_def);
+                    let index = self.tcx.field_index(field.node.id, self.tables);
+                    self.check_field(use_ctxt, field.span, adt, &variant.fields[index]);
                 }
             }
             _ => {}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 2bf17cd1317..d32d853c18b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -11,9 +11,9 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
 
 #[macro_use]
 extern crate log;
@@ -1150,13 +1150,9 @@ impl<'a> ModuleData<'a> {
 
     fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
         let resolutions = self.resolutions.borrow();
-        let mut resolutions = resolutions.iter().map(|(&(ident, ns), &resolution)| {
-                                                    // Pre-compute keys for sorting
-                                                    (ident.name.as_str(), ns, ident, resolution)
-                                                })
-                                                .collect::<Vec<_>>();
-        resolutions.sort_unstable_by_key(|&(str, ns, ..)| (str, ns));
-        for &(_, ns, ident, resolution) in resolutions.iter() {
+        let mut resolutions = resolutions.iter().collect::<Vec<_>>();
+        resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.name.as_str(), ns));
+        for &(&(ident, ns), &resolution) in resolutions.iter() {
             resolution.borrow().binding.map(|binding| f(ident, ns, binding));
         }
     }
@@ -3341,7 +3337,9 @@ impl<'a> Resolver<'a> {
                         let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
                         let mut candidates =
                             self.lookup_import_candidates(name, TypeNS, is_mod);
-                        candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string()));
+                        candidates.sort_by_cached_key(|c| {
+                            (c.path.segments.len(), c.path.to_string())
+                        });
                         if let Some(candidate) = candidates.get(0) {
                             format!("Did you mean `{}`?", candidate.path)
                         } else {
@@ -3579,7 +3577,7 @@ impl<'a> Resolver<'a> {
 
         let name = path[path.len() - 1].name;
         // Make sure error reporting is deterministic.
-        names.sort_by_key(|name| name.as_str());
+        names.sort_by_cached_key(|name| name.as_str());
         match find_best_match_for_name(names.iter(), &name.as_str(), None) {
             Some(found) if found != name => Some(found),
             _ => None,
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 607701b056b..abaa02a856e 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -25,7 +25,6 @@
 
 use rustc::hir::def::Def as HirDef;
 use rustc::hir::def_id::DefId;
-use rustc::hir::map::Node;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 
@@ -1006,20 +1005,16 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 };
                 let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id));
 
-                for &Spanned {
-                    node: ref field,
-                    span,
-                } in fields
-                {
+                for &Spanned { node: ref field, span } in fields {
                     let sub_span = self.span.span_for_first_ident(span);
-                    if let Some(f) = variant.find_field_named(field.ident.name) {
+                    if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
                         if !self.span.filter_generated(sub_span, span) {
                             let span =
                                 self.span_from_span(sub_span.expect("No span fund for var ref"));
                             self.dumper.dump_ref(Ref {
                                 kind: RefKind::Variable,
                                 span,
-                                ref_id: ::id_from_def_id(f.did),
+                                ref_id: ::id_from_def_id(variant.fields[index].did),
                             });
                         }
                     }
@@ -1638,52 +1633,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                     }
                 }
             }
-            ast::ExprKind::TupField(ref sub_ex, idx) => {
-                self.visit_expr(&sub_ex);
-
-                let hir_node = match self.save_ctxt.tcx.hir.find(sub_ex.id) {
-                    Some(Node::NodeExpr(expr)) => expr,
-                    _ => {
-                        debug!(
-                            "Missing or weird node for sub-expression {} in {:?}",
-                            sub_ex.id,
-                            ex
-                        );
-                        return;
-                    }
-                };
-                let ty = match self.save_ctxt.tables.expr_ty_adjusted_opt(&hir_node) {
-                    Some(ty) => &ty.sty,
-                    None => {
-                        visit::walk_expr(self, ex);
-                        return;
-                    }
-                };
-                match *ty {
-                    ty::TyAdt(def, _) => {
-                        let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
-                        if !self.span.filter_generated(sub_span, ex.span) {
-                            let span =
-                                self.span_from_span(sub_span.expect("No span found for var ref"));
-                            if let Some(field) = def.non_enum_variant().fields.get(idx.node) {
-                                let ref_id = ::id_from_def_id(field.did);
-                                self.dumper.dump_ref(Ref {
-                                    kind: RefKind::Variable,
-                                    span,
-                                    ref_id,
-                                });
-                            } else {
-                                return;
-                            }
-                        }
-                    }
-                    ty::TyTuple(..) => {}
-                    _ => {
-                        debug!("Expected struct or tuple type, found {:?}", ty);
-                        return;
-                    }
-                }
-            }
             ast::ExprKind::Closure(_, _, ref decl, ref body, _fn_decl_span) => {
                 let mut id = String::from("$");
                 id.push_str(&ex.id.to_string());
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4f46fb3545b..ca19ed0df67 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -11,7 +11,6 @@
 #![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/")]
-#![deny(warnings)]
 #![feature(custom_attribute)]
 #![feature(macro_lifetime_matcher)]
 #![allow(unused_attributes)]
@@ -554,16 +553,18 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 };
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
-                        let f = def.non_enum_variant().field_named(ident.name);
+                        let variant = &def.non_enum_variant();
+                        let index = self.tcx.find_field_index(ident, variant).unwrap();
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
                         filter!(self.span_utils, sub_span, expr.span, None);
                         let span = self.span_from_span(sub_span.unwrap());
                         return Some(Data::RefData(Ref {
                             kind: RefKind::Variable,
                             span,
-                            ref_id: id_from_def_id(f.did),
+                            ref_id: id_from_def_id(variant.fields[index].did),
                         }));
                     }
+                    ty::TyTuple(..) => None,
                     _ => {
                         debug!("Expected struct or union type, found {:?}", ty);
                         None
@@ -817,7 +818,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         field_ref: &ast::Field,
         variant: &ty::VariantDef,
     ) -> Option<Ref> {
-        let f = variant.find_field_named(field_ref.ident.name)?;
+        let index = self.tcx.find_field_index(field_ref.ident, variant).unwrap();
         // We don't really need a sub-span here, but no harm done
         let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
         filter!(self.span_utils, sub_span, field_ref.ident.span, None);
@@ -825,7 +826,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         Some(Ref {
             kind: RefKind::Variable,
             span,
-            ref_id: id_from_def_id(f.did),
+            ref_id: id_from_def_id(variant.fields[index].did),
         })
     }
 
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index d5a58c08cbe..4d93e81a78f 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -202,10 +202,6 @@ impl<'a> SpanUtils<'a> {
         self.sub_span_after(span, |t| t.is_keyword(keyword))
     }
 
-    pub fn sub_span_after_token(&self, span: Span, tok: Token) -> Option<Span> {
-        self.sub_span_after(span, |t| t == tok)
-    }
-
     fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span> {
         let mut toks = self.retokenise_span(span);
         loop {
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 1fe2f87128a..5f4daf0d568 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -153,7 +153,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
         span, for_ty, depth, ty
     );
 
-    if depth >= tcx.sess.recursion_limit.get() {
+    if depth >= *tcx.sess.recursion_limit.get() {
         return Ok(DtorckConstraint {
             outlives: vec![],
             dtorck_types: vec![],
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index cfa3b6912f2..8136f6857a5 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -11,8 +11,6 @@
 //! New recursive solver modeled on Chalk's recursive solver. Most of
 //! the guts are broken up into modules; see the comments in those modules.
 
-#![deny(warnings)]
-
 #![feature(crate_visibility_modifier)]
 
 #[macro_use]
diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs
index 153b2e73033..df6793e8a60 100644
--- a/src/librustc_traits/lowering.rs
+++ b/src/librustc_traits/lowering.rs
@@ -11,12 +11,14 @@
 use rustc::hir::{self, ImplPolarity};
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, Slice, TyCtxt};
 use rustc::ty::subst::Substs;
-use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause};
+use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause, Goal};
 use syntax::ast;
 use rustc_data_structures::sync::Lrc;
 
+use std::iter;
+
 trait Lower<T> {
     /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
     fn lower(&self) -> T;
@@ -90,8 +92,30 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
     }
 }
 
+/// Transforms an existing goal into a FromEnv goal.
+///
+/// Used for lowered where clauses (see rustc guide).
+trait IntoFromEnvGoal {
+    fn into_from_env_goal(self) -> Self;
+}
+
+impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
+    fn into_from_env_goal(self) -> DomainGoal<'tcx> {
+        use self::DomainGoal::*;
+        match self {
+            Holds(wc_atom) => FromEnv(wc_atom),
+            WellFormed(..) |
+            FromEnv(..) |
+            WellFormedTy(..) |
+            FromEnvTy(..) |
+            RegionOutlives(..) |
+            TypeOutlives(..) => self,
+        }
+    }
+}
+
 crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-    -> Lrc<Vec<Clause<'tcx>>>
+                                       -> Lrc<&'tcx Slice<Clause<'tcx>>>
 {
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let item = tcx.hir.expect_item(node_id);
@@ -100,16 +124,16 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
         hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
 
         // FIXME: other constructions e.g. traits, associated types...
-        _ => Lrc::new(vec![]),
+        _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
     }
 }
 
 fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-    -> Lrc<Vec<Clause<'tcx>>>
+                                       -> Lrc<&'tcx Slice<Clause<'tcx>>>
 {
-    // Rule Implemented-From-Env (see rustc guide)
-    //
     // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
+
+    // Rule Implemented-From-Env (see rustc guide)
     //
     // ```
     // forall<Self, P1..Pn> {
@@ -125,23 +149,62 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
         }
     };
     // `FromEnv(Self: Trait<P1..Pn>)`
-    let from_env = DomainGoal::FromEnv(trait_pred.lower()).into();
+    let from_env = Goal::from(DomainGoal::FromEnv(trait_pred.lower()));
     // `Implemented(Self: Trait<P1..Pn>)`
     let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
 
     // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
-    let clause = ProgramClause {
+    let implemented_from_env = ProgramClause {
         goal: impl_trait,
-        hypotheses: vec![from_env],
+        hypotheses: tcx.mk_goals(iter::once(from_env)),
     };
-    Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))])
+    let clauses = iter::once(
+        Clause::ForAll(ty::Binder::dummy(implemented_from_env))
+    );
+
+    // Rule Implied-Bound-From-Trait
+    //
+    // For each where clause WC:
+    // ```
+    // forall<Self, P1..Pn> {
+    //   FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn)
+    // }
+    // ```
+
+    // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
+    // FIXME: Remove the [1..] slice; this is a hack because the query
+    // predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
+    let where_clauses = &tcx.predicates_of(def_id).predicates;
+    let implied_bound_clauses =
+        where_clauses[1..].into_iter()
+        .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc));
+
+    Lrc::new(tcx.mk_clauses(clauses.chain(implied_bound_clauses)))
+}
+
+/// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`.
+fn implied_bound_from_trait<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    trait_pred: ty::TraitPredicate<'tcx>,
+    where_clause: &ty::Predicate<'tcx>,
+) -> Clause<'tcx> {
+    // `FromEnv(Self: Trait<P1..Pn>)`
+    let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred));
+
+    // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
+    Clause::ForAll(
+        where_clause.lower().map_bound(|goal| ProgramClause {
+            goal: goal.into_from_env_goal(),
+            hypotheses: tcx.mk_goals(iter::once(Goal::from(impl_trait))),
+        })
+    )
 }
 
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-    -> Lrc<Vec<Clause<'tcx>>>
+                                      -> Lrc<&'tcx Slice<Clause<'tcx>>>
 {
     if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
-        return Lrc::new(vec![]);
+        return Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()));
     }
 
     // Rule Implemented-From-Impl (see rustc guide)
@@ -163,9 +226,11 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
      // `Implemented(A0: Trait<A1..An>) :- WC`
     let clause = ProgramClause {
         goal: trait_pred,
-        hypotheses: where_clauses.into_iter().map(|wc| wc.into()).collect()
+        hypotheses: tcx.mk_goals(
+            where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx))
+        )
     };
-    Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))])
+    Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))))
 }
 
 pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -187,7 +252,7 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx > {
         for attr in attrs {
             if attr.check_name("rustc_dump_program_clauses") {
                 let clauses = self.tcx.program_clauses_for(def_id);
-                for clause in &*clauses {
+                for clause in *clauses {
                     // Skip the top-level binder for a less verbose output
                     let program_clause = match clause {
                         Clause::Implies(program_clause) => program_clause,
diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs
index 14f8694dbf7..1857df5717b 100644
--- a/src/librustc_traits/normalize_erasing_regions.rs
+++ b/src/librustc_traits/normalize_erasing_regions.rs
@@ -11,17 +11,14 @@
 use rustc::traits::{Normalized, ObligationCause};
 use rustc::traits::query::NoSolution;
 use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
-use rustc::util::common::CellUsizeExt;
+use std::sync::atomic::Ordering;
 
 crate fn normalize_ty_after_erasing_regions<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> Ty<'tcx> {
     let ParamEnvAnd { param_env, value } = goal;
-    tcx.sess
-        .perf_stats
-        .normalize_ty_after_erasing_regions
-        .increment();
+    tcx.sess.perf_stats.normalize_ty_after_erasing_regions.fetch_add(1, Ordering::Relaxed);
     tcx.infer_ctxt().enter(|infcx| {
         let cause = ObligationCause::dummy();
         match infcx.at(&cause, param_env).normalize(&value) {
diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs
index 62d5ef11551..8fc00c937e6 100644
--- a/src/librustc_traits/normalize_projection_ty.rs
+++ b/src/librustc_traits/normalize_projection_ty.rs
@@ -13,11 +13,11 @@ use rustc::traits::{self, FulfillmentContext, Normalized, ObligationCause,
                     SelectionContext};
 use rustc::traits::query::{CanonicalProjectionGoal, NoSolution, normalize::NormalizationResult};
 use rustc::ty::{ParamEnvAnd, TyCtxt};
-use rustc::util::common::CellUsizeExt;
 use rustc_data_structures::sync::Lrc;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::DUMMY_SP;
 use util;
+use std::sync::atomic::Ordering;
 
 crate fn normalize_projection_ty<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
@@ -25,7 +25,7 @@ crate fn normalize_projection_ty<'tcx>(
 ) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, NormalizationResult<'tcx>>>>, NoSolution> {
     debug!("normalize_provider(goal={:#?})", goal);
 
-    tcx.sess.perf_stats.normalize_projection_ty.increment();
+    tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed);
     tcx.infer_ctxt().enter(|ref infcx| {
         let (
             ParamEnvAnd {
diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs
index e1c145b122d..f2dd2ed8460 100644
--- a/src/librustc_trans/allocator.rs
+++ b/src/librustc_trans/allocator.rs
@@ -30,7 +30,6 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
     };
     let i8 = llvm::LLVMInt8TypeInContext(llcx);
     let i8p = llvm::LLVMPointerType(i8, 0);
-    let usizep = llvm::LLVMPointerType(usize, 0);
     let void = llvm::LLVMVoidTypeInContext(llcx);
 
     for method in ALLOCATOR_METHODS {
@@ -41,40 +40,21 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
                     args.push(usize); // size
                     args.push(usize); // align
                 }
-                AllocatorTy::LayoutRef => args.push(i8p),
                 AllocatorTy::Ptr => args.push(i8p),
-                AllocatorTy::AllocErr => args.push(i8p),
+                AllocatorTy::Usize => args.push(usize),
 
                 AllocatorTy::Bang |
-                AllocatorTy::ResultExcess |
                 AllocatorTy::ResultPtr |
-                AllocatorTy::ResultUnit |
-                AllocatorTy::UsizePair |
                 AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
         }
         let output = match method.output {
-            AllocatorTy::UsizePair => {
-                args.push(usizep); // min
-                args.push(usizep); // max
-                None
-            }
             AllocatorTy::Bang => None,
-            AllocatorTy::ResultExcess => {
-                args.push(i8p); // excess_ptr
-                args.push(i8p); // err_ptr
-                Some(i8p)
-            }
-            AllocatorTy::ResultPtr => {
-                args.push(i8p); // err_ptr
-                Some(i8p)
-            }
-            AllocatorTy::ResultUnit => Some(i8),
+            AllocatorTy::ResultPtr => Some(i8p),
             AllocatorTy::Unit => None,
 
-            AllocatorTy::AllocErr |
             AllocatorTy::Layout |
-            AllocatorTy::LayoutRef |
+            AllocatorTy::Usize |
             AllocatorTy::Ptr => panic!("invalid allocator output"),
         };
         let ty = llvm::LLVMFunctionType(output.unwrap_or(void),
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index acd2a765730..965a34eccb8 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -157,12 +157,12 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         })
         .collect();
 
-    if let Some(id) = tcx.sess.derive_registrar_fn.get() {
+    if let Some(id) = *tcx.sess.derive_registrar_fn.get() {
         let def_id = tcx.hir.local_def_id(id);
         reachable_non_generics.insert(def_id, SymbolExportLevel::C);
     }
 
-    if let Some(id) = tcx.sess.plugin_registrar_fn.get() {
+    if let Some(id) = *tcx.sess.plugin_registrar_fn.get() {
         let def_id = tcx.hir.local_def_id(id);
         reachable_non_generics.insert(def_id, SymbolExportLevel::C);
     }
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index fc699f7569f..f501b1739eb 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -154,13 +154,16 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
     }
 }
 
-pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
-    target_machine_factory(sess)().unwrap_or_else(|err| {
+pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef {
+    target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
         llvm_err(sess.diagnostic(), err).raise()
     })
 }
 
-pub fn target_machine_factory(sess: &Session)
+// If find_features is true this won't access `sess.crate_types` by assuming
+// that `is_pie_binary` is false. When we discover LLVM target features
+// `sess.crate_types` is uninitialized so we cannot access it.
+pub fn target_machine_factory(sess: &Session, find_features: bool)
     -> Arc<Fn() -> Result<TargetMachineRef, String> + Send + Sync>
 {
     let reloc_model = get_reloc_model(sess);
@@ -201,7 +204,7 @@ pub fn target_machine_factory(sess: &Session)
     };
     let cpu = CString::new(cpu.as_bytes()).unwrap();
     let features = CString::new(target_feature(sess).as_bytes()).unwrap();
-    let is_pie_binary = is_pie_binary(sess);
+    let is_pie_binary = !find_features && is_pie_binary(sess);
     let trap_unreachable = sess.target.target.options.trap_unreachable;
 
     Arc::new(move || {
@@ -1035,7 +1038,7 @@ pub fn start_async_translation(tcx: TyCtxt,
         crate_info,
 
         time_graph,
-        coordinator_send: tcx.tx_to_llvm_workers.clone(),
+        coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
         trans_worker_receive,
         shared_emitter_main,
         future: coordinator_thread,
@@ -1428,7 +1431,7 @@ fn start_executing_work(tcx: TyCtxt,
                         metadata_config: Arc<ModuleConfig>,
                         allocator_config: Arc<ModuleConfig>)
                         -> thread::JoinHandle<Result<CompiledModules, ()>> {
-    let coordinator_send = tcx.tx_to_llvm_workers.clone();
+    let coordinator_send = tcx.tx_to_llvm_workers.lock().clone();
     let sess = tcx.sess;
 
     // Compute the set of symbols we need to retain when doing LTO (if we need to)
@@ -1510,7 +1513,7 @@ fn start_executing_work(tcx: TyCtxt,
         regular_module_config: modules_config,
         metadata_module_config: metadata_config,
         allocator_module_config: allocator_config,
-        tm_factory: target_machine_factory(tcx.sess),
+        tm_factory: target_machine_factory(tcx.sess, false),
         total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
@@ -2340,7 +2343,7 @@ pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt,
                                                mtrans: ModuleTranslation,
                                                cost: u64) {
     let llvm_work_item = WorkItem::Optimize(mtrans);
-    drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone {
+    drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::TranslationDone {
         llvm_work_item,
         cost,
     })));
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 0329264a312..1da6f25fd63 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -82,7 +82,8 @@ use std::ffi::CString;
 use std::str;
 use std::sync::Arc;
 use std::time::{Instant, Duration};
-use std::{i32, usize};
+use std::i32;
+use std::cmp;
 use std::sync::mpsc;
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
@@ -517,7 +518,7 @@ pub fn set_link_section(cx: &CodegenCx,
 /// users main function.
 fn maybe_create_entry_wrapper(cx: &CodegenCx) {
     let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
-        Some((id, span)) => {
+        Some((id, span, _)) => {
             (cx.tcx.hir.local_def_id(id), span)
         }
         None => return,
@@ -533,11 +534,11 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
 
     let main_llfn = callee::get_fn(cx, instance);
 
-    let et = cx.sess().entry_type.get().unwrap();
+    let et = cx.sess().entry_fn.get().map(|e| e.2);
     match et {
-        config::EntryMain => create_entry_fn(cx, span, main_llfn, main_def_id, true),
-        config::EntryStart => create_entry_fn(cx, span, main_llfn, main_def_id, false),
-        config::EntryNone => {}    // Do nothing.
+        Some(config::EntryMain) => create_entry_fn(cx, span, main_llfn, main_def_id, true),
+        Some(config::EntryStart) => create_entry_fn(cx, span, main_llfn, main_def_id, false),
+        None => {}    // Do nothing.
     }
 
     fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
@@ -737,7 +738,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         source: ModuleSource::Translated(ModuleLlvm {
             llcx: metadata_llcx,
             llmod: metadata_llmod,
-            tm: create_target_machine(tcx.sess),
+            tm: create_target_machine(tcx.sess, false),
         }),
         kind: ModuleKind::Metadata,
     };
@@ -795,7 +796,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         codegen_units.len());
 
     // Translate an allocator shim, if any
-    let allocator_module = if let Some(kind) = tcx.sess.allocator_kind.get() {
+    let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() {
         unsafe {
             let llmod_id = "allocator";
             let (llcx, llmod) =
@@ -803,7 +804,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let modules = ModuleLlvm {
                 llmod,
                 llcx,
-                tm: create_target_machine(tcx.sess),
+                tm: create_target_machine(tcx.sess, false),
             };
             time(tcx.sess, "write allocator module", || {
                 allocator::trans(tcx, &modules, kind)
@@ -830,7 +831,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // a bit more efficiently.
     let codegen_units = {
         let mut codegen_units = codegen_units;
-        codegen_units.sort_by_key(|cgu| usize::MAX - cgu.size_estimate());
+        codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
         codegen_units
     };
 
@@ -1260,7 +1261,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let llvm_module = ModuleLlvm {
                 llcx: cx.llcx,
                 llmod: cx.llmod,
-                tm: create_target_machine(cx.sess()),
+                tm: create_target_machine(cx.sess(), false),
             };
 
             ModuleTranslation {
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 1f2c3cc883c..fe8a7052bdf 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -162,7 +162,7 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
-        let tm = ::back::write::create_target_machine(sess);
+        let tm = ::back::write::create_target_machine(sess, false);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
         llvm::LLVMRustDisposeTargetMachine(tm);
 
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 7664c88679e..28311018ee7 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -42,7 +42,7 @@ use std::ptr;
 
 use syntax_pos::{self, Span, Pos};
 use syntax::ast;
-use syntax::symbol::Symbol;
+use syntax::symbol::{Symbol, InternedString};
 use rustc::ty::layout::{self, LayoutOf};
 
 pub mod gdb;
@@ -263,7 +263,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     let local_id = cx.tcx.hir.as_local_node_id(def_id);
     match *cx.sess().entry_fn.borrow() {
-        Some((id, _)) => {
+        Some((id, _, _)) => {
             if local_id == Some(id) {
                 flags = flags | DIFlags::FlagMainSubprogram;
             }
@@ -393,7 +393,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_str().as_bytes()).unwrap();
+                let name = CString::new(name.as_bytes()).unwrap();
                 unsafe {
                     llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
@@ -412,7 +412,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return create_DIArray(DIB(cx), &template_params[..]);
     }
 
-    fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<ast::Name> {
+    fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<InternedString> {
         let mut names = generics.parent.map_or(vec![], |def_id| {
             get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
         });
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 344f959c141..a38d51e7546 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -17,7 +17,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -27,6 +26,7 @@
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(optin_builtin_traits)]
 #![feature(inclusive_range_fields)]
 #![feature(underscore_lifetimes)]
diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index 1c8f09ce7b3..fa3ecb1cc11 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -134,13 +134,14 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
         ("x86", "pclmulqdq") => "pclmul",
         ("x86", "rdrand") => "rdrnd",
         ("x86", "bmi1") => "bmi",
+        ("aarch64", "fp") => "fp-armv8",
         ("aarch64", "fp16") => "fullfp16",
         (_, s) => s,
     }
 }
 
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
-    let target_machine = create_target_machine(sess);
+    let target_machine = create_target_machine(sess, true);
     target_feature_whitelist(sess)
         .iter()
         .filter(|feature| {
@@ -178,7 +179,7 @@ pub fn print_passes() {
 
 pub(crate) fn print(req: PrintRequest, sess: &Session) {
     require_inited();
-    let tm = create_target_machine(sess);
+    let tm = create_target_machine(sess, true);
     unsafe {
         match req {
             PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index cf47d9b62a9..0c6bc9e246b 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -15,7 +15,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -52,7 +51,7 @@ pub mod symbol_names_test;
 /// that actually test that compilation succeeds without
 /// reporting an error.
 pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
-    if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
+    if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() {
         let main_def_id = tcx.hir.local_def_id(id);
 
         if tcx.has_attr(main_def_id, "rustc_error") {
diff --git a/src/librustc_trans_utils/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs
index af174f7ce85..f3b7326b210 100644
--- a/src/librustc_trans_utils/symbol_names.rs
+++ b/src/librustc_trans_utils/symbol_names.rs
@@ -244,11 +244,11 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
     let node_id = tcx.hir.as_local_node_id(def_id);
 
     if let Some(id) = node_id {
-        if tcx.sess.plugin_registrar_fn.get() == Some(id) {
+        if *tcx.sess.plugin_registrar_fn.get() == Some(id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
-        if tcx.sess.derive_registrar_fn.get() == Some(id) {
+        if *tcx.sess.derive_registrar_fn.get() == Some(id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_derive_registrar_symbol(disambiguator);
         }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 0e93277983f..c4ea543ab36 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -979,7 +979,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))
+                tcx.mk_param(index, tcx.hir.name(node_id).as_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index ae373fbad22..7b4dc60409b 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -860,7 +860,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
         // Index the struct fields' types.
         let field_map = variant.fields
             .iter()
-            .map(|field| (field.name, field))
+            .enumerate()
+            .map(|(i, field)| (field.name.to_ident(), (i, field)))
             .collect::<FxHashMap<_, _>>();
 
         // Keep track of which fields have already appeared in the pattern.
@@ -869,7 +870,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
         let mut inexistent_fields = vec![];
         // Typecheck each field.
         for &Spanned { node: ref field, span } in fields {
-            let field_ty = match used_fields.entry(field.name) {
+            let ident = tcx.adjust(field.name, variant.did, self.body_id).0;
+            let field_ty = match used_fields.entry(ident) {
                 Occupied(occupied) => {
                     struct_span_err!(tcx.sess, span, E0025,
                                      "field `{}` bound multiple times \
@@ -883,10 +885,10 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                 }
                 Vacant(vacant) => {
                     vacant.insert(span);
-                    field_map.get(&field.name)
-                        .map(|f| {
+                    field_map.get(&ident)
+                        .map(|(i, f)| {
+                            self.write_field_index(field.id, *i);
                             self.tcx.check_stability(f.did, Some(pat_id), span);
-
                             self.field_ty(span, f, substs)
                         })
                         .unwrap_or_else(|| {
@@ -958,8 +960,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
         } else if !etc {
             let unmentioned_fields = variant.fields
                 .iter()
-                .map(|field| field.name)
-                .filter(|field| !used_fields.contains_key(&field))
+                .map(|field| field.name.to_ident())
+                .filter(|ident| !used_fields.contains_key(&ident))
                 .collect::<Vec<_>>();
             if unmentioned_fields.len() > 0 {
                 let field_names = if unmentioned_fields.len() == 1 {
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 1d7c533178f..a87058d1fa5 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -56,9 +56,9 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
             return Some((self.cur_ty, 0));
         }
 
-        if self.steps.len() >= tcx.sess.recursion_limit.get() {
+        if self.steps.len() >= *tcx.sess.recursion_limit.get() {
             // We've reached the recursion limit, error gracefully.
-            let suggested_limit = tcx.sess.recursion_limit.get() * 2;
+            let suggested_limit = *tcx.sess.recursion_limit.get() * 2;
             let msg = format!("reached the recursion limit while auto-dereferencing {:?}",
                               self.cur_ty);
             let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg.clone());
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 8db8e52b10d..734d72584da 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -486,11 +486,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                     ty::TypeVariants::TyInfer(t) => {
                         match t {
                             ty::InferTy::IntVar(_) |
-                            ty::InferTy::FloatVar(_) |
-                            ty::InferTy::FreshIntTy(_) |
-                            ty::InferTy::FreshFloatTy(_) => {
-                                Err(CastError::NeedDeref)
-                            }
+                            ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref),
                             _ => Err(CastError::NeedViaPtr),
                         }
                     }
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 377e3a89184..da0d4509353 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)));
+    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_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));
+        let name = Symbol::intern(&format!("P{}", n)).as_str();
         tcx.mk_param(n, name)
     };
 
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 3705c53a76f..7569bdccd5a 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -433,7 +433,6 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             let last = exprs[exprs.len() - 1];
             match last.node {
                 hir::ExprField(ref expr, _) |
-                hir::ExprTupField(ref expr, _) |
                 hir::ExprIndex(ref expr, _) |
                 hir::ExprUnary(hir::UnDeref, ref expr) => exprs.push(&expr),
                 _ => break,
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index e33e4c51892..49d0df555fa 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -31,6 +31,7 @@ use rustc_data_structures::sync::Lrc;
 
 pub use self::MethodError::*;
 pub use self::CandidateSource::*;
+pub use self::suggest::TraitInfo;
 
 mod confirm;
 pub mod probe;
@@ -38,6 +39,10 @@ mod suggest;
 
 use self::probe::{IsSuggestion, ProbeScope};
 
+pub fn provide(providers: &mut ty::maps::Providers) {
+    suggest::provide(providers);
+}
+
 #[derive(Clone, Copy, Debug)]
 pub struct MethodCallee<'tcx> {
     /// Impl method ID, for inherent methods, or trait method ID, otherwise.
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index fa2022e8cc9..de570956622 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -799,7 +799,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             .collect();
 
         // sort them by the name so we have a stable result
-        names.sort_by_key(|n| n.as_str());
+        names.sort_by_cached_key(|n| n.as_str());
         names
     }
 
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 4bc2d8ce123..d8907866467 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -13,6 +13,7 @@
 
 use check::FnCtxt;
 use rustc::hir::map as hir_map;
+use rustc_data_structures::sync::Lrc;
 use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
 use hir::def::Def;
 use hir::def_id::{CRATE_DEF_INDEX, DefId};
@@ -26,12 +27,12 @@ use syntax::util::lev_distance::find_best_match_for_name;
 use errors::DiagnosticBuilder;
 use syntax_pos::Span;
 
+use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir;
 use rustc::hir::print;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::ty::TyAdt;
 
-use std::cell;
 use std::cmp::Ordering;
 
 use super::{MethodError, NoMatchData, CandidateSource};
@@ -208,6 +209,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     // be used exists at all, and the type is an ambiuous numeric type
                     // ({integer}/{float}).
                     let mut candidates = all_traits(self.tcx)
+                        .into_iter()
                         .filter(|info| {
                             self.associated_item(info.def_id, item_name, Namespace::Value).is_some()
                         });
@@ -302,8 +304,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     for (ty, _) in self.autoderef(span, rcvr_ty) {
                         match ty.sty {
                             ty::TyAdt(def, substs) if !def.is_enum() => {
-                                if let Some(field) = def.non_enum_variant()
-                                    .find_field_named(item_name) {
+                                let variant = &def.non_enum_variant();
+                                if let Some(index) =
+                                        self.tcx.find_field_index(item_name.to_ident(), variant) {
+                                    let field = &variant.fields[index];
                                     let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
                                     let expr_string = match snippet {
                                         Ok(expr_string) => expr_string,
@@ -519,6 +523,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // implement, by finding ones that have the item name, and are
         // legal to implement.
         let mut candidates = all_traits(self.tcx)
+            .into_iter()
             .filter(|info| {
                 // we approximate the coherence rules to only suggest
                 // traits that are legal to implement by requiring that
@@ -603,18 +608,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 }
 
-pub type AllTraitsVec = Vec<DefId>;
-
 #[derive(Copy, Clone)]
 pub struct TraitInfo {
     pub def_id: DefId,
 }
 
-impl TraitInfo {
-    fn new(def_id: DefId) -> TraitInfo {
-        TraitInfo { def_id: def_id }
-    }
-}
 impl PartialEq for TraitInfo {
     fn eq(&self, other: &TraitInfo) -> bool {
         self.cmp(other) == Ordering::Equal
@@ -638,8 +636,12 @@ impl Ord for TraitInfo {
 }
 
 /// Retrieve all traits in this crate and any dependent crates.
-pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> {
-    if tcx.all_traits.borrow().is_none() {
+pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<TraitInfo> {
+    tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
+}
+
+/// Compute all traits in this crate and any dependent crates.
+fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId> {
         use rustc::hir::itemlikevisit;
 
         let mut traits = vec![];
@@ -649,7 +651,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a>
         // meh.
         struct Visitor<'a, 'tcx: 'a> {
             map: &'a hir_map::Map<'tcx>,
-            traits: &'a mut AllTraitsVec,
+            traits: &'a mut Vec<DefId>,
         }
         impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
             fn visit_item(&mut self, i: &'v hir::Item) {
@@ -676,7 +678,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a>
         // Cross-crate:
         let mut external_mods = FxHashSet();
         fn handle_external_def(tcx: TyCtxt,
-                               traits: &mut AllTraitsVec,
+                               traits: &mut Vec<DefId>,
                                external_mods: &mut FxHashSet<DefId>,
                                def: Def) {
             let def_id = def.def_id();
@@ -703,43 +705,16 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a>
             handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id));
         }
 
-        *tcx.all_traits.borrow_mut() = Some(traits);
-    }
-
-    let borrow = tcx.all_traits.borrow();
-    assert!(borrow.is_some());
-    AllTraits {
-        borrow,
-        idx: 0,
-    }
+    traits
 }
 
-pub struct AllTraits<'a> {
-    borrow: cell::Ref<'a, Option<AllTraitsVec>>,
-    idx: usize,
-}
-
-impl<'a> Iterator for AllTraits<'a> {
-    type Item = TraitInfo;
-
-    fn next(&mut self) -> Option<TraitInfo> {
-        let AllTraits { ref borrow, ref mut idx } = *self;
-        // ugh.
-        borrow.as_ref().unwrap().get(*idx).map(|info| {
-            *idx += 1;
-            TraitInfo::new(*info)
-        })
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = self.borrow.as_ref().unwrap().len() - self.idx;
-        (len, Some(len))
+pub fn provide(providers: &mut ty::maps::Providers) {
+    providers.all_traits = |tcx, cnum| {
+        assert_eq!(cnum, LOCAL_CRATE);
+        Lrc::new(compute_all_traits(tcx))
     }
 }
 
-impl<'a> ExactSizeIterator for AllTraits<'a> {}
-
-
 struct UsePlacementFinder<'a, 'tcx: 'a, 'gcx: 'tcx> {
     target_module: ast::NodeId,
     span: Option<Span>,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 6c18f8d285d..ca35153d571 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -85,7 +85,7 @@ use self::method::MethodCallee;
 use self::TupleArgumentsFlag::*;
 
 use astconv::AstConv;
-use hir::def::{Def, CtorKind};
+use hir::def::Def;
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use std::slice;
 use namespace::Namespace;
@@ -121,7 +121,7 @@ use std::ops::{self, Deref};
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax::attr;
-use syntax::codemap::{self, original_sp, Spanned};
+use syntax::codemap::{original_sp, Spanned};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, InternedString, keywords};
@@ -730,6 +730,7 @@ fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: De
 }
 
 pub fn provide(providers: &mut Providers) {
+    method::provide(providers);
     *providers = Providers {
         typeck_item_bodies,
         typeck_tables_of,
@@ -1127,10 +1128,10 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Check that the main return type implements the termination trait.
     if let Some(term_id) = fcx.tcx.lang_items().termination() {
-        if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+        if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
             if id == fn_id {
-                match fcx.sess().entry_type.get() {
-                    Some(config::EntryMain) => {
+                match entry_type {
+                    config::EntryMain => {
                         let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
                         let trait_ref = ty::TraitRef::new(term_id, substs);
                         let return_ty_span = decl.output.span();
@@ -1141,7 +1142,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                             traits::Obligation::new(
                                 cause, param_env, trait_ref.to_predicate()));
                     },
-                    _ => {},
+                    config::EntryStart => {},
                 }
             }
         }
@@ -1553,8 +1554,19 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
 }
 
 fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
-    if tcx.adt_def(def_id).repr.packed() {
-        if tcx.adt_def(def_id).repr.align > 0 {
+    let repr = tcx.adt_def(def_id).repr;
+    if repr.packed() {
+        for attr in tcx.get_attrs(def_id).iter() {
+            for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
+                if let attr::ReprPacked(pack) = r {
+                    if pack != repr.pack {
+                        struct_span_err!(tcx.sess, sp, E0634,
+                                         "type has conflicting packed representation hints").emit();
+                    }
+                }
+            }
+        }
+        if repr.align > 0 {
             struct_span_err!(tcx.sess, sp, E0587,
                              "type has conflicting packed and align representation hints").emit();
         }
@@ -1926,6 +1938,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn write_field_index(&self, node_id: ast::NodeId, index: usize) {
+        let hir_id = self.tcx.hir.node_to_hir_id(node_id);
+        self.tables.borrow_mut().field_indices_mut().insert(hir_id, index);
+    }
+
     // The NodeId and the ItemLocalId must identify the same item. We just pass
     // both of them for consistency checking.
     pub fn write_method_call(&self,
@@ -2254,7 +2271,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
             hir::ExprUnary(hir::UnDeref, _) |
             hir::ExprField(..) |
-            hir::ExprTupField(..) |
             hir::ExprIndex(..) => {
                 true
             }
@@ -3058,20 +3074,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     let (ident, def_scope) =
                         self.tcx.adjust(field.node, base_def.did, self.body_id);
                     let fields = &base_def.non_enum_variant().fields;
-                    if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
+                    if let Some(index) = fields.iter().position(|f| f.name.to_ident() == ident) {
+                        let field = &fields[index];
                         let field_ty = self.field_ty(expr.span, field, substs);
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
                             let adjustments = autoderef.adjust_steps(needs);
                             self.apply_adjustments(base, adjustments);
                             autoderef.finalize();
 
+                            self.write_field_index(expr.id, index);
                             self.tcx.check_stability(field.did, Some(expr.id), expr.span);
-
                             return field_ty;
                         }
                         private_candidate = Some((base_def.did, field_ty));
                     }
                 }
+                ty::TyTuple(ref tys) => {
+                    let fstr = field.node.as_str();
+                    if let Ok(index) = fstr.parse::<usize>() {
+                        if fstr == index.to_string() {
+                            if let Some(field_ty) = tys.get(index) {
+                                let adjustments = autoderef.adjust_steps(needs);
+                                self.apply_adjustments(base, adjustments);
+                                autoderef.finalize();
+
+                                self.write_field_index(expr.id, index);
+                                return field_ty;
+                            }
+                        }
+                    }
+                }
                 _ => {}
             }
         }
@@ -3177,78 +3209,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         display
     }
 
-    // Check tuple index expressions
-    fn check_tup_field(&self,
-                       expr: &'gcx hir::Expr,
-                       needs: Needs,
-                       base: &'gcx hir::Expr,
-                       idx: codemap::Spanned<usize>) -> Ty<'tcx> {
-        let expr_t = self.check_expr_with_needs(base, needs);
-        let expr_t = self.structurally_resolved_type(expr.span,
-                                                     expr_t);
-        let mut private_candidate = None;
-        let mut tuple_like = false;
-        let mut autoderef = self.autoderef(expr.span, expr_t);
-        while let Some((base_t, _)) = autoderef.next() {
-            let field = match base_t.sty {
-                ty::TyAdt(base_def, substs) if base_def.is_struct() => {
-                    tuple_like = base_def.non_enum_variant().ctor_kind == CtorKind::Fn;
-                    if !tuple_like { continue }
-
-                    debug!("tuple struct named {:?}",  base_t);
-                    let ident =
-                        ast::Ident::new(Symbol::intern(&idx.node.to_string()), idx.span.modern());
-                    let (ident, def_scope) =
-                        self.tcx.adjust_ident(ident, base_def.did, self.body_id);
-                    let fields = &base_def.non_enum_variant().fields;
-                    if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
-                        let field_ty = self.field_ty(expr.span, field, substs);
-                        if field.vis.is_accessible_from(def_scope, self.tcx) {
-                            self.tcx.check_stability(field.did, Some(expr.id), expr.span);
-                            Some(field_ty)
-                        } else {
-                            private_candidate = Some((base_def.did, field_ty));
-                            None
-                        }
-                    } else {
-                        None
-                    }
-                }
-                ty::TyTuple(ref v) => {
-                    tuple_like = true;
-                    v.get(idx.node).cloned()
-                }
-                _ => continue
-            };
-
-            if let Some(field_ty) = field {
-                let adjustments = autoderef.adjust_steps(needs);
-                self.apply_adjustments(base, adjustments);
-                autoderef.finalize();
-                return field_ty;
-            }
-        }
-        autoderef.unambiguous_final_ty();
-
-        if let Some((did, field_ty)) = private_candidate {
-            let struct_path = self.tcx().item_path_str(did);
-            struct_span_err!(self.tcx().sess, expr.span, E0611,
-                             "field `{}` of tuple-struct `{}` is private",
-                             idx.node, struct_path).emit();
-            return field_ty;
-        }
-
-        if tuple_like {
-            type_error_struct!(self.tcx().sess, expr.span, expr_t, E0612,
-                "attempted out-of-bounds tuple index `{}` on type `{}`",
-                idx.node, expr_t).emit();
-        } else {
-            self.no_such_field_err(expr.span, idx.node, expr_t).emit();
-        }
-
-        self.tcx().types.err
-    }
-
     fn no_such_field_err<T: Display>(&self, span: Span, field: T, expr_t: &ty::TyS)
         -> DiagnosticBuilder {
         type_error_struct!(self.tcx().sess, span, expr_t, E0609,
@@ -3331,8 +3291,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         };
 
         let mut remaining_fields = FxHashMap();
-        for field in &variant.fields {
-            remaining_fields.insert(field.name.to_ident(), field);
+        for (i, field) in variant.fields.iter().enumerate() {
+            remaining_fields.insert(field.name.to_ident(), (i, field));
         }
 
         let mut seen_fields = FxHashMap();
@@ -3342,8 +3302,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Typecheck each field.
         for field in ast_fields {
             let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0;
-            let field_type = if let Some(v_field) = remaining_fields.remove(&ident) {
-                seen_fields.insert(field.name.node, field.span);
+            let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
+                seen_fields.insert(ident, field.span);
+                self.write_field_index(field.id, i);
 
                 // we don't look at stability attributes on
                 // struct-like enums (yet...), but it's definitely not
@@ -3355,18 +3316,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.field_ty(field.span, v_field, substs)
             } else {
                 error_happened = true;
-                if let Some(_) = variant.find_field_named(field.name.node) {
+                if let Some(prev_span) = seen_fields.get(&ident) {
                     let mut err = struct_span_err!(self.tcx.sess,
                                                 field.name.span,
                                                 E0062,
                                                 "field `{}` specified more than once",
-                                                field.name.node);
+                                                ident);
 
                     err.span_label(field.name.span, "used more than once");
-
-                    if let Some(prev_span) = seen_fields.get(&field.name.node) {
-                        err.span_label(*prev_span, format!("first use of `{}`", field.name.node));
-                    }
+                    err.span_label(*prev_span, format!("first use of `{}`", ident));
 
                     err.emit();
                 } else {
@@ -4109,9 +4067,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
           hir::ExprField(ref base, ref field) => {
             self.check_field(expr, needs, &base, field)
           }
-          hir::ExprTupField(ref base, idx) => {
-            self.check_tup_field(expr, needs, &base, idx)
-          }
           hir::ExprIndex(ref base, ref idx) => {
               let base_t = self.check_expr_with_needs(&base, needs);
               let idx_t = self.check_expr(&idx);
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 7dc73a1d5f0..6348f386177 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[..]);
         }
     }
 }
@@ -759,7 +759,7 @@ fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast:
     err
 }
 
-fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: ast::Name) {
+fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: &str) {
     struct_span_err!(tcx.sess, span, E0194,
               "type parameter `{}` shadows another type parameter of the same name",
               name)
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index bbd04e0b19a..6e0d7dd8508 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -226,13 +226,24 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
 
         self.visit_node_id(e.span, e.hir_id);
 
-        if let hir::ExprClosure(_, _, body, _, _) = e.node {
-            let body = self.fcx.tcx.hir.body(body);
-            for arg in &body.arguments {
-                self.visit_node_id(e.span, arg.hir_id);
-            }
+        match e.node {
+            hir::ExprClosure(_, _, body, _, _) => {
+                let body = self.fcx.tcx.hir.body(body);
+                for arg in &body.arguments {
+                    self.visit_node_id(e.span, arg.hir_id);
+                }
 
-            self.visit_body(body);
+                self.visit_body(body);
+            }
+            hir::ExprStruct(_, ref fields, _) => {
+                for field in fields {
+                    self.visit_field_id(field.id);
+                }
+            }
+            hir::ExprField(..) => {
+                self.visit_field_id(e.id);
+            }
+            _ => {}
         }
 
         intravisit::walk_expr(self, e);
@@ -254,6 +265,11 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
                     .expect("missing binding mode");
                 self.tables.pat_binding_modes_mut().insert(p.hir_id, bm);
             }
+            hir::PatKind::Struct(_, ref fields, _) => {
+                for field in fields {
+                    self.visit_field_id(field.node.id);
+                }
+            }
             _ => {}
         };
 
@@ -384,6 +400,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         }
     }
 
+    fn visit_field_id(&mut self, node_id: ast::NodeId) {
+        let hir_id = self.tcx().hir.node_to_hir_id(node_id);
+        if let Some(index) = self.fcx.tables.borrow_mut().field_indices_mut().remove(hir_id) {
+            self.tables.field_indices_mut().insert(hir_id, index);
+        }
+    }
+
     fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) {
         // Export associated path extensions and method resultions.
         if let Some(def) = self.fcx
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 59156bf0dfe..3939c3a0627 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
         type_of,
         generics_of,
         predicates_of,
+        explicit_predicates_of,
         super_predicates_of,
         type_param_predicates,
         trait_def,
@@ -241,7 +242,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));
+    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_str());
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -513,11 +514,11 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     discr: ty::VariantDiscr,
                                     def: &hir::VariantData)
                                     -> ty::VariantDef {
-    let mut seen_fields: FxHashMap<ast::Name, Span> = FxHashMap();
+    let mut seen_fields: FxHashMap<ast::Ident, Span> = FxHashMap();
     let node_id = tcx.hir.as_local_node_id(did).unwrap();
     let fields = def.fields().iter().map(|f| {
         let fid = tcx.hir.local_def_id(f.id);
-        let dup_span = seen_fields.get(&f.name).cloned();
+        let dup_span = seen_fields.get(&f.name.to_ident()).cloned();
         if let Some(prev_span) = dup_span {
             struct_span_err!(tcx.sess, f.span, E0124,
                              "field `{}` is already declared",
@@ -526,7 +527,7 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 .span_label(prev_span, format!("`{}` first declared here", f.name))
                 .emit();
         } else {
-            seen_fields.insert(f.name, f.span);
+            seen_fields.insert(f.name.to_ident(), f.span);
         }
 
         ty::FieldDef {
@@ -839,7 +840,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     opt_self = Some(ty::TypeParameterDef {
                         index: 0,
-                        name: keywords::SelfType.name(),
+                        name: keywords::SelfType.name().as_str(),
                         def_id: tcx.hir.local_def_id(param_id),
                         has_default: false,
                         object_lifetime_default: rl::Set1::Empty,
@@ -915,7 +916,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         ty::TypeParameterDef {
             index: type_start + i as u32,
-            name: p.name,
+            name: p.name.as_str(),
             def_id: tcx.hir.local_def_id(p.id),
             has_default: p.default.is_some(),
             object_lifetime_default:
@@ -934,7 +935,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>"),
+            name: Symbol::intern("<closure_kind>").as_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -945,7 +946,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>"),
+            name: Symbol::intern("<closure_signature>").as_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -956,7 +957,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>"),
+                name: Symbol::intern("<upvar>").as_str(),
                 def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
@@ -1296,13 +1297,17 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            def_id: DefId)
                            -> ty::GenericPredicates<'tcx> {
     let explicit = explicit_predicates_of(tcx, def_id);
+    let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
+        [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
+    } else { explicit.predicates };
+
     ty::GenericPredicates {
         parent: explicit.parent,
-        predicates: [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
+        predicates: predicates,
     }
 }
 
-fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            def_id: DefId)
                            -> ty::GenericPredicates<'tcx> {
     use rustc::hir::map::*;
@@ -1436,7 +1441,7 @@ 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).to_ty(tcx);
+        let param_ty = ty::ParamTy::new(index, param.name.as_str()).to_ty(tcx);
         index += 1;
 
         let bounds = compute_bounds(&icx,
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 79d7c8e7282..ae3b2b22ea1 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4138,86 +4138,6 @@ https://doc.rust-lang.org/book/first-edition/primitive-types.html
 https://doc.rust-lang.org/book/first-edition/structs.html
 "##,
 
-E0611: r##"
-Attempted to access a private field on a tuple-struct.
-
-Erroneous code example:
-
-```compile_fail,E0611
-mod some_module {
-    pub struct Foo(u32);
-
-    impl Foo {
-        pub fn new() -> Foo { Foo(0) }
-    }
-}
-
-let y = some_module::Foo::new();
-println!("{}", y.0); // error: field `0` of tuple-struct `some_module::Foo`
-                     //        is private
-```
-
-Since the field is private, you have two solutions:
-
-1) Make the field public:
-
-```
-mod some_module {
-    pub struct Foo(pub u32); // The field is now public.
-
-    impl Foo {
-        pub fn new() -> Foo { Foo(0) }
-    }
-}
-
-let y = some_module::Foo::new();
-println!("{}", y.0); // So we can access it directly.
-```
-
-2) Add a getter function to keep the field private but allow for accessing its
-value:
-
-```
-mod some_module {
-    pub struct Foo(u32);
-
-    impl Foo {
-        pub fn new() -> Foo { Foo(0) }
-
-        // We add the getter function.
-        pub fn get(&self) -> &u32 { &self.0 }
-    }
-}
-
-let y = some_module::Foo::new();
-println!("{}", y.get()); // So we can get the value through the function.
-```
-"##,
-
-E0612: r##"
-Attempted out-of-bounds tuple index.
-
-Erroneous code example:
-
-```compile_fail,E0612
-struct Foo(u32);
-
-let y = Foo(0);
-println!("{}", y.1); // error: attempted out-of-bounds tuple index `1`
-                     //        on type `Foo`
-```
-
-If a tuple/tuple-struct type has n fields, you can only try to access these n
-fields from 0 to (n - 1). So in this case, you can only index `0`. Example:
-
-```
-struct Foo(u32);
-
-let y = Foo(0);
-println!("{}", y.0); // ok!
-```
-"##,
-
 E0614: r##"
 Attempted to dereference a variable which cannot be dereferenced.
 
@@ -4836,14 +4756,17 @@ register_diagnostics! {
 //  E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
     E0564, // only named lifetimes are allowed in `impl Trait`,
            // but `{}` was found in the type `{}`
-    E0587, // struct has conflicting packed and align representation hints
-    E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
+    E0587, // type has conflicting packed and align representation hints
+    E0588, // packed type cannot transitively contain a `[repr(align)]` type
     E0592, // duplicate definitions with name `{}`
+//  E0611, // merged into E0616
+//  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
-    E0640, // infer outlives
     E0627, // yield statement outside of generator literal
     E0632, // cannot provide explicit type parameters when `impl Trait` is used in
            // argument position.
+    E0634, // type has conflicting packed representaton hints
+    E0640, // infer outlives requirements
     E0641, // cannot cast to/from a pointer with an unknown kind
     E0645, // trait aliases not finished
     E0907, // type inside generator must be known in this context
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 6f71db998bd..a4477e80b98 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -68,7 +68,6 @@ 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/")]
-#![deny(warnings)]
 
 #![allow(non_camel_case_types)]
 
@@ -77,12 +76,13 @@ This API is completely unstable and subject to change.
 #![feature(crate_visibility_modifier)]
 #![feature(from_ref)]
 #![feature(exhaustive_patterns)]
-#![feature(option_filter)]
 #![feature(quote)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(dyn_trait)]
+#![feature(underscore_lifetimes)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -289,12 +289,10 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    if let Some((id, sp)) = *tcx.sess.entry_fn.borrow() {
-        match tcx.sess.entry_type.get() {
-            Some(config::EntryMain) => check_main_fn_ty(tcx, id, sp),
-            Some(config::EntryStart) => check_start_fn_ty(tcx, id, sp),
-            Some(config::EntryNone) => {}
-            None => bug!("entry function without a type")
+    if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
+        match entry_type {
+            config::EntryMain => check_main_fn_ty(tcx, id, sp),
+            config::EntryStart => check_start_fn_ty(tcx, id, sp),
         }
     }
 }
diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs
new file mode 100644
index 00000000000..9a8fd46b0ef
--- /dev/null
+++ b/src/librustc_typeck/outlives/explicit.rs
@@ -0,0 +1,82 @@
+// Copyright 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.
+
+use hir::map as hir_map;
+use rustc::hir;
+use rustc::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::ty::maps::Providers;
+use rustc::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_data_structures::sync::Lrc;
+use util::nodemap::FxHashMap;
+
+pub fn explicit_predicates<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    crate_num: CrateNum,
+) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    let mut predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> = FxHashMap();
+
+    // iterate over the entire crate
+    tcx.hir.krate().visit_all_item_likes(&mut ExplicitVisitor {
+        tcx: tcx,
+        explicit_predicates: &mut predicates,
+        crate_num: crate_num,
+    });
+
+    predicates
+}
+
+pub struct ExplicitVisitor<'cx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
+    explicit_predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+    crate_num: CrateNum,
+}
+
+impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        let def_id = DefId {
+            krate: self.crate_num,
+            index: item.hir_id.owner,
+        };
+
+        let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);
+
+        let filtered_predicates = local_explicit_predicate
+            .predicates
+            .into_iter()
+            .filter(|pred| match pred {
+                ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => true,
+
+                ty::Predicate::Trait(..)
+                | ty::Predicate::Projection(..)
+                | ty::Predicate::WellFormed(..)
+                | ty::Predicate::ObjectSafe(..)
+                | ty::Predicate::ClosureKind(..)
+                | ty::Predicate::Subtype(..)
+                | ty::Predicate::ConstEvaluatable(..) => false,
+            })
+            .collect();
+
+        match item.node {
+            hir::ItemStruct(..) | hir::ItemEnum(..) => {
+                self.tcx.adt_def(def_id);
+            }
+            _ => {}
+        }
+
+        self.explicit_predicates
+            .insert(def_id, Lrc::new(filtered_predicates));
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
+
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
+}
diff --git a/src/librustc_typeck/outlives/implicit_empty.rs b/src/librustc_typeck/outlives/implicit_empty.rs
new file mode 100644
index 00000000000..b2259c63683
--- /dev/null
+++ b/src/librustc_typeck/outlives/implicit_empty.rs
@@ -0,0 +1,52 @@
+// Copyright 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.
+
+use hir::map as hir_map;
+use rustc::hir;
+use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::ty::maps::Providers;
+use rustc::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_data_structures::sync::Lrc;
+use util::nodemap::FxHashMap;
+
+// Create the sets of inferred predicates for each type. These sets
+// are initially empty but will grow during the inference step.
+pub fn empty_predicate_map<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
+    let mut predicates = FxHashMap();
+
+    // iterate over the entire crate
+    tcx.hir
+        .krate()
+        .visit_all_item_likes(&mut EmptyImplicitVisitor {
+            tcx,
+            predicates: &mut predicates,
+        });
+
+    predicates
+}
+
+pub struct EmptyImplicitVisitor<'cx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
+    predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+}
+
+impl<'a, 'p, 'v> ItemLikeVisitor<'v> for EmptyImplicitVisitor<'a, 'p> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        self.predicates
+            .insert(self.tcx.hir.local_def_id(item.id), Lrc::new(Vec::new()));
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {}
+
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {}
+}
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
new file mode 100644
index 00000000000..ac53a6d4a3f
--- /dev/null
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -0,0 +1,442 @@
+// Copyright 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.
+
+#![allow(unused)]
+
+use rustc::hir;
+use rustc::hir::def::{CtorKind, Def};
+use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::map as hir_map;
+use rustc::ty::Slice;
+use rustc::ty::maps::Providers;
+use rustc::ty::outlives::Component;
+use rustc::ty::subst::{Kind, Subst, UnpackedKind};
+use rustc::ty::{self, AdtKind, CratePredicatesMap, Region, RegionKind, ReprOptions,
+                ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc_data_structures::sync::Lrc;
+use syntax::{abi, ast};
+use syntax_pos::{Span, DUMMY_SP};
+
+/// Infer predicates for the items in the crate.
+///
+/// global_inferred_outlives: this is initially the empty map that
+///     was generated by walking the items in the crate. This will
+///     now be filled with inferred predicates.
+pub fn infer_predicates<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
+    debug!("infer_predicates");
+
+    let mut predicates_added = true;
+
+    let mut global_inferred_outlives = FxHashMap::default();
+
+    // If new predicates were added then we need to re-calculate
+    // all crates since there could be new implied predicates.
+    while predicates_added {
+        predicates_added = false;
+
+        let mut visitor = InferVisitor {
+            tcx: tcx,
+            global_inferred_outlives: &mut global_inferred_outlives,
+            predicates_added: &mut predicates_added,
+            explicit_map: explicit_map,
+        };
+
+        // Visit all the crates and infer predicates
+        tcx.hir.krate().visit_all_item_likes(&mut visitor);
+    }
+
+    global_inferred_outlives
+}
+
+pub struct InferVisitor<'cx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
+    global_inferred_outlives: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
+    predicates_added: &'cx mut bool,
+    explicit_map: &'cx FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+}
+
+/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
+/// must be added to the struct header.
+type RequiredPredicates<'tcx> = FxHashSet<ty::OutlivesPredicate<Kind<'tcx>, ty::Region<'tcx>>>;
+
+impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        let item_did = self.tcx.hir.local_def_id(item.id);
+
+        debug!("InferVisitor::visit_item(item={:?})", item_did);
+
+        let node_id = self.tcx
+            .hir
+            .as_local_node_id(item_did)
+            .expect("expected local def-id");
+        let item = match self.tcx.hir.get(node_id) {
+            hir::map::NodeItem(item) => item,
+            _ => bug!(),
+        };
+
+        let mut item_required_predicates = RequiredPredicates::default();
+        match item.node {
+            hir::ItemUnion(..) | hir::ItemEnum(..) | hir::ItemStruct(..) => {
+                let adt_def = self.tcx.adt_def(item_did);
+
+                // Iterate over all fields in item_did
+                for field_def in adt_def.all_fields() {
+                    // Calculating the predicate requirements necessary
+                    // for item_did.
+                    //
+                    // For field of type &'a T (reference) or TyAdt
+                    // (struct/enum/union) there will be outlive
+                    // requirements for adt_def.
+                    let field_ty = self.tcx.type_of(field_def.did);
+                    insert_required_predicates_to_be_wf(
+                        self.tcx,
+                        field_ty,
+                        self.global_inferred_outlives,
+                        &mut item_required_predicates,
+                        self.explicit_map,
+                    );
+                }
+            }
+
+            _ => {}
+        };
+
+        // If new predicates were added (`local_predicate_map` has more
+        // predicates than the `global_inferred_outlives`), the new predicates
+        // might result in implied predicates for their parent types.
+        // Therefore mark `predicates_added` as true and which will ensure
+        // we walk the crates again and re-calculate predicates for all
+        // items.
+        let item_predicates_len: usize = self.global_inferred_outlives
+            .get(&item_did)
+            .map(|p| p.len())
+            .unwrap_or(0);
+        if item_required_predicates.len() > item_predicates_len {
+            *self.predicates_added = true;
+            self.global_inferred_outlives
+                .insert(item_did, item_required_predicates);
+        }
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
+
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
+}
+
+fn insert_required_predicates_to_be_wf<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    field_ty: Ty<'tcx>,
+    global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
+    required_predicates: &mut RequiredPredicates<'tcx>,
+    explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+) {
+    for ty in field_ty.walk() {
+        match ty.sty {
+            // The field is of type &'a T which means that we will have
+            // a predicate requirement of T: 'a (T outlives 'a).
+            //
+            // We also want to calculate potential predicates for the T
+            ty::TyRef(region, mt) => {
+                insert_outlives_predicate(tcx, mt.ty.into(), region, required_predicates);
+            }
+
+            // For each TyAdt (struct/enum/union) type `Foo<'a, T>`, we
+            // can load the current set of inferred and explicit
+            // predicates from `global_inferred_outlives` and filter the
+            // ones that are TypeOutlives.
+            //
+            ty::TyAdt(def, substs) => {
+                // First check the inferred predicates
+                //
+                // Example 1:
+                //
+                //     struct Foo<'a, T> {
+                //         field1: Bar<'a, T>
+                //     }
+                //
+                //     struct Bar<'b, U> {
+                //         field2: &'b U
+                //     }
+                //
+                // Here, when processing the type of `field1`, we would
+                // request the set of implicit predicates computed for `Bar`
+                // thus far. This will initially come back empty, but in next
+                // round we will get `U: 'b`. We then apply the substitution
+                // `['b => 'a, U => T]` and thus get the requirement that `T:
+                // 'a` holds for `Foo`.
+                if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
+                    for unsubstituted_predicate in unsubstituted_predicates {
+                        // `unsubstituted_predicate` is `U: 'b` in the
+                        // example above.  So apply the substitution to
+                        // get `T: 'a` (or `predicate`):
+                        let predicate = unsubstituted_predicate.subst(tcx, substs);
+                        insert_outlives_predicate(
+                            tcx,
+                            predicate.0,
+                            predicate.1,
+                            required_predicates,
+                        );
+                    }
+                }
+
+                // Check if the type has any explicit predicates that need
+                // to be added to `required_predicates`
+                // let _: () = substs.region_at(0);
+                check_explicit_predicates(tcx, &def.did, substs, required_predicates, explicit_map);
+            }
+
+            ty::TyDynamic(obj, region) => {
+                // FIXME This corresponds to `dyn Trait<..>`. In this
+                // case, we should use the explicit predicates as
+                // well.
+                if let Some(p) = obj.principal() {
+                    check_explicit_predicates(
+                        tcx,
+                        &p.skip_binder().def_id,
+                        &[region.into()],
+                        required_predicates,
+                        explicit_map,
+                    );
+                }
+            }
+
+            ty::TyProjection(obj) => {
+                // FIXME This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
+                // explicit predicates as well.
+                check_explicit_predicates(
+                    tcx,
+                    &obj.item_def_id,
+                    obj.substs,
+                    required_predicates,
+                    explicit_map,
+                );
+            }
+
+            _ => {}
+        }
+    }
+}
+
+/// We also have to check the explicit predicates
+/// declared on the type.
+///
+///     struct Foo<'a, T> {
+///         field1: Bar<T>
+///     }
+///
+///     struct Bar<U> where U: 'static, U: Foo {
+///         ...
+///     }
+///
+/// Here, we should fetch the explicit predicates, which
+/// will give us `U: 'static` and `U: Foo`. The latter we
+/// can ignore, but we will want to process `U: 'static`,
+/// applying the substitution as above.
+fn check_explicit_predicates<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    def_id: &DefId,
+    substs: &[Kind<'tcx>],
+    required_predicates: &mut RequiredPredicates<'tcx>,
+    explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
+) {
+    if let Some(general_predicates) = explicit_map.get(def_id) {
+        for general_predicate in general_predicates.iter() {
+            match general_predicate {
+                // `poly` is `PolyTypeOutlivesPredicate<OutlivesPredicate<Ty>>`
+                // where OutlivesPredicate<type1, region1> is the predicate
+                // we want to add.
+                ty::Predicate::TypeOutlives(poly) => {
+                    let predicate = poly.0.subst(tcx, substs);
+                    insert_outlives_predicate(
+                        tcx,
+                        predicate.0.into(),
+                        predicate.1,
+                        required_predicates,
+                    );
+                }
+
+                // `poly` is `PolyRegionOutlivesPredicate<OutlivesPredicate<Ty>>`
+                // where OutlivesPredicate<region1, region2> is the predicate
+                // we want to add.
+                ty::Predicate::RegionOutlives(poly) => {
+                    let predicate = poly.0.subst(tcx, substs);
+                    insert_outlives_predicate(
+                        tcx,
+                        predicate.0.into(),
+                        predicate.1,
+                        required_predicates,
+                    );
+                }
+
+                ty::Predicate::Trait(..)
+                | ty::Predicate::Projection(..)
+                | ty::Predicate::WellFormed(..)
+                | ty::Predicate::ObjectSafe(..)
+                | ty::Predicate::ClosureKind(..)
+                | ty::Predicate::Subtype(..)
+                | ty::Predicate::ConstEvaluatable(..) => (),
+            }
+        }
+    }
+}
+
+/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
+/// outlives_component and add it to `required_predicates`
+fn insert_outlives_predicate<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    kind: Kind<'tcx>,
+    outlived_region: Region<'tcx>,
+    required_predicates: &mut RequiredPredicates<'tcx>,
+) {
+    // If the `'a` region is bound within the field type itself, we
+    // don't want to propagate this constraint to the header.
+    if !is_free_region(outlived_region) {
+        return;
+    }
+
+    match kind.unpack() {
+        UnpackedKind::Type(ty) => {
+            // `T: 'outlived_region` for some type `T`
+            // But T could be a lot of things:
+            // e.g., if `T = &'b u32`, then `'b: 'outlived_region` is
+            // what we want to add.
+            //
+            // Or if within `struct Foo<U>` you had `T = Vec<U>`, then
+            // we would want to add `U: 'outlived_region`
+            for component in tcx.outlives_components(ty) {
+                match component {
+                    Component::Region(r) => {
+                        // This would arise from something like:
+                        //
+                        // ```
+                        // struct Foo<'a, 'b> {
+                        //    x:  &'a &'b u32
+                        // }
+                        // ```
+                        //
+                        // Here `outlived_region = 'a` and `kind = &'b
+                        // u32`.  Decomposing `&'b u32` into
+                        // components would yield `'b`, and we add the
+                        // where clause that `'b: 'a`.
+                        insert_outlives_predicate(
+                            tcx,
+                            r.into(),
+                            outlived_region,
+                            required_predicates,
+                        );
+                    }
+
+                    Component::Param(param_ty) => {
+                        // param_ty: ty::ParamTy
+                        // This would arise from something like:
+                        //
+                        // ```
+                        // struct Foo<'a, U> {
+                        //    x:  &'a Vec<U>
+                        // }
+                        // ```
+                        //
+                        // Here `outlived_region = 'a` and `kind =
+                        // Vec<U>`.  Decomposing `Vec<U>` into
+                        // components would yield `U`, and we add the
+                        // where clause that `U: 'a`.
+                        let ty: Ty<'tcx> = tcx.mk_param(param_ty.idx, param_ty.name);
+                        required_predicates
+                            .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
+                    }
+
+                    Component::Projection(proj_ty) => {
+                        // This would arise from something like:
+                        //
+                        // ```
+                        // struct Foo<'a, T: Iterator> {
+                        //    x:  &'a <T as Iterator>::Item
+                        // }
+                        // ```
+                        //
+                        // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
+                        let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
+                        required_predicates
+                            .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
+                    }
+
+                    Component::EscapingProjection(_) => {
+                        // As above, but the projection involves
+                        // late-bound regions.  Therefore, the WF
+                        // requirement is not checked in type definition
+                        // but at fn call site, so ignore it.
+                        //
+                        // ```
+                        // struct Foo<'a, T: Iterator> {
+                        //    x: for<'b> fn(<&'b T as Iterator>::Item)
+                        //              //  ^^^^^^^^^^^^^^^^^^^^^^^^^
+                        // }
+                        // ```
+                        //
+                        // Since `'b` is not in scope on `Foo`, can't
+                        // do anything here, ignore it.
+                    }
+
+                    Component::UnresolvedInferenceVariable(_) => bug!("not using infcx"),
+                }
+            }
+        }
+
+        UnpackedKind::Lifetime(r) => {
+            if !is_free_region(r) {
+                return;
+            }
+            required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
+        }
+    }
+}
+
+fn is_free_region(region: Region<'_>) -> bool {
+    // First, screen for regions that might appear in a type header.
+    match region {
+        // *These* correspond to `T: 'a` relationships where `'a` is
+        // either declared on the type or `'static`:
+        //
+        //     struct Foo<'a, T> {
+        //         field: &'a T, // this would generate a ReEarlyBound referencing `'a`
+        //         field2: &'static T, // this would generate a ReStatic
+        //     }
+        //
+        // We care about these, so fall through.
+        RegionKind::ReStatic | RegionKind::ReEarlyBound(_) => true,
+
+        // Late-bound regions can appear in `fn` types:
+        //
+        //     struct Foo<T> {
+        //         field: for<'b> fn(&'b T) // e.g., 'b here
+        //     }
+        //
+        // The type above might generate a `T: 'b` bound, but we can
+        // ignore it.  We can't put it on the struct header anyway.
+        RegionKind::ReLateBound(..) => false,
+
+        // These regions don't appear in types from type declarations:
+        RegionKind::ReEmpty
+        | RegionKind::ReErased
+        | RegionKind::ReClosureBound(..)
+        | RegionKind::ReCanonical(..)
+        | RegionKind::ReScope(..)
+        | RegionKind::ReVar(..)
+        | RegionKind::ReSkolemized(..)
+        | RegionKind::ReFree(..) => {
+            bug!("unexpected region in outlives inference: {:?}", region);
+        }
+    }
+}
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
index 1127028cbc8..bad0c68a6fe 100644
--- a/src/librustc_typeck/outlives/mod.rs
+++ b/src/librustc_typeck/outlives/mod.rs
@@ -7,23 +7,105 @@
 // <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::hir::def_id::DefId;
-use rustc::ty::{self, TyCtxt};
+#![allow(unused)]
+#[allow(dead_code)]
+use hir::map as hir_map;
+use rustc::dep_graph::DepKind;
+use rustc::hir;
+use rustc::hir::Ty_::*;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::ty::maps::Providers;
+use rustc::ty::subst::UnpackedKind;
+use rustc::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_data_structures::sync::Lrc;
+use util::nodemap::FxHashMap;
 
+mod explicit;
+mod implicit_empty;
+mod implicit_infer;
 /// Code to write unit test for outlives.
 pub mod test;
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         inferred_outlives_of,
+        inferred_outlives_crate,
         ..*providers
     };
 }
 
-//todo
-fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, _def_id: DefId)
-                                  -> Vec<ty::Predicate<'tcx>> {
-    Vec::new()
+fn inferred_outlives_of<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    item_def_id: DefId,
+) -> Lrc<Vec<ty::Predicate<'tcx>>> {
+    let id = tcx.hir
+        .as_local_node_id(item_def_id)
+        .expect("expected local def-id");
+
+    match tcx.hir.get(id) {
+        hir_map::NodeItem(item) => match item.node {
+            hir::ItemStruct(..) | hir::ItemEnum(..) | hir::ItemUnion(..) => {
+                let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
+                let dep_node = item_def_id.to_dep_node(tcx, DepKind::InferredOutlivesOf);
+                tcx.dep_graph.read(dep_node);
+
+                crate_map
+                    .predicates
+                    .get(&item_def_id)
+                    .unwrap_or(&crate_map.empty_predicate)
+                    .clone()
+            }
+
+            _ => Lrc::new(Vec::new()),
+        },
+
+        _ => Lrc::new(Vec::new()),
+    }
+}
+
+fn inferred_outlives_crate<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    crate_num: CrateNum,
+) -> Lrc<CratePredicatesMap<'tcx>> {
+    // Compute a map from each struct/enum/union S to the **explicit**
+    // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
+    // Typically there won't be many of these, except in older code where
+    // they were mandatory. Nonetheless, we have to ensure that every such
+    // predicate is satisfied, so they form a kind of base set of requirements
+    // for the type.
+
+    // Compute the inferred predicates
+    let exp = explicit::explicit_predicates(tcx, crate_num);
+    let mut global_inferred_outlives = implicit_infer::infer_predicates(tcx, &exp);
+
+    // Convert the inferred predicates into the "collected" form the
+    // global data structure expects.
+    //
+    // FIXME -- consider correcting impedance mismatch in some way,
+    // probably by updating the global data structure.
+    let mut predicates = global_inferred_outlives
+        .iter()
+        .map(|(&def_id, set)| {
+            let vec: Vec<ty::Predicate<'tcx>> = set.iter()
+                .map(
+                    |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
+                        UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder(
+                            ty::OutlivesPredicate(ty1, region2),
+                        )),
+                        UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives(
+                            ty::Binder(ty::OutlivesPredicate(region1, region2)),
+                        ),
+                    },
+                )
+                .collect();
+            (def_id, Lrc::new(vec))
+        })
+        .collect();
+
+    let empty_predicate = Lrc::new(Vec::new());
+
+    Lrc::new(ty::CratePredicatesMap {
+        predicates,
+        empty_predicate,
+    })
 }
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index 196e6605494..c3c2ae667dd 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -13,11 +13,13 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::TyCtxt;
 
 pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.hir.krate().visit_all_item_likes(&mut OutlivesTest { tcx });
+    tcx.hir
+        .krate()
+        .visit_all_item_likes(&mut OutlivesTest { tcx });
 }
 
 struct OutlivesTest<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> {
@@ -28,14 +30,16 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> {
         // attribute and report an error with various results if found.
         if self.tcx.has_attr(item_def_id, "rustc_outlives") {
             let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
-            span_err!(self.tcx.sess,
-                      item.span,
-                      E0640,
-                      "{:?}",
-                      inferred_outlives_of);
+            span_err!(
+                self.tcx.sess,
+                item.span,
+                E0640,
+                "{:?}",
+                inferred_outlives_of
+            );
         }
     }
 
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { }
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
 }
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index a87e1df5efc..888148352c7 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -260,7 +260,9 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
                 P(hir::Path {
                     span: DUMMY_SP,
                     def: Def::TyParam(param.def_id),
-                    segments: HirVec::from_vec(vec![hir::PathSegment::from_name(param.name)]),
+                    segments: HirVec::from_vec(vec![
+                        hir::PathSegment::from_name(Symbol::intern(&param.name))
+                    ]),
                 }),
             )),
             span: DUMMY_SP,
@@ -1435,9 +1437,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
     // involved (impls rarely have more than a few bounds) means that it
     // shouldn't matter in practice.
     fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) {
-        vec.sort_unstable_by(|first, second| {
-            format!("{:?}", first).cmp(&format!("{:?}", second))
-        });
+        vec.sort_by_cached_key(|x| format!("{:?}", x))
     }
 
     fn is_fn_ty(&self, tcx: &TyCtxt, ty: &Type) -> bool {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b57c9589afa..da8085d84c3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -27,7 +27,7 @@ use syntax::codemap::{dummy_spanned, Spanned};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::ptr::P;
 use syntax::symbol::keywords;
-use syntax::symbol::Symbol;
+use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
 use rustc::middle::const_val::ConstVal;
@@ -1787,7 +1787,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
         // predicates field (see rustc_typeck::collect::ty_generics), so remove
         // them.
         let stripped_typarams = gens.types.iter().filter_map(|tp| {
-            if tp.name == keywords::SelfType.name() {
+            if tp.name == keywords::SelfType.name().as_str() {
                 assert_eq!(tp.index, 0);
                 None
             } else {
@@ -3367,6 +3367,12 @@ impl Clean<String> for ast::Name {
     }
 }
 
+impl Clean<String> for InternedString {
+    fn clean(&self, _: &DocContext) -> String {
+        self.to_string()
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Typedef {
     pub type_: Type,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 72c4c4e4495..9e2c7bd7ef1 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1087,7 +1087,8 @@ impl<'a> SourceCollector<'a> {
             href.push_str(component);
             href.push('/');
         });
-        let mut fname = p.file_name().expect("source has no filename")
+        let mut fname = p.file_name()
+                         .expect("source has no filename")
                          .to_os_string();
         fname.push(".html");
         cur.push(&fname);
@@ -1373,6 +1374,135 @@ impl<'a> Cache {
     }
 }
 
+#[derive(Debug, Eq, PartialEq, Hash)]
+struct ItemEntry {
+    url: String,
+    name: String,
+}
+
+impl ItemEntry {
+    fn new(mut url: String, name: String) -> ItemEntry {
+        while url.starts_with('/') {
+            url.remove(0);
+        }
+        ItemEntry {
+            url,
+            name,
+        }
+    }
+}
+
+impl fmt::Display for ItemEntry {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "<a href='{}'>{}</a>", self.url, Escape(&self.name))
+    }
+}
+
+impl PartialOrd for ItemEntry {
+    fn partial_cmp(&self, other: &ItemEntry) -> Option<::std::cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for ItemEntry {
+    fn cmp(&self, other: &ItemEntry) -> ::std::cmp::Ordering {
+        self.name.cmp(&other.name)
+    }
+}
+
+#[derive(Debug)]
+struct AllTypes {
+    structs: HashSet<ItemEntry>,
+    enums: HashSet<ItemEntry>,
+    unions: HashSet<ItemEntry>,
+    primitives: HashSet<ItemEntry>,
+    traits: HashSet<ItemEntry>,
+    macros: HashSet<ItemEntry>,
+    functions: HashSet<ItemEntry>,
+    typedefs: HashSet<ItemEntry>,
+    statics: HashSet<ItemEntry>,
+    constants: HashSet<ItemEntry>,
+}
+
+impl AllTypes {
+    fn new() -> AllTypes {
+        AllTypes {
+            structs: HashSet::with_capacity(100),
+            enums: HashSet::with_capacity(100),
+            unions: HashSet::with_capacity(100),
+            primitives: HashSet::with_capacity(26),
+            traits: HashSet::with_capacity(100),
+            macros: HashSet::with_capacity(100),
+            functions: HashSet::with_capacity(100),
+            typedefs: HashSet::with_capacity(100),
+            statics: HashSet::with_capacity(100),
+            constants: HashSet::with_capacity(100),
+        }
+    }
+
+    fn append(&mut self, item_name: String, item_type: &ItemType) {
+        let mut url: Vec<_> = item_name.split("::").skip(1).collect();
+        if let Some(name) = url.pop() {
+            let new_url = format!("{}/{}.{}.html", url.join("/"), item_type, name);
+            url.push(name);
+            let name = url.join("::");
+            match *item_type {
+                ItemType::Struct => self.structs.insert(ItemEntry::new(new_url, name)),
+                ItemType::Enum => self.enums.insert(ItemEntry::new(new_url, name)),
+                ItemType::Union => self.unions.insert(ItemEntry::new(new_url, name)),
+                ItemType::Primitive => self.primitives.insert(ItemEntry::new(new_url, name)),
+                ItemType::Trait => self.traits.insert(ItemEntry::new(new_url, name)),
+                ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)),
+                ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)),
+                ItemType::Typedef => self.typedefs.insert(ItemEntry::new(new_url, name)),
+                ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
+                ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
+                _ => true,
+            };
+        }
+    }
+}
+
+fn print_entries(f: &mut fmt::Formatter, e: &HashSet<ItemEntry>, title: &str,
+                 class: &str) -> fmt::Result {
+    if !e.is_empty() {
+        let mut e: Vec<&ItemEntry> = e.iter().collect();
+        e.sort();
+        write!(f, "<h3 id='{}'>{}</h3><ul class='{} docblock'>{}</ul>",
+               title,
+               Escape(title),
+               class,
+               e.iter().map(|s| format!("<li>{}</li>", s)).collect::<String>())?;
+    }
+    Ok(())
+}
+
+impl fmt::Display for AllTypes {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f,
+"<h1 class='fqn'>\
+     <span class='in-band'>List of all items</span>\
+     <span class='out-of-band'>\
+         <span id='render-detail'>\
+             <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" title=\"collapse all docs\">\
+                 [<span class='inner'>&#x2212;</span>]\
+             </a>\
+         </span>
+     </span>
+</h1>")?;
+        print_entries(f, &self.structs, "Structs", "structs")?;
+        print_entries(f, &self.enums, "Enums", "enums")?;
+        print_entries(f, &self.unions, "Unions", "unions")?;
+        print_entries(f, &self.primitives, "Primitives", "primitives")?;
+        print_entries(f, &self.traits, "Traits", "traits")?;
+        print_entries(f, &self.macros, "Macros", "macros")?;
+        print_entries(f, &self.functions, "Functions", "functions")?;
+        print_entries(f, &self.typedefs, "Typedefs", "typedefs")?;
+        print_entries(f, &self.statics, "Statics", "statics")?;
+        print_entries(f, &self.constants, "Constants", "constants")
+    }
+}
+
 impl Context {
     /// String representation of how to get back to the root path of the 'doc/'
     /// folder in terms of a relative URL.
@@ -1414,16 +1544,52 @@ impl Context {
             Some(i) => i,
             None => return Ok(()),
         };
+        let final_file = self.dst.join(&krate.name)
+                                 .join("all.html");
+        let crate_name = krate.name.clone();
         item.name = Some(krate.name);
 
-        // Render the crate documentation
-        let mut work = vec![(self, item)];
+        let mut all = AllTypes::new();
 
-        while let Some((mut cx, item)) = work.pop() {
-            cx.item(item, |cx, item| {
-                work.push((cx.clone(), item))
-            })?
+        {
+            // Render the crate documentation
+            let mut work = vec![(self.clone(), item)];
+
+            while let Some((mut cx, item)) = work.pop() {
+                cx.item(item, &mut all, |cx, item| {
+                    work.push((cx.clone(), item))
+                })?
+            }
         }
+
+        let mut w = BufWriter::new(try_err!(File::create(&final_file), &final_file));
+        let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
+        if !root_path.ends_with('/') {
+            root_path.push('/');
+        }
+        let page = layout::Page {
+            title: "List of all items in this crate",
+            css_class: "mod",
+            root_path: "../",
+            description: "List of all items in this crate",
+            keywords: BASIC_KEYWORDS,
+            resource_suffix: &self.shared.resource_suffix,
+        };
+        let sidebar = if let Some(ref version) = cache().crate_version {
+            format!("<p class='location'>Crate {}</p>\
+                     <div class='block version'>\
+                         <p>Version {}</p>\
+                     </div>\
+                     <a id='all-types' href='index.html'><p>Back to index</p></a>",
+                    crate_name, version)
+        } else {
+            String::new()
+        };
+        try_err!(layout::render(&mut w, &self.shared.layout,
+                                &page, &sidebar, &all,
+                                self.shared.css_file_extension.is_some(),
+                                &self.shared.themes),
+                 &final_file);
         Ok(())
     }
 
@@ -1496,8 +1662,8 @@ impl Context {
     /// all sub-items which need to be rendered.
     ///
     /// The rendering driver uses this closure to queue up more work.
-    fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
-        F: FnMut(&mut Context, clean::Item),
+    fn item<F>(&mut self, item: clean::Item, all: &mut AllTypes, mut f: F) -> Result<(), Error>
+        where F: FnMut(&mut Context, clean::Item),
     {
         // Stripped modules survive the rustdoc passes (i.e. `strip-private`)
         // if they contain impls for public types. These modules can also
@@ -1544,7 +1710,7 @@ impl Context {
                 }
 
                 for item in m.items {
-                    f(this,item);
+                    f(this, item);
                 }
 
                 Ok(())
@@ -1562,13 +1728,14 @@ impl Context {
                 let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                 try_err!(dst.write_all(&buf), &joint_dst);
 
+                all.append(full_path(self, &item), &item_type);
                 // Redirect from a sane URL using the namespace to Rustdoc's
                 // URL for the page.
                 let redir_name = format!("{}.{}.html", name, item_type.name_space());
                 let redir_dst = self.dst.join(redir_name);
                 if let Ok(redirect_out) = OpenOptions::new().create_new(true)
-                                                                .write(true)
-                                                                .open(&redir_dst) {
+                                                            .write(true)
+                                                            .open(&redir_dst) {
                     let mut redirect_out = BufWriter::new(redirect_out);
                     try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
                 }
@@ -1730,11 +1897,12 @@ impl<'a> fmt::Display for Item<'a> {
                    version)?;
         }
         write!(fmt,
-               r##"<span id='render-detail'>
-                   <a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
-                       [<span class='inner'>&#x2212;</span>]
-                   </a>
-               </span>"##)?;
+               "<span id='render-detail'>\
+                   <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
+                      title=\"collapse all docs\">\
+                       [<span class='inner'>&#x2212;</span>]\
+                   </a>\
+               </span>")?;
 
         // Write `src` tag
         //
@@ -3567,24 +3735,23 @@ impl<'a> fmt::Display for Sidebar<'a> {
 
         if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union()
             || it.is_enum() || it.is_mod() || it.is_typedef() {
-            write!(fmt, "<p class='location'>")?;
-            match it.inner {
-                clean::StructItem(..) => write!(fmt, "Struct ")?,
-                clean::TraitItem(..) => write!(fmt, "Trait ")?,
-                clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
-                clean::UnionItem(..) => write!(fmt, "Union ")?,
-                clean::EnumItem(..) => write!(fmt, "Enum ")?,
-                clean::TypedefItem(..) => write!(fmt, "Type Definition ")?,
-                clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?,
-                clean::ModuleItem(..) => if it.is_crate() {
-                    write!(fmt, "Crate ")?;
-                } else {
-                    write!(fmt, "Module ")?;
+            write!(fmt, "<p class='location'>{}{}</p>",
+                match it.inner {
+                    clean::StructItem(..) => "Struct ",
+                    clean::TraitItem(..) => "Trait ",
+                    clean::PrimitiveItem(..) => "Primitive Type ",
+                    clean::UnionItem(..) => "Union ",
+                    clean::EnumItem(..) => "Enum ",
+                    clean::TypedefItem(..) => "Type Definition ",
+                    clean::ForeignTypeItem => "Foreign Type ",
+                    clean::ModuleItem(..) => if it.is_crate() {
+                        "Crate "
+                    } else {
+                        "Module "
+                    },
+                    _ => "",
                 },
-                _ => (),
-            }
-            write!(fmt, "{}", it.name.as_ref().unwrap())?;
-            write!(fmt, "</p>")?;
+                it.name.as_ref().unwrap())?;
         }
 
         if it.is_crate() {
@@ -3592,8 +3759,10 @@ impl<'a> fmt::Display for Sidebar<'a> {
                 write!(fmt,
                        "<div class='block version'>\
                         <p>Version {}</p>\
-                        </div>",
-                       version)?;
+                        </div>
+                        <a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
+                       version,
+                       it.name.as_ref().unwrap())?;
             }
         }
 
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index f4918033c8e..4c6c8dcfdda 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1294,3 +1294,21 @@ kbd {
 	font-size: 19px;
 	display: block;
 }
+
+#main > ul {
+	padding-left: 10px;
+}
+#main > ul > li {
+	list-style: none;
+}
+#all-types {
+	text-align: center;
+	border: 1px solid;
+	margin: 0 10px;
+	margin-bottom: 10px;
+	display: block;
+	border-radius: 7px;
+}
+#all-types > p {
+	margin: 5px 0;
+}
\ No newline at end of file
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 09776569f80..93971a205bf 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -389,3 +389,10 @@ kbd {
 		background: #f0f0f0;
 	}
 }
+
+#all-types {
+	background-color: #505050;
+}
+#all-types:hover {
+	background-color: #606060;
+}
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 2334a272855..e13818b4bd2 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -383,3 +383,10 @@ kbd {
 		background: #fff;
 	}
 }
+
+#all-types {
+	background-color: #fff;
+}
+#all-types:hover {
+	background-color: #f9f9f9;
+}
\ No newline at end of file
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 42e87f88fd4..8463475afab 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -12,7 +12,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
-#![deny(warnings)]
 
 #![feature(ascii_ctype)]
 #![feature(rustc_private)]
@@ -20,8 +19,8 @@
 #![feature(box_syntax)]
 #![feature(fs_read_write)]
 #![feature(set_stdio)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(test)]
-#![feature(unicode)]
 #![feature(vec_remove_item)]
 #![feature(entry_and_modify)]
 
@@ -42,7 +41,6 @@ extern crate serialize;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 extern crate test as testing;
-extern crate std_unicode;
 #[macro_use] extern crate log;
 extern crate rustc_errors as errors;
 extern crate pulldown_cmark;
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index f78eed30694..22d27b6697a 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -19,7 +19,6 @@ Core encoding and decoding interfaces.
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(allow(unused_variables), deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
new file mode 100644
index 00000000000..ff578ec42d2
--- /dev/null
+++ b/src/libstd/alloc.rs
@@ -0,0 +1,121 @@
+// 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.
+
+//! dox
+
+#![unstable(issue = "32838", feature = "allocator_api")]
+
+#[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap;
+#[doc(inline)] pub use alloc_crate::alloc::Global;
+#[doc(inline)] pub use alloc_system::System;
+#[doc(inline)] pub use core::alloc::*;
+
+#[cfg(not(test))]
+#[doc(hidden)]
+#[allow(unused_attributes)]
+pub mod __default_lib_allocator {
+    use super::{System, Layout, GlobalAlloc, Opaque};
+    // for symbol names src/librustc/middle/allocator.rs
+    // for signatures src/librustc_allocator/lib.rs
+
+    // linkage directives are provided as part of the current compiler allocator
+    // ABI
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        System.alloc(layout) as *mut u8
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_oom() -> ! {
+        System.oom()
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
+                                       size: usize,
+                                       align: usize) {
+        System.dealloc(ptr as *mut Opaque, Layout::from_size_align_unchecked(size, align))
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
+                                       old_size: usize,
+                                       align: usize,
+                                       new_size: usize) -> *mut u8 {
+        let old_layout = Layout::from_size_align_unchecked(old_size, align);
+        System.realloc(ptr as *mut Opaque, old_layout, new_size) as *mut u8
+    }
+
+    #[no_mangle]
+    #[rustc_std_internal_symbol]
+    pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        System.alloc_zeroed(layout) as *mut u8
+    }
+
+    #[cfg(stage0)]
+    pub mod stage0 {
+        #[no_mangle]
+        #[rustc_std_internal_symbol]
+        pub unsafe extern fn __rdl_usable_size(_layout: *const u8,
+                                               _min: *mut usize,
+                                               _max: *mut usize) {
+            unimplemented!()
+        }
+
+        #[no_mangle]
+        #[rustc_std_internal_symbol]
+        pub unsafe extern fn __rdl_alloc_excess(_size: usize,
+                                                _align: usize,
+                                                _excess: *mut usize,
+                                                _err: *mut u8) -> *mut u8 {
+            unimplemented!()
+        }
+
+        #[no_mangle]
+        #[rustc_std_internal_symbol]
+        pub unsafe extern fn __rdl_realloc_excess(_ptr: *mut u8,
+                                                  _old_size: usize,
+                                                  _old_align: usize,
+                                                  _new_size: usize,
+                                                  _new_align: usize,
+                                                  _excess: *mut usize,
+                                                  _err: *mut u8) -> *mut u8 {
+            unimplemented!()
+        }
+
+        #[no_mangle]
+        #[rustc_std_internal_symbol]
+        pub unsafe extern fn __rdl_grow_in_place(_ptr: *mut u8,
+                                                 _old_size: usize,
+                                                 _old_align: usize,
+                                                 _new_size: usize,
+                                                 _new_align: usize) -> u8 {
+            unimplemented!()
+        }
+
+        #[no_mangle]
+        #[rustc_std_internal_symbol]
+        pub unsafe extern fn __rdl_shrink_in_place(_ptr: *mut u8,
+                                                   _old_size: usize,
+                                                   _old_align: usize,
+                                                   _new_size: usize,
+                                                   _new_align: usize) -> u8 {
+            unimplemented!()
+        }
+
+    }
+}
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index e0b48e565d0..20a4f9b508d 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -11,10 +11,8 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
-use alloc::heap::Heap;
-use alloc::allocator::CollectionAllocErr;
+use alloc::{Global, Alloc, CollectionAllocErr};
 use cell::Cell;
-use core::heap::Alloc;
 use borrow::Borrow;
 use cmp::max;
 use fmt::{self, Debug};
@@ -786,7 +784,7 @@ impl<K, V, S> HashMap<K, V, S>
     pub fn reserve(&mut self, additional: usize) {
         match self.try_reserve(additional) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e),
+            Err(CollectionAllocErr::AllocErr) => Global.oom(),
             Ok(()) => { /* yay */ }
          }
     }
@@ -3636,7 +3634,7 @@ mod test_map {
             if let Err(CapacityOverflow) = empty_bytes.try_reserve(max_no_ovf) {
             } else { panic!("isize::MAX + 1 should trigger a CapacityOverflow!") }
         } else {
-            if let Err(AllocErr(_)) = empty_bytes.try_reserve(max_no_ovf) {
+            if let Err(AllocErr) = empty_bytes.try_reserve(max_no_ovf) {
             } else { panic!("isize::MAX + 1 should trigger an OOM!") }
         }
     }
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index fa6053d3f6d..93f059076d7 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::heap::Heap;
-use core::heap::{Alloc, Layout};
-
+use alloc::{Global, Alloc, Layout, CollectionAllocErr};
 use cmp;
 use hash::{BuildHasher, Hash, Hasher};
 use marker;
@@ -18,7 +16,6 @@ use mem::{align_of, size_of, needs_drop};
 use mem;
 use ops::{Deref, DerefMut};
 use ptr::{self, Unique, NonNull};
-use alloc::allocator::CollectionAllocErr;
 
 use self::BucketState::*;
 
@@ -757,15 +754,13 @@ impl<K, V> RawTable<K, V> {
             return Err(CollectionAllocErr::CapacityOverflow);
         }
 
-        let buffer = Heap.alloc(Layout::from_size_align(size, alignment)
-            .ok_or(CollectionAllocErr::CapacityOverflow)?)?;
-
-        let hashes = buffer as *mut HashUint;
+        let buffer = Global.alloc(Layout::from_size_align(size, alignment)
+            .map_err(|_| CollectionAllocErr::CapacityOverflow)?)?;
 
         Ok(RawTable {
             capacity_mask: capacity.wrapping_sub(1),
             size: 0,
-            hashes: TaggedHashUintPtr::new(hashes),
+            hashes: TaggedHashUintPtr::new(buffer.cast().as_ptr()),
             marker: marker::PhantomData,
         })
     }
@@ -775,7 +770,7 @@ impl<K, V> RawTable<K, V> {
     unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         match Self::try_new_uninitialized(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e),
+            Err(CollectionAllocErr::AllocErr) => Global.oom(),
             Ok(table) => { table }
         }
     }
@@ -814,7 +809,7 @@ impl<K, V> RawTable<K, V> {
     pub fn new(capacity: usize) -> RawTable<K, V> {
         match Self::try_new(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr(e)) => Heap.oom(e),
+            Err(CollectionAllocErr::AllocErr) => Global.oom(),
             Ok(table) => { table }
         }
     }
@@ -1188,8 +1183,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
         debug_assert!(!oflo, "should be impossible");
 
         unsafe {
-            Heap.dealloc(self.hashes.ptr() as *mut u8,
-                         Layout::from_size_align(size, align).unwrap());
+            Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).as_opaque(),
+                           Layout::from_size_align(size, align).unwrap());
             // Remember how everything was allocated out of one buffer
             // during initialization? We only need one call to free here.
         }
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index c7ad27d8d26..9cf73824dea 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -424,13 +424,13 @@
 #[doc(hidden)]
 pub use ops::Bound;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{BinaryHeap, BTreeMap, BTreeSet};
+pub use alloc_crate::{BinaryHeap, BTreeMap, BTreeSet};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{LinkedList, VecDeque};
+pub use alloc_crate::{LinkedList, VecDeque};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{binary_heap, btree_map, btree_set};
+pub use alloc_crate::{binary_heap, btree_map, btree_set};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::{linked_list, vec_deque};
+pub use alloc_crate::{linked_list, vec_deque};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::hash_map::HashMap;
@@ -446,7 +446,7 @@ pub mod range {
 }
 
 #[unstable(feature = "try_reserve", reason = "new API", issue="48043")]
-pub use alloc::allocator::CollectionAllocErr;
+pub use heap::CollectionAllocErr;
 
 mod hash;
 
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 3d0c96585b5..3c209928d43 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -51,13 +51,13 @@
 // coherence challenge (e.g., specialization, neg impls, etc) we can
 // reconsider what crate these items belong in.
 
-use alloc::allocator;
 use any::TypeId;
 use borrow::Cow;
 use cell;
 use char;
 use core::array;
 use fmt::{self, Debug, Display};
+use heap::{AllocErr, LayoutErr, CannotReallocInPlace};
 use mem::transmute;
 use num;
 use str;
@@ -241,18 +241,27 @@ impl Error for ! {
 #[unstable(feature = "allocator_api",
            reason = "the precise API and guarantees it provides may be tweaked.",
            issue = "32838")]
-impl Error for allocator::AllocErr {
+impl Error for AllocErr {
     fn description(&self) -> &str {
-        allocator::AllocErr::description(self)
+        "memory allocation failed"
     }
 }
 
 #[unstable(feature = "allocator_api",
            reason = "the precise API and guarantees it provides may be tweaked.",
            issue = "32838")]
-impl Error for allocator::CannotReallocInPlace {
+impl Error for LayoutErr {
     fn description(&self) -> &str {
-        allocator::CannotReallocInPlace::description(self)
+        "invalid parameters to Layout::from_size_align"
+    }
+}
+
+#[unstable(feature = "allocator_api",
+           reason = "the precise API and guarantees it provides may be tweaked.",
+           issue = "32838")]
+impl Error for CannotReallocInPlace {
+    fn description(&self) -> &str {
+        CannotReallocInPlace::description(self)
     }
 }
 
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index ceb019bc95b..ca39089a958 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -329,6 +329,57 @@ impl f32 {
         unsafe { intrinsics::fmaf32(self, a, b) }
     }
 
+    /// Calculates Euclidean division, the matching method for `mod_euc`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * rhs + self.mod_euc(rhs)`.
+    /// In other words, the result is `self / rhs` rounded to the integer `n`
+    /// such that `self >= n * rhs`.
+    ///
+    /// ```
+    /// #![feature(euclidean_division)]
+    /// let a: f32 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// ```
+    #[inline]
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn div_euc(self, rhs: f32) -> f32 {
+        let q = (self / rhs).trunc();
+        if self % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
+        }
+        q
+    }
+
+    /// Calculates the Euclidean modulo (self mod rhs), which is never negative.
+    ///
+    /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
+    ///
+    /// ```
+    /// #![feature(euclidean_division)]
+    /// let a: f32 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.mod_euc(b), 3.0);
+    /// assert_eq!((-a).mod_euc(b), 1.0);
+    /// assert_eq!(a.mod_euc(-b), 3.0);
+    /// assert_eq!((-a).mod_euc(-b), 1.0);
+    /// ```
+    #[inline]
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn mod_euc(self, rhs: f32) -> f32 {
+        let r = self % rhs;
+        if r < 0.0 {
+            r + rhs.abs()
+        } else {
+            r
+        }
+    }
+
+
     /// Takes the reciprocal (inverse) of a number, `1/x`.
     ///
     /// ```
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index 97adf108b73..a9585670ad0 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -315,6 +315,56 @@ impl f64 {
         unsafe { intrinsics::fmaf64(self, a, b) }
     }
 
+    /// Calculates Euclidean division, the matching method for `mod_euc`.
+    ///
+    /// This computes the integer `n` such that
+    /// `self = n * rhs + self.mod_euc(rhs)`.
+    /// In other words, the result is `self / rhs` rounded to the integer `n`
+    /// such that `self >= n * rhs`.
+    ///
+    /// ```
+    /// #![feature(euclidean_division)]
+    /// let a: f64 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// ```
+    #[inline]
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn div_euc(self, rhs: f64) -> f64 {
+        let q = (self / rhs).trunc();
+        if self % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
+        }
+        q
+    }
+
+    /// Calculates the Euclidean modulo (self mod rhs), which is never negative.
+    ///
+    /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
+    ///
+    /// ```
+    /// #![feature(euclidean_division)]
+    /// let a: f64 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(a.mod_euc(b), 3.0);
+    /// assert_eq!((-a).mod_euc(b), 1.0);
+    /// assert_eq!(a.mod_euc(-b), 3.0);
+    /// assert_eq!((-a).mod_euc(-b), 1.0);
+    /// ```
+    #[inline]
+    #[unstable(feature = "euclidean_division", issue = "49048")]
+    pub fn mod_euc(self, rhs: f64) -> f64 {
+        let r = self % rhs;
+        if r < 0.0 {
+            r + rhs.abs()
+        } else {
+            r
+        }
+    }
+
     /// Takes the reciprocal (inverse) of a number, `1/x`.
     ///
     /// ```
diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs
deleted file mode 100644
index 4a391372c3a..00000000000
--- a/src/libstd/heap.rs
+++ /dev/null
@@ -1,176 +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.
-
-//! dox
-
-#![unstable(issue = "32838", feature = "allocator_api")]
-
-pub use alloc::heap::Heap;
-pub use alloc_system::System;
-pub use core::heap::*;
-
-#[cfg(not(test))]
-#[doc(hidden)]
-#[allow(unused_attributes)]
-pub mod __default_lib_allocator {
-    use super::{System, Layout, Alloc, AllocErr};
-    use ptr;
-
-    // for symbol names src/librustc/middle/allocator.rs
-    // for signatures src/librustc_allocator/lib.rs
-
-    // linkage directives are provided as part of the current compiler allocator
-    // ABI
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_alloc(size: usize,
-                                     align: usize,
-                                     err: *mut u8) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        match System.alloc(layout) {
-            Ok(p) => p,
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
-        System.oom((*(err as *const AllocErr)).clone())
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
-                                       size: usize,
-                                       align: usize) {
-        System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_usable_size(layout: *const u8,
-                                           min: *mut usize,
-                                           max: *mut usize) {
-        let pair = System.usable_size(&*(layout as *const Layout));
-        *min = pair.0;
-        *max = pair.1;
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
-                                       old_size: usize,
-                                       old_align: usize,
-                                       new_size: usize,
-                                       new_align: usize,
-                                       err: *mut u8) -> *mut u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.realloc(ptr, old_layout, new_layout) {
-            Ok(p) => p,
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
-                                            align: usize,
-                                            err: *mut u8) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        match System.alloc_zeroed(layout) {
-            Ok(p) => p,
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_alloc_excess(size: usize,
-                                            align: usize,
-                                            excess: *mut usize,
-                                            err: *mut u8) -> *mut u8 {
-        let layout = Layout::from_size_align_unchecked(size, align);
-        match System.alloc_excess(layout) {
-            Ok(p) => {
-                *excess = p.1;
-                p.0
-            }
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
-                                              old_size: usize,
-                                              old_align: usize,
-                                              new_size: usize,
-                                              new_align: usize,
-                                              excess: *mut usize,
-                                              err: *mut u8) -> *mut u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.realloc_excess(ptr, old_layout, new_layout) {
-            Ok(p) => {
-                *excess = p.1;
-                p.0
-            }
-            Err(e) => {
-                ptr::write(err as *mut AllocErr, e);
-                0 as *mut u8
-            }
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
-                                             old_size: usize,
-                                             old_align: usize,
-                                             new_size: usize,
-                                             new_align: usize) -> u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.grow_in_place(ptr, old_layout, new_layout) {
-            Ok(()) => 1,
-            Err(_) => 0,
-        }
-    }
-
-    #[no_mangle]
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
-                                               old_size: usize,
-                                               old_align: usize,
-                                               new_size: usize,
-                                               new_align: usize) -> u8 {
-        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
-        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
-        match System.shrink_in_place(ptr, old_layout, new_layout) {
-            Ok(()) => 1,
-            Err(_) => 0,
-        }
-    }
-}
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 3b8c42ddb39..b02e133ee4d 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1829,7 +1829,6 @@ impl<T> Take<T> {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(take_set_limit)]
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1845,7 +1844,7 @@ impl<T> Take<T> {
     ///     Ok(())
     /// }
     /// ```
-    #[unstable(feature = "take_set_limit", issue = "42781")]
+    #[stable(feature = "take_set_limit", since = "1.27.0")]
     pub fn set_limit(&mut self, limit: u64) {
         self.limit = limit;
     }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 3227aa9acff..a34fcb5a7f9 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -227,10 +227,6 @@
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
 
-// Turn warnings into errors, but only after stage0, where it can be useful for
-// code to emit warnings during language transitions
-#![cfg_attr(not(stage0), deny(warnings))]
-
 // std may use features in a platform-specific way
 #![allow(unused_features)]
 
@@ -279,6 +275,7 @@
 #![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
+#![feature(nonnull_cast)]
 #![feature(exhaustive_patterns)]
 #![feature(nonzero)]
 #![feature(num_bits_bytes)]
@@ -311,7 +308,6 @@
 #![feature(toowned_clone_into)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(unicode)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
@@ -356,9 +352,8 @@ extern crate core as __core;
 
 #[macro_use]
 #[macro_reexport(vec, format)]
-extern crate alloc;
+extern crate alloc as alloc_crate;
 extern crate alloc_system;
-extern crate std_unicode;
 #[doc(masked)]
 extern crate libc;
 
@@ -443,23 +438,23 @@ pub use core::u32;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::u64;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::boxed;
+pub use alloc_crate::boxed;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::rc;
+pub use alloc_crate::rc;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::borrow;
+pub use alloc_crate::borrow;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::fmt;
+pub use alloc_crate::fmt;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::slice;
+pub use alloc_crate::slice;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::str;
+pub use alloc_crate::str;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::string;
+pub use alloc_crate::string;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::vec;
+pub use alloc_crate::vec;
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use std_unicode::char;
+pub use core::char;
 #[stable(feature = "i128", since = "1.26.0")]
 pub use core::u128;
 
@@ -483,7 +478,14 @@ pub mod path;
 pub mod process;
 pub mod sync;
 pub mod time;
-pub mod heap;
+pub mod alloc;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+#[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
+/// Use the `alloc` module instead.
+pub mod heap {
+    pub use alloc::*;
+}
 
 // Platform-abstraction modules
 #[macro_use]
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index 289b47b3484..642b284c6c7 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -18,7 +18,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::arc::{Arc, Weak};
+pub use alloc_crate::arc::{Arc, Weak};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::sync::atomic;
 
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
index 296773d20f6..df945ac3859 100644
--- a/src/libstd/sync/mpsc/mpsc_queue.rs
+++ b/src/libstd/sync/mpsc/mpsc_queue.rs
@@ -23,10 +23,9 @@
 
 pub use self::PopResult::*;
 
-use alloc::boxed::Box;
 use core::ptr;
 use core::cell::UnsafeCell;
-
+use boxed::Box;
 use sync::atomic::{AtomicPtr, Ordering};
 
 /// A result of the `pop` function.
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index cc4be92276a..9482f6958b3 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -16,7 +16,7 @@
 
 // http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
 
-use alloc::boxed::Box;
+use boxed::Box;
 use core::ptr;
 use core::cell::UnsafeCell;
 
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
index a22d9053b69..5d66936b2a4 100644
--- a/src/libstd/sys/cloudabi/thread.rs
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use cmp;
 use ffi::CStr;
 use io;
diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs
index da27787babb..eb3a1ead58c 100644
--- a/src/libstd/sys/redox/os_str.rs
+++ b/src/libstd/sys/redox/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
 use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs
index f20350269b7..110d46ca3ab 100644
--- a/src/libstd/sys/redox/thread.rs
+++ b/src/libstd/sys/redox/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use ffi::CStr;
 use io;
 use mem;
diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs
index e43bc6da5f1..01c0fb830aa 100644
--- a/src/libstd/sys/unix/os_str.rs
+++ b/src/libstd/sys/unix/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
 use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 2db3d4a5744..9e388808030 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use cmp;
 use ffi::CStr;
 use io;
diff --git a/src/libstd/sys/wasm/os_str.rs b/src/libstd/sys/wasm/os_str.rs
index 84f560af69b..e0da5bdf36c 100644
--- a/src/libstd/sys/wasm/os_str.rs
+++ b/src/libstd/sys/wasm/os_str.rs
@@ -19,7 +19,7 @@ use rc::Rc;
 use sync::Arc;
 use sys_common::{AsInner, IntoInner};
 use sys_common::bytestring::debug_fmt_bytestring;
-use std_unicode::lossy::Utf8Lossy;
+use core::str::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
index 7345843b975..728e678a2e8 100644
--- a/src/libstd/sys/wasm/thread.rs
+++ b/src/libstd/sys/wasm/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use ffi::CStr;
 use io;
 use sys::{unsupported, Void};
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index bd5507e8f89..be442f41374 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -31,7 +31,7 @@ use sys::stdio;
 use sys::cvt;
 use sys_common::{AsInner, FromInner, IntoInner};
 use sys_common::process::{CommandEnv, EnvKey};
-use alloc::borrow::Borrow;
+use borrow::Borrow;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 4b3d1b586b5..b6f63303dc2 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use io;
 use ffi::CStr;
 use mem;
diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs
index ce6fd4cb075..26da51c9825 100644
--- a/src/libstd/sys_common/at_exit_imp.rs
+++ b/src/libstd/sys_common/at_exit_imp.rs
@@ -12,7 +12,7 @@
 //!
 //! Documentation can be found on the `rt::at_exit` function.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use ptr;
 use sys_common::mutex::Mutex;
 
diff --git a/src/libstd/sys_common/bytestring.rs b/src/libstd/sys_common/bytestring.rs
index eb9cad09915..971b83938c1 100644
--- a/src/libstd/sys_common/bytestring.rs
+++ b/src/libstd/sys_common/bytestring.rs
@@ -11,7 +11,7 @@
 #![allow(dead_code)]
 
 use fmt::{Formatter, Result, Write};
-use std_unicode::lossy::{Utf8Lossy, Utf8LossyChunk};
+use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
 
 pub fn debug_fmt_bytestring(slice: &[u8], f: &mut Formatter) -> Result {
     // Writes out a valid unicode string with the correct escape sequences
diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs
index d0c5951bd6c..ddf0ebe603e 100644
--- a/src/libstd/sys_common/process.rs
+++ b/src/libstd/sys_common/process.rs
@@ -14,7 +14,7 @@
 use ffi::{OsStr, OsString};
 use env;
 use collections::BTreeMap;
-use alloc::borrow::Borrow;
+use borrow::Borrow;
 
 pub trait EnvKey:
     From<OsString> + Into<OsString> +
diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs
index f1379b6ec63..da6f58ef6bb 100644
--- a/src/libstd/sys_common/thread.rs
+++ b/src/libstd/sys_common/thread.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::boxed::FnBox;
+use boxed::FnBox;
 use env;
 use sync::atomic::{self, Ordering};
 use sys::stack_overflow;
diff --git a/src/libstd_unicode/Cargo.toml b/src/libstd_unicode/Cargo.toml
index 283070a0e2c..b1c55c2e4b6 100644
--- a/src/libstd_unicode/Cargo.toml
+++ b/src/libstd_unicode/Cargo.toml
@@ -9,10 +9,6 @@ path = "lib.rs"
 test = false
 bench = false
 
-[[test]]
-name = "std_unicode_tests"
-path = "tests/lib.rs"
-
 [dependencies]
 core = { path = "../libcore" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
index c22ea1671fa..c0d47f1fcb4 100644
--- a/src/libstd_unicode/lib.rs
+++ b/src/libstd_unicode/lib.rs
@@ -27,39 +27,10 @@
        html_playground_url = "https://play.rust-lang.org/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
-#![deny(warnings)]
-#![deny(missing_debug_implementations)]
 #![no_std]
 
-#![feature(ascii_ctype)]
-#![feature(core_char_ext)]
-#![feature(str_internals)]
-#![feature(decode_utf8)]
-#![feature(fn_traits)]
-#![feature(lang_items)]
-#![feature(non_exhaustive)]
+#![feature(unicode_internals)]
 #![feature(staged_api)]
-#![feature(unboxed_closures)]
+#![rustc_deprecated(since = "1.27.0", reason = "moved into libcore")]
 
-mod bool_trie;
-mod tables;
-mod u_str;
-mod version;
-pub mod char;
-pub mod lossy;
-
-#[allow(deprecated)]
-pub mod str {
-    pub use u_str::{SplitWhitespace, UnicodeStr};
-    pub use u_str::Utf16Encoder;
-}
-
-// For use in liballoc, not re-exported in libstd.
-pub mod derived_property {
-    pub use tables::derived_property::{Case_Ignorable, Cased};
-}
-
-// For use in libsyntax
-pub mod property {
-    pub use tables::property::Pattern_White_Space;
-}
+pub use core::unicode::*;
diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs
deleted file mode 100644
index a72e1210d93..00000000000
--- a/src/libstd_unicode/u_str.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-// 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.
-
-//! Unicode-intensive string manipulations.
-//!
-//! This module provides functionality to `str` that requires the Unicode
-//! methods provided by the unicode parts of the CharExt trait.
-
-use core::char;
-use core::iter::{Filter, FusedIterator};
-use core::str::Split;
-
-/// An iterator over the non-whitespace substrings of a string,
-/// separated by any amount of whitespace.
-///
-/// This struct is created by the [`split_whitespace`] method on [`str`].
-/// See its documentation for more.
-///
-/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
-/// [`str`]: ../../std/primitive.str.html
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-#[derive(Clone, Debug)]
-pub struct SplitWhitespace<'a> {
-    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
-}
-
-/// Methods for Unicode string slices
-#[allow(missing_docs)] // docs in liballoc
-pub trait UnicodeStr {
-    fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
-    fn is_whitespace(&self) -> bool;
-    fn is_alphanumeric(&self) -> bool;
-    fn trim(&self) -> &str;
-    fn trim_left(&self) -> &str;
-    fn trim_right(&self) -> &str;
-}
-
-impl UnicodeStr for str {
-    #[inline]
-    fn split_whitespace(&self) -> SplitWhitespace {
-        SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
-    }
-
-    #[inline]
-    fn is_whitespace(&self) -> bool {
-        self.chars().all(|c| c.is_whitespace())
-    }
-
-    #[inline]
-    fn is_alphanumeric(&self) -> bool {
-        self.chars().all(|c| c.is_alphanumeric())
-    }
-
-    #[inline]
-    fn trim(&self) -> &str {
-        self.trim_matches(|c: char| c.is_whitespace())
-    }
-
-    #[inline]
-    fn trim_left(&self) -> &str {
-        self.trim_left_matches(|c: char| c.is_whitespace())
-    }
-
-    #[inline]
-    fn trim_right(&self) -> &str {
-        self.trim_right_matches(|c: char| c.is_whitespace())
-    }
-}
-
-/// Iterator adaptor for encoding `char`s to UTF-16.
-#[derive(Clone)]
-#[allow(missing_debug_implementations)]
-pub struct Utf16Encoder<I> {
-    chars: I,
-    extra: u16,
-}
-
-impl<I> Utf16Encoder<I> {
-    /// Create a UTF-16 encoder from any `char` iterator.
-    pub fn new(chars: I) -> Utf16Encoder<I>
-        where I: Iterator<Item = char>
-    {
-        Utf16Encoder {
-            chars,
-            extra: 0,
-        }
-    }
-}
-
-impl<I> Iterator for Utf16Encoder<I>
-    where I: Iterator<Item = char>
-{
-    type Item = u16;
-
-    #[inline]
-    fn next(&mut self) -> Option<u16> {
-        if self.extra != 0 {
-            let tmp = self.extra;
-            self.extra = 0;
-            return Some(tmp);
-        }
-
-        let mut buf = [0; 2];
-        self.chars.next().map(|ch| {
-            let n = CharExt::encode_utf16(ch, &mut buf).len();
-            if n == 2 {
-                self.extra = buf[1];
-            }
-            buf[0]
-        })
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (low, high) = self.chars.size_hint();
-        // every char gets either one u16 or two u16,
-        // so this iterator is between 1 or 2 times as
-        // long as the underlying iterator.
-        (low, high.and_then(|n| n.checked_mul(2)))
-    }
-}
-
-impl<I> FusedIterator for Utf16Encoder<I>
-    where I: FusedIterator<Item = char> {}
-
-#[derive(Clone)]
-struct IsWhitespace;
-
-impl FnOnce<(char, )> for IsWhitespace {
-    type Output = bool;
-
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
-        self.call_mut(arg)
-    }
-}
-
-impl FnMut<(char, )> for IsWhitespace {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
-        arg.0.is_whitespace()
-    }
-}
-
-#[derive(Clone)]
-struct IsNotEmpty;
-
-impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
-    type Output = bool;
-
-    #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
-        self.call_mut(arg)
-    }
-}
-
-impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
-    #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
-        !arg.0.is_empty()
-    }
-}
-
-
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-impl<'a> Iterator for SplitWhitespace<'a> {
-    type Item = &'a str;
-
-    fn next(&mut self) -> Option<&'a str> {
-        self.inner.next()
-    }
-}
-
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
-    fn next_back(&mut self) -> Option<&'a str> {
-        self.inner.next_back()
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<'a> FusedIterator for SplitWhitespace<'a> {}
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e7900af7f12..91c9a1524e1 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1018,7 +1018,6 @@ impl Expr {
             ExprKind::Assign(..) => ExprPrecedence::Assign,
             ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
             ExprKind::Field(..) => ExprPrecedence::Field,
-            ExprKind::TupField(..) => ExprPrecedence::TupField,
             ExprKind::Index(..) => ExprPrecedence::Index,
             ExprKind::Range(..) => ExprPrecedence::Range,
             ExprKind::Path(..) => ExprPrecedence::Path,
@@ -1133,12 +1132,8 @@ pub enum ExprKind {
     ///
     /// For example, `a += 1`.
     AssignOp(BinOp, P<Expr>, P<Expr>),
-    /// Access of a named struct field (`obj.foo`)
+    /// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct field
     Field(P<Expr>, Ident),
-    /// Access of an unnamed field of a struct or tuple-struct
-    ///
-    /// For example, `foo.0`.
-    TupField(P<Expr>, Spanned<usize>),
     /// An indexing operation (`foo[2]`)
     Index(P<Expr>, P<Expr>),
     /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 2812e1238e9..c68a743303a 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -993,7 +993,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                     let word = &*mi.ident.name.as_str();
                     let hint = match word {
                         "C" => Some(ReprC),
-                        "packed" => Some(ReprPacked),
+                        "packed" => Some(ReprPacked(1)),
                         "simd" => Some(ReprSimd),
                         "transparent" => Some(ReprTransparent),
                         _ => match int_type_of_word(word) {
@@ -1009,27 +1009,41 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                         acc.push(h);
                     }
                 } else if let Some((name, value)) = item.name_value_literal() {
-                    if name == "align" {
-                        recognised = true;
-                        let mut align_error = None;
-                        if let ast::LitKind::Int(align, ast::LitIntType::Unsuffixed) = value.node {
-                            if align.is_power_of_two() {
+                    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 align <= 2147483647 {
-                                    acc.push(ReprAlign(align as u32));
+                                if *literal <= 2147483647 {
+                                    Ok(*literal as u32)
                                 } else {
-                                    align_error = Some("larger than 2147483647");
+                                    Err("larger than 2147483647")
                                 }
                             } else {
-                                align_error = Some("not a power of two");
+                                Err("not a power of two")
                             }
                         } else {
-                            align_error = Some("not an unsuffixed integer");
-                        }
-                        if let Some(align_error) = align_error {
-                            span_err!(diagnostic, item.span, E0589,
-                                      "invalid `repr(align)` attribute: {}", align_error);
+                            Err("not an unsuffixed integer")
                         }
+                    };
+
+                    let mut literal_error = None;
+                    if name == "align" {
+                        recognised = true;
+                        match parse_alignment(&value.node) {
+                            Ok(literal) => acc.push(ReprAlign(literal)),
+                            Err(message) => literal_error = Some(message)
+                        };
+                    }
+                    else if name == "packed" {
+                        recognised = true;
+                        match parse_alignment(&value.node) {
+                            Ok(literal) => acc.push(ReprPacked(literal)),
+                            Err(message) => literal_error = Some(message)
+                        };
+                    }
+                    if let Some(literal_error) = literal_error {
+                        span_err!(diagnostic, item.span, E0589,
+                                  "invalid `repr(align)` attribute: {}", literal_error);
                     }
                 }
                 if !recognised {
@@ -1065,7 +1079,7 @@ fn int_type_of_word(s: &str) -> Option<IntType> {
 pub enum ReprAttr {
     ReprInt(IntType),
     ReprC,
-    ReprPacked,
+    ReprPacked(u32),
     ReprSimd,
     ReprTransparent,
     ReprAlign(u32),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index a09bea25a24..c25a7686bea 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -28,7 +28,7 @@ use std::collections::HashMap;
 use std::iter;
 use std::path::PathBuf;
 use std::rc::Rc;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use std::default::Default;
 use tokenstream::{self, TokenStream};
 
@@ -565,26 +565,26 @@ pub enum SyntaxExtension {
     /// `#[derive(...)]` is a `MultiItemDecorator`.
     ///
     /// Prefer ProcMacro or MultiModifier since they are more flexible.
-    MultiDecorator(Box<MultiItemDecorator>),
+    MultiDecorator(Box<MultiItemDecorator + sync::Sync + sync::Send>),
 
     /// A syntax extension that is attached to an item and modifies it
     /// in-place. Also allows decoration, i.e., creating new items.
-    MultiModifier(Box<MultiItemModifier>),
+    MultiModifier(Box<MultiItemModifier + sync::Sync + sync::Send>),
 
     /// A function-like procedural macro. TokenStream -> TokenStream.
-    ProcMacro(Box<ProcMacro>),
+    ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>),
 
     /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
     /// The first TokenSteam is the attribute, the second is the annotated item.
     /// Allows modification of the input items and adding new items, similar to
     /// MultiModifier, but uses TokenStreams, rather than AST nodes.
-    AttrProcMacro(Box<AttrProcMacro>),
+    AttrProcMacro(Box<AttrProcMacro + sync::Sync + sync::Send>),
 
     /// A normal, function-like syntax extension.
     ///
     /// `bytes!` is a `NormalTT`.
     NormalTT {
-        expander: Box<TTMacroExpander>,
+        expander: Box<TTMacroExpander + sync::Sync + sync::Send>,
         def_info: Option<(ast::NodeId, Span)>,
         /// Whether the contents of the macro can
         /// directly use `#[unstable]` things (true == yes).
@@ -599,13 +599,15 @@ pub enum SyntaxExtension {
     /// A function-like syntax extension that has an extra ident before
     /// the block.
     ///
-    IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
+    IdentTT(Box<IdentMacroExpander + sync::Sync + sync::Send>, Option<Span>, bool),
 
     /// An attribute-like procedural macro. TokenStream -> TokenStream.
     /// The input is the annotated item.
     /// Allows generating code to implement a Trait for a given struct
     /// or enum item.
-    ProcMacroDerive(Box<MultiItemModifier>, Vec<Symbol> /* inert attribute names */),
+    ProcMacroDerive(Box<MultiItemModifier +
+                        sync::Sync +
+                        sync::Send>, Vec<Symbol> /* inert attribute names */),
 
     /// An attribute-like procedural macro that derives a builtin trait.
     BuiltinDerive(BuiltinDeriveFn),
@@ -613,7 +615,7 @@ pub enum SyntaxExtension {
     /// A declarative macro, e.g. `macro m() {}`.
     ///
     /// The second element is the definition site span.
-    DeclMacro(Box<TTMacroExpander>, Option<(ast::NodeId, Span)>),
+    DeclMacro(Box<TTMacroExpander + sync::Sync + sync::Send>, Option<(ast::NodeId, Span)>),
 }
 
 impl SyntaxExtension {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 062f3ce1127..36244f0a3c4 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -636,8 +636,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
-        let id = Spanned { node: idx, span: sp };
-        self.expr(sp, ast::ExprKind::TupField(expr, id))
+        let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
+        self.expr(sp, ast::ExprKind::Field(expr, ident))
     }
     fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
         self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Immutable, e))
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 0a3cd66d897..73ebfc20876 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -426,12 +426,18 @@ declare_features! (
     // Use `?` as the Kleene "at most one" operator
     (active, macro_at_most_once_rep, "1.25.0", Some(48075), None),
 
+    // Infer outlives requirements; RFC 2093
+    (active, infer_outlives_requirements, "1.26.0", Some(44493), None),
+
     // Multiple patterns with `|` in `if let` and `while let`
     (active, if_while_or_patterns, "1.26.0", Some(48215), None),
 
     // Parentheses in patterns
     (active, pattern_parentheses, "1.26.0", None, None),
 
+    // Allows `#[repr(packed)]` attribute on structs
+    (active, repr_packed, "1.26.0", Some(33158), None),
+
     // `use path as _;` and `extern crate c as _;`
     (active, underscore_imports, "1.26.0", Some(48216), None),
 
@@ -1020,6 +1026,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                  "never will be stable",
                                  cfg_fn!(rustc_attrs))),
 
+    // RFC #2093
+    ("infer_outlives_requirements", Normal, Gated(Stability::Unstable,
+                                   "infer_outlives_requirements",
+                                   "infer outlives requirements is an experimental feature",
+                                   cfg_fn!(infer_outlives_requirements))),
+
     ("wasm_custom_section", Whitelisted, Gated(Stability::Unstable,
                                  "wasm_custom_section",
                                  "attribute is currently unstable",
@@ -1439,11 +1451,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             }
         }
 
-        // allow attr_literals in #[repr(align(x))]
-        let mut is_repr_align = false;
+        // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
+        let mut allow_attr_literal = false;
         if attr.path == "repr" {
             if let Some(content) = attr.meta_item_list() {
-                is_repr_align = content.iter().any(|c| c.check_name("align"));
+                allow_attr_literal = content.iter().any(
+                    |c| c.check_name("align") || c.check_name("packed"));
             }
         }
 
@@ -1451,7 +1464,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             return
         }
 
-        if !is_repr_align {
+        if !allow_attr_literal {
             let meta = panictry!(attr.parse_meta(self.context.parse_sess));
             if contains_novel_literal(&meta) {
                 gate_feature_post!(&self, attr_literals, attr.span,
@@ -1535,6 +1548,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                                "the `#[repr(transparent)]` attribute \
                                                is experimental");
                         }
+                        if let Some((name, _)) = item.name_value_literal() {
+                            if name == "packed" {
+                                gate_feature_post!(&self, repr_packed, attr.span,
+                                                   "the `#[repr(packed(n))]` attribute \
+                                                   is experimental");
+                            }
+                        }
                     }
                 }
             }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ba6703b9c74..a0cd831a9ba 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1267,11 +1267,6 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
             ExprKind::Field(el, ident) => {
                 ExprKind::Field(folder.fold_expr(el), folder.fold_ident(ident))
             }
-            ExprKind::TupField(el, index) => {
-                ExprKind::TupField(folder.fold_expr(el),
-                             respan(folder.new_span(index.span),
-                                    folder.fold_usize(index.node)))
-            }
             ExprKind::Index(el, er) => {
                 ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er))
             }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index c456dc45d21..ad98e2a6b71 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -18,22 +18,24 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
-#![deny(warnings)]
 
-#![feature(unicode)]
+#![feature(unicode_internals)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
 #![feature(non_exhaustive)]
 #![feature(const_atomic_usize_new)]
 #![feature(rustc_attrs)]
 
+#![recursion_limit="256"]
+
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
 
 #[macro_use] extern crate bitflags;
+extern crate core;
 extern crate serialize;
 #[macro_use] extern crate log;
-extern crate std_unicode;
 pub extern crate rustc_errors as errors;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 152c4c31eb3..cb3323c7eca 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -15,7 +15,7 @@ use errors::{FatalError, DiagnosticBuilder};
 use parse::{token, ParseSess};
 use str::char_at;
 use symbol::{Symbol, keywords};
-use std_unicode::property::Pattern_White_Space;
+use core::unicode::property::Pattern_White_Space;
 
 use std::borrow::Cow;
 use std::char;
@@ -1781,7 +1781,6 @@ mod tests {
     use errors;
     use feature_gate::UnstableFeatures;
     use parse::token;
-    use std::cell::RefCell;
     use std::collections::HashSet;
     use std::io;
     use std::path::PathBuf;
@@ -1797,12 +1796,12 @@ mod tests {
             span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
             unstable_features: UnstableFeatures::from_environment(),
             config: CrateConfig::new(),
-            included_mod_stack: RefCell::new(Vec::new()),
+            included_mod_stack: Lock::new(Vec::new()),
             code_map: cm,
-            missing_fragment_specifiers: RefCell::new(HashSet::new()),
-            raw_identifier_spans: RefCell::new(Vec::new()),
+            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
-            non_modrs_mods: RefCell::new(vec![]),
+            non_modrs_mods: Lock::new(vec![]),
         }
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 428b3b136df..ff63c9a5c6d 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -23,7 +23,6 @@ use symbol::Symbol;
 use tokenstream::{TokenStream, TokenTree};
 use diagnostics::plugin::ErrorMap;
 
-use std::cell::RefCell;
 use std::collections::HashSet;
 use std::iter;
 use std::path::{Path, PathBuf};
@@ -46,17 +45,17 @@ pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
-    pub missing_fragment_specifiers: RefCell<HashSet<Span>>,
+    pub missing_fragment_specifiers: Lock<HashSet<Span>>,
     /// Places where raw identifiers were used. This is used for feature gating
     /// raw identifiers
-    pub raw_identifier_spans: RefCell<Vec<Span>>,
+    pub raw_identifier_spans: Lock<Vec<Span>>,
     /// The registered diagnostics codes
     pub registered_diagnostics: Lock<ErrorMap>,
     // Spans where a `mod foo;` statement was included in a non-mod.rs file.
     // These are used to issue errors if the non_modrs_mods feature is not enabled.
-    pub non_modrs_mods: RefCell<Vec<(ast::Ident, Span)>>,
+    pub non_modrs_mods: Lock<Vec<(ast::Ident, Span)>>,
     /// Used to determine and report recursive mod inclusions
-    included_mod_stack: RefCell<Vec<PathBuf>>,
+    included_mod_stack: Lock<Vec<PathBuf>>,
     code_map: Lrc<CodeMap>,
 }
 
@@ -75,12 +74,12 @@ impl ParseSess {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
             config: HashSet::new(),
-            missing_fragment_specifiers: RefCell::new(HashSet::new()),
-            raw_identifier_spans: RefCell::new(Vec::new()),
+            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
-            included_mod_stack: RefCell::new(vec![]),
+            included_mod_stack: Lock::new(vec![]),
             code_map,
-            non_modrs_mods: RefCell::new(vec![]),
+            non_modrs_mods: Lock::new(vec![]),
         }
     }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e6da5bcaa3a..a7a9ce74512 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -689,7 +689,7 @@ impl<'a> Parser<'a> {
                 .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
                 .chain(self.expected_tokens.iter().cloned())
                 .collect::<Vec<_>>();
-            expected.sort_by(|a, b| a.to_string().cmp(&b.to_string()));
+            expected.sort_by_cached_key(|x| x.to_string());
             expected.dedup();
             let expect = tokens_to_string(&expected[..]);
             let actual = self.this_token_to_string();
@@ -2144,10 +2144,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<usize>) -> ast::ExprKind {
-        ExprKind::TupField(expr, idx)
-    }
-
     pub fn mk_assign_op(&mut self, binop: ast::BinOp,
                         lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
         ExprKind::AssignOp(binop, lhs, rhs)
@@ -2605,35 +2601,11 @@ impl<'a> Parser<'a> {
                   token::Ident(..) => {
                     e = self.parse_dot_suffix(e, lo)?;
                   }
-                  token::Literal(token::Integer(index_ident), suf) => {
-                    let sp = self.span;
-
-                    // A tuple index may not have a suffix
-                    self.expect_no_suffix(sp, "tuple index", suf);
-
-                    let idx_span = self.span;
+                  token::Literal(token::Integer(name), _) => {
+                    let span = self.span;
                     self.bump();
-
-                    let invalid_msg = "invalid tuple or struct index";
-
-                    let index = index_ident.as_str().parse::<usize>().ok();
-                    match index {
-                        Some(n) => {
-                            if n.to_string() != index_ident.as_str() {
-                                let mut err = self.struct_span_err(self.prev_span, invalid_msg);
-                                err.span_suggestion(self.prev_span,
-                                                    "try simplifying the index",
-                                                    n.to_string());
-                                err.emit();
-                            }
-                            let field = self.mk_tup_field(e, respan(idx_span, n));
-                            e = self.mk_expr(lo.to(idx_span), field, ThinVec::new());
-                        }
-                        None => {
-                            let prev_span = self.prev_span;
-                            self.span_err(prev_span, invalid_msg);
-                        }
-                    }
+                    let field = ExprKind::Field(e, Ident::new(name, span));
+                    e = self.mk_expr(lo.to(span), field, ThinVec::new());
                   }
                   token::Literal(token::Float(n), _suf) => {
                     self.bump();
@@ -2830,7 +2802,48 @@ impl<'a> Parser<'a> {
                 let (span, e) = self.interpolated_or_expr_span(e)?;
                 (lo.to(span), ExprKind::Box(e))
             }
-            _ => return self.parse_dot_or_call_expr(Some(attrs))
+            token::Ident(..) if self.token.is_ident_named("not") => {
+                // `not` is just an ordinary identifier in Rust-the-language,
+                // but as `rustc`-the-compiler, we can issue clever diagnostics
+                // for confused users who really want to say `!`
+                let token_cannot_continue_expr = |t: &token::Token| match *t {
+                    // These tokens can start an expression after `!`, but
+                    // can't continue an expression after an ident
+                    token::Ident(ident, is_raw) => token::ident_can_begin_expr(ident, is_raw),
+                    token::Literal(..) | token::Pound => true,
+                    token::Interpolated(ref nt) => match nt.0 {
+                        token::NtIdent(..) | token::NtExpr(..) |
+                        token::NtBlock(..) | token::NtPath(..) => true,
+                        _ => false,
+                    },
+                    _ => false
+                };
+                let cannot_continue_expr = self.look_ahead(1, token_cannot_continue_expr);
+                if cannot_continue_expr {
+                    self.bump();
+                    // Emit the error ...
+                    let mut err = self.diagnostic()
+                        .struct_span_err(self.span,
+                                         &format!("unexpected {} after identifier",
+                                                  self.this_token_descr()));
+                    // span the `not` plus trailing whitespace to avoid
+                    // trailing whitespace after the `!` in our suggestion
+                    let to_replace = self.sess.codemap()
+                        .span_until_non_whitespace(lo.to(self.span));
+                    err.span_suggestion_short(to_replace,
+                                              "use `!` to perform logical negation",
+                                              "!".to_owned());
+                    err.emit();
+                    // —and recover! (just as if we were in the block
+                    // for the `token::Not` arm)
+                    let e = self.parse_prefix_expr(None);
+                    let (span, e) = self.interpolated_or_expr_span(e)?;
+                    (lo.to(span), self.mk_unary(UnOp::Not, e))
+                } else {
+                    return self.parse_dot_or_call_expr(Some(attrs));
+                }
+            }
+            _ => { return self.parse_dot_or_call_expr(Some(attrs)); }
         };
         return Ok(self.mk_expr(lo.to(hi), ex, attrs));
     }
@@ -4486,6 +4499,11 @@ impl<'a> Parser<'a> {
             // Which is valid in other languages, but not Rust.
             match self.parse_stmt_without_recovery(false) {
                 Ok(Some(stmt)) => {
+                    if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) {
+                        // if the next token is an open brace (e.g., `if a b {`), the place-
+                        // inside-a-block suggestion would be more likely wrong than right
+                        return Err(e);
+                    }
                     let mut stmt_span = stmt.span;
                     // expand the span to include the semicolon, if it exists
                     if self.eat(&token::Semi) {
@@ -7012,7 +7030,7 @@ impl<'a> Parser<'a> {
             match self.token {
                 token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
                     self.bump(); // `_`
-                    Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
+                    Ok(Some(Ident::new(ident.name.gensymed(), ident.span)))
                 }
                 _ => self.parse_ident().map(Some),
             }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 6544619af9c..8da79f92768 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -25,9 +25,8 @@ use syntax_pos::{self, Span, FileName};
 use tokenstream::{TokenStream, TokenTree};
 use tokenstream;
 
-use std::cell::Cell;
 use std::{cmp, fmt};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, Lock};
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
 pub enum BinOpToken {
@@ -91,7 +90,7 @@ impl Lit {
     }
 }
 
-fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
+pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
     let ident_token: Token = Ident(ident, is_raw);
 
     !ident_token.is_reserved_ident() ||
@@ -348,6 +347,15 @@ impl Token {
         self.lifetime().is_some()
     }
 
+    /// Returns `true` if the token is a identifier whose name is the given
+    /// string slice.
+    pub fn is_ident_named(&self, name: &str) -> bool {
+        match self.ident() {
+            Some((ident, _)) => ident.name.as_str() == name,
+            None => false
+        }
+    }
+
     /// Returns `true` if the token is a documentation comment.
     pub fn is_doc_comment(&self) -> bool {
         match *self {
@@ -618,15 +626,8 @@ pub fn is_op(tok: &Token) -> bool {
     }
 }
 
-pub struct LazyTokenStream(Cell<Option<TokenStream>>);
-
-impl Clone for LazyTokenStream {
-    fn clone(&self) -> Self {
-        let opt_stream = self.0.take();
-        self.0.set(opt_stream.clone());
-        LazyTokenStream(Cell::new(opt_stream))
-    }
-}
+#[derive(Clone)]
+pub struct LazyTokenStream(Lock<Option<TokenStream>>);
 
 impl cmp::Eq for LazyTokenStream {}
 impl PartialEq for LazyTokenStream {
@@ -643,15 +644,14 @@ impl fmt::Debug for LazyTokenStream {
 
 impl LazyTokenStream {
     pub fn new() -> Self {
-        LazyTokenStream(Cell::new(None))
+        LazyTokenStream(Lock::new(None))
     }
 
     pub fn force<F: FnOnce() -> TokenStream>(&self, f: F) -> TokenStream {
-        let mut opt_stream = self.0.take();
+        let mut opt_stream = self.0.lock();
         if opt_stream.is_none() {
-            opt_stream = Some(f());
+            *opt_stream = Some(f());
         }
-        self.0.set(opt_stream.clone());
         opt_stream.clone().unwrap()
     }
 }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8168db19058..3741850b8a9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1966,8 +1966,7 @@ impl<'a> State<'a> {
                        args: &[P<ast::Expr>]) -> io::Result<()> {
         let prec =
             match func.node {
-                ast::ExprKind::Field(..) |
-                ast::ExprKind::TupField(..) => parser::PREC_FORCE_PAREN,
+                ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
                 _ => parser::PREC_POSTFIX,
             };
 
@@ -2203,11 +2202,6 @@ impl<'a> State<'a> {
                 self.s.word(".")?;
                 self.print_ident(ident)?;
             }
-            ast::ExprKind::TupField(ref expr, id) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
-                self.s.word(".")?;
-                self.print_usize(id.node)?;
-            }
             ast::ExprKind::Index(ref expr, ref index) => {
                 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
                 self.s.word("[")?;
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index 4770273e8c4..524f9f127f5 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -251,7 +251,6 @@ pub enum ExprPrecedence {
     Call,
     MethodCall,
     Field,
-    TupField,
     Index,
     Try,
     InlineAsm,
@@ -320,7 +319,6 @@ impl ExprPrecedence {
             ExprPrecedence::Call |
             ExprPrecedence::MethodCall |
             ExprPrecedence::Field |
-            ExprPrecedence::TupField |
             ExprPrecedence::Index |
             ExprPrecedence::Try |
             ExprPrecedence::InlineAsm |
@@ -365,7 +363,6 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
         ast::ExprKind::Cast(ref x, _) |
         ast::ExprKind::Type(ref x, _) |
         ast::ExprKind::Field(ref x, _) |
-        ast::ExprKind::TupField(ref x, _) |
         ast::ExprKind::Index(ref x, _) => {
             // &X { y: 1 }, X { y: 1 }.y
             contains_exterior_struct_lit(&x)
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index fdb3e2c5f31..8743840e443 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -749,9 +749,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_ident(ident);
         }
-        ExprKind::TupField(ref subexpression, _) => {
-            visitor.visit_expr(subexpression);
-        }
         ExprKind::Index(ref main_expression, ref index_expression) => {
             visitor.visit_expr(main_expression);
             visitor.visit_expr(index_expression)
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 4126ce79f35..66053e037e1 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -413,8 +413,12 @@ impl<'a> TraitDef<'a> {
         match *item {
             Annotatable::Item(ref item) => {
                 let is_packed = item.attrs.iter().any(|attr| {
-                    attr::find_repr_attrs(&cx.parse_sess.span_diagnostic, attr)
-                        .contains(&attr::ReprPacked)
+                    for r in attr::find_repr_attrs(&cx.parse_sess.span_diagnostic, attr) {
+                        if let attr::ReprPacked(_) = r {
+                            return true;
+                        }
+                    }
+                    false
                 });
                 let has_no_type_params = match item.node {
                     ast::ItemKind::Struct(_, ref generics) |
@@ -831,7 +835,7 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &
     for a in type_attrs {
         for r in &attr::find_repr_attrs(diagnostic, a) {
             repr_type_name = match *r {
-                attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) | attr::ReprTransparent =>
+                attr::ReprPacked(_) | attr::ReprSimd | attr::ReprAlign(_) | attr::ReprTransparent =>
                     continue,
 
                 attr::ReprC => "i32",
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 249a64b353f..97e34c554d1 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -13,7 +13,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(proc_macro_internals)]
 #![feature(decl_macro)]
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index c180563450f..8cb5776fdeb 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -432,6 +432,7 @@ pub enum ExpnFormat {
 pub enum CompilerDesugaringKind {
     DotFill,
     QuestionMark,
+    Catch,
 }
 
 impl CompilerDesugaringKind {
@@ -440,6 +441,7 @@ impl CompilerDesugaringKind {
         let s = match *self {
             DotFill => "...",
             QuestionMark => "?",
+            Catch => "do catch",
         };
         Symbol::intern(s)
     }
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 33428eb271a..9a7d1fd8ee6 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -17,7 +17,6 @@
 #![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/")]
-#![deny(warnings)]
 
 #![feature(const_fn)]
 #![feature(custom_attribute)]
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index ad0e582b1c3..a012f4e776f 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -46,7 +46,6 @@
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
 #![deny(missing_docs)]
-#![deny(warnings)]
 
 #![cfg_attr(windows, feature(libc))]
 // Handle rustfmt skips
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index b8be1aeff17..9291eaa910b 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -31,7 +31,6 @@
 #![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/", test(attr(deny(warnings))))]
-#![deny(warnings)]
 #![feature(asm)]
 #![feature(fnbox)]
 #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs
index 5347c781218..2b3c19c067e 100644
--- a/src/libunwind/lib.rs
+++ b/src/libunwind/lib.rs
@@ -10,7 +10,6 @@
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
-#![deny(warnings)]
 
 #![feature(cfg_target_vendor)]
 #![feature(link_cfg)]
diff --git a/src/llvm b/src/llvm
-Subproject 6ceaaa4b0176a200e4bbd347d6a991ab6c776ed
+Subproject 7243155b1c3da0a980c868a87adebf00e0b3398
diff --git a/src/rustc/dlmalloc_shim/Cargo.toml b/src/rustc/dlmalloc_shim/Cargo.toml
index d2fe159d806..b6f8550829f 100644
--- a/src/rustc/dlmalloc_shim/Cargo.toml
+++ b/src/rustc/dlmalloc_shim/Cargo.toml
@@ -12,4 +12,3 @@ doc = false
 [dependencies]
 core = { path = "../../libcore" }
 compiler_builtins = { path = "../../rustc/compiler_builtins_shim" }
-alloc = { path = "../../liballoc" }
diff --git a/src/rustc/rustc.rs b/src/rustc/rustc.rs
index 9fa33f911a1..a888838ce43 100644
--- a/src/rustc/rustc.rs
+++ b/src/rustc/rustc.rs
@@ -13,6 +13,7 @@
 
 // Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
 // for the rationale.
+#[allow(unused_attributes)]
 #[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
 // We only build for msvc and gnu now, but we use a exhaustive condition here
 // so we can expect either the stack size to be set or the build fails.
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
index c4c0f1ab6e6..c3fc3e5452c 100644
--- a/src/rustllvm/llvm-rebuild-trigger
+++ b/src/rustllvm/llvm-rebuild-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2018-03-10
+2018-04-05
diff --git a/src/test/codegen/link_section.rs b/src/test/codegen/link_section.rs
index 9c56a316b34..415ee6eb7ea 100644
--- a/src/test/codegen/link_section.rs
+++ b/src/test/codegen/link_section.rs
@@ -15,8 +15,14 @@
 // CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
 #[no_mangle]
 #[link_section = ".test_one"]
+#[cfg(target_endian = "little")]
 pub static VAR1: u32 = 1;
 
+#[no_mangle]
+#[link_section = ".test_one"]
+#[cfg(target_endian = "big")]
+pub static VAR1: u32 = 0x01000000;
+
 pub enum E {
     A(u32),
     B(f32)
diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs
index 022f581278c..0693eae7d78 100644
--- a/src/test/codegen/packed.rs
+++ b/src/test/codegen/packed.rs
@@ -11,16 +11,23 @@
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
+#![feature(repr_packed)]
 
 #[repr(packed)]
-pub struct Packed {
+pub struct Packed1 {
     dealign: u8,
     data: u32
 }
 
-// CHECK-LABEL: @write_pkd
+#[repr(packed(2))]
+pub struct Packed2 {
+    dealign: u8,
+    data: u32
+}
+
+// CHECK-LABEL: @write_pkd1
 #[no_mangle]
-pub fn write_pkd(pkd: &mut Packed) -> u32 {
+pub fn write_pkd1(pkd: &mut Packed1) -> u32 {
 // CHECK: %{{.*}} = load i32, i32* %{{.*}}, align 1
 // CHECK: store i32 42, i32* %{{.*}}, align 1
     let result = pkd.data;
@@ -28,43 +35,94 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
     result
 }
 
+// CHECK-LABEL: @write_pkd2
+#[no_mangle]
+pub fn write_pkd2(pkd: &mut Packed2) -> u32 {
+// CHECK: %{{.*}} = load i32, i32* %{{.*}}, align 2
+// CHECK: store i32 42, i32* %{{.*}}, align 2
+    let result = pkd.data;
+    pkd.data = 42;
+    result
+}
+
 pub struct Array([i32; 8]);
 #[repr(packed)]
-pub struct BigPacked {
+pub struct BigPacked1 {
+    dealign: u8,
+    data: Array
+}
+
+#[repr(packed(2))]
+pub struct BigPacked2 {
     dealign: u8,
     data: Array
 }
 
-// CHECK-LABEL: @call_pkd
+// CHECK-LABEL: @call_pkd1
 #[no_mangle]
-pub fn call_pkd(f: fn() -> Array) -> BigPacked {
+pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
 // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
 // CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
-    BigPacked { dealign: 0, data: f() }
+    BigPacked1 { dealign: 0, data: f() }
+}
+
+// CHECK-LABEL: @call_pkd2
+#[no_mangle]
+pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
+// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
+// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 2, i1 false)
+    // check that calls whose destination is a field of a packed struct
+    // go through an alloca rather than calling the function with an
+    // unaligned destination.
+    BigPacked2 { dealign: 0, data: f() }
 }
 
 #[repr(packed)]
 #[derive(Copy, Clone)]
-pub struct PackedPair(u8, u32);
+pub struct Packed1Pair(u8, u32);
 
-// CHECK-LABEL: @pkd_pair
+#[repr(packed(2))]
+#[derive(Copy, Clone)]
+pub struct Packed2Pair(u8, u32);
+
+// CHECK-LABEL: @pkd1_pair
 #[no_mangle]
-pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) {
+pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
 // CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 5, i32 1, i1 false)
     *pair2 = *pair1;
 }
 
+// CHECK-LABEL: @pkd2_pair
+#[no_mangle]
+pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 6, i32 2, i1 false)
+    *pair2 = *pair1;
+}
+
 #[repr(packed)]
 #[derive(Copy, Clone)]
-pub struct PackedNestedPair((u32, u32));
+pub struct Packed1NestedPair((u32, u32));
+
+#[repr(packed(2))]
+#[derive(Copy, Clone)]
+pub struct Packed2NestedPair((u32, u32));
 
-// CHECK-LABEL: @pkd_nested_pair
+// CHECK-LABEL: @pkd1_nested_pair
 #[no_mangle]
-pub fn pkd_nested_pair(pair1: &mut PackedNestedPair, pair2: &mut PackedNestedPair) {
+pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
 // CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 1, i1 false)
     *pair2 = *pair1;
 }
+
+// CHECK-LABEL: @pkd2_nested_pair
+#[no_mangle]
+pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 2, i1 false)
+    *pair2 = *pair1;
+}
+
diff --git a/src/test/compile-fail/allocator/not-an-allocator.rs b/src/test/compile-fail/allocator/not-an-allocator.rs
index e4301435063..1479d0b6264 100644
--- a/src/test/compile-fail/allocator/not-an-allocator.rs
+++ b/src/test/compile-fail/allocator/not-an-allocator.rs
@@ -12,15 +12,10 @@
 
 #[global_allocator]
 static A: usize = 0;
-//~^ the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
-//~| the trait bound `&usize:
+//~^ the trait bound `usize:
+//~| the trait bound `usize:
+//~| the trait bound `usize:
+//~| the trait bound `usize:
+//~| the trait bound `usize:
 
 fn main() {}
diff --git a/src/test/compile-fail/borrowck/borrowck-issue-14498.rs b/src/test/compile-fail/borrowck/borrowck-issue-14498.rs
index 8a09ab3fd06..fbdd013024d 100644
--- a/src/test/compile-fail/borrowck/borrowck-issue-14498.rs
+++ b/src/test/compile-fail/borrowck/borrowck-issue-14498.rs
@@ -27,7 +27,7 @@ fn indirect_write_to_imm_box() {
     let y: Box<_> = box &mut x;
     let p = &y;
     ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
-              //[mir]~^ ERROR cannot assign to immutable item `***p`
+              //[mir]~^ ERROR cannot assign to data in a `&` reference
     drop(p);
 }
 
diff --git a/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs b/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs
index a214e3c126e..eec7df84c82 100644
--- a/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs
+++ b/src/test/compile-fail/borrowck/borrowck-uninit-field-access.rs
@@ -36,7 +36,7 @@ fn main() {
 
     let mut line1 = Line::default();
     let _moved = line1.origin;
-    let _ = line1.origin.x + 1; //[ast]~ ERROR use of collaterally moved value: `line1.origin.x`
+    let _ = line1.origin.x + 1; //[ast]~ ERROR use of moved value: `line1.origin.x`
                                 //[mir]~^ [E0382]
 
     let mut line2 = Line::default();
diff --git a/src/test/compile-fail/catch-bad-lifetime.rs b/src/test/compile-fail/catch-bad-lifetime.rs
index f24561b8887..f332ffd4494 100644
--- a/src/test/compile-fail/catch-bad-lifetime.rs
+++ b/src/test/compile-fail/catch-bad-lifetime.rs
@@ -21,7 +21,6 @@ pub fn main() {
             //~^ ERROR `my_string` does not live long enough
             Err(my_str) ?;
             Err("") ?;
-            Ok(())
         };
     }
 
@@ -32,7 +31,6 @@ pub fn main() {
         let mut j: Result<(), &mut i32> = do catch {
             Err(k) ?;
             i = 10; //~ ERROR cannot assign to `i` because it is borrowed
-            Ok(())
         };
         ::std::mem::drop(k); //~ ERROR use of moved value: `k`
         i = 40; //~ ERROR cannot assign to `i` because it is borrowed
diff --git a/src/test/compile-fail/catch-bad-type.rs b/src/test/compile-fail/catch-bad-type.rs
index cff9f508275..b369847699b 100644
--- a/src/test/compile-fail/catch-bad-type.rs
+++ b/src/test/compile-fail/catch-bad-type.rs
@@ -11,11 +11,18 @@
 #![feature(catch_expr)]
 
 pub fn main() {
-    let res: Result<i32, i32> = do catch {
+    let res: Result<u32, i32> = do catch {
         Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` is not satisfied
-        Ok(5)
+        5
     };
+
     let res: Result<i32, i32> = do catch {
-        Ok("") //~ mismatched types
+        "" //~ ERROR type mismatch
     };
+
+    let res: Result<i32, i32> = do catch { }; //~ ERROR type mismatch
+
+    let res: () = do catch { }; //~ the trait bound `(): std::ops::Try` is not satisfied
+
+    let res: i32 = do catch { 5 }; //~ ERROR the trait bound `i32: std::ops::Try` is not satisfied
 }
diff --git a/src/test/compile-fail/catch-maybe-bad-lifetime.rs b/src/test/compile-fail/catch-maybe-bad-lifetime.rs
index b783a3dd786..faefb5ef18a 100644
--- a/src/test/compile-fail/catch-maybe-bad-lifetime.rs
+++ b/src/test/compile-fail/catch-maybe-bad-lifetime.rs
@@ -17,7 +17,7 @@ pub fn main() {
         let mut i = 222;
         let x: Result<&i32, ()> = do catch {
             Err(())?;
-            Ok(&i)
+            &i
         };
         x.ok().cloned();
         i = 0; //~ ERROR cannot assign to `i` because it is borrowed
@@ -29,7 +29,6 @@ pub fn main() {
         let _y: Result<(), ()> = do catch {
             Err(())?;
             ::std::mem::drop(x);
-            Ok(())
         };
         println!("{}", x); //~ ERROR use of moved value: `x`
     }
@@ -42,7 +41,6 @@ pub fn main() {
         let x: Result<(), ()> = do catch {
             Err(())?;
             j = &i;
-            Ok(())
         };
         i = 0; //~ ERROR cannot assign to `i` because it is borrowed
         let _ = i;
diff --git a/src/test/compile-fail/catch-opt-init.rs b/src/test/compile-fail/catch-opt-init.rs
index 48284b4cb90..0c41102e3be 100644
--- a/src/test/compile-fail/catch-opt-init.rs
+++ b/src/test/compile-fail/catch-opt-init.rs
@@ -19,7 +19,6 @@ pub fn main() {
         cfg_res = 5;
         Ok::<(), ()>(())?;
         use_val(cfg_res);
-        Ok(())
     };
     assert_eq!(cfg_res, 5); //~ ERROR use of possibly uninitialized variable
 }
diff --git a/src/test/compile-fail/conflicting-repr-hints.rs b/src/test/compile-fail/conflicting-repr-hints.rs
index 8acc8b7bb1e..426f60c6b09 100644
--- a/src/test/compile-fail/conflicting-repr-hints.rs
+++ b/src/test/compile-fail/conflicting-repr-hints.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![allow(dead_code)]
+#![feature(repr_packed)]
 
 #[repr(C)]
 enum A { A }
@@ -36,6 +37,16 @@ struct G(i32); //~ ERROR type has conflicting packed and align representation hi
 #[repr(packed)]
 struct H(i32); //~ ERROR type has conflicting packed and align representation hints
 
+#[repr(packed, packed(2))]
+struct I(i32); //~ ERROR type has conflicting packed representation hints
+
+#[repr(packed(2))]
+#[repr(packed)]
+struct J(i32); //~ ERROR type has conflicting packed representation hints
+
+#[repr(packed, packed(1))]
+struct K(i32);
+
 #[repr(packed, align(8))]
 union X { //~ ERROR type has conflicting packed and align representation hints
     i: i32
diff --git a/src/test/compile-fail/issue-19244-1.rs b/src/test/compile-fail/issue-19244-1.rs
index 0fa1a154772..df34aab4b8f 100644
--- a/src/test/compile-fail/issue-19244-1.rs
+++ b/src/test/compile-fail/issue-19244-1.rs
@@ -12,5 +12,5 @@ const TUP: (usize,) = (42,);
 
 fn main() {
     let a: [isize; TUP.1];
-    //~^ ERROR attempted out-of-bounds tuple index
+    //~^ ERROR no field `1` on type `(usize,)`
 }
diff --git a/src/test/compile-fail/lint-non-uppercase-statics.rs b/src/test/compile-fail/lint-non-uppercase-statics.rs
index 463a93612ca..84cc24a0010 100644
--- a/src/test/compile-fail/lint-non-uppercase-statics.rs
+++ b/src/test/compile-fail/lint-non-uppercase-statics.rs
@@ -16,4 +16,7 @@ static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case
 static mut bar: isize = 1;
         //~^ ERROR static variable `bar` should have an upper case name such as `BAR`
 
+#[no_mangle]
+pub static extern_foo: isize = 1; // OK, because #[no_mangle] supersedes the warning
+
 fn main() { }
diff --git a/src/test/compile-fail/outlives-associated-types.rs b/src/test/compile-fail/outlives-associated-types.rs
index 778394c9fc8..5c392223f88 100644
--- a/src/test/compile-fail/outlives-associated-types.rs
+++ b/src/test/compile-fail/outlives-associated-types.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
+
 // Test that the outlives computation runs for now...
 
 #![feature(rustc_attrs)]
@@ -16,7 +18,7 @@
 // https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md#example-1-a-reference
 
 #[rustc_outlives]
-struct Direct<'a, T> { //~ ERROR 19:1: 21:2: [] [E0640]
+struct Direct<'a, T> { //~ ERROR 21:1: 23:2: [Binder(OutlivesPredicate(T, ReEarlyBound(0, 'a)))] [E0640]
     field: &'a T
 }
 
diff --git a/src/test/compile-fail/single-primitive-inherent-impl.rs b/src/test/compile-fail/single-primitive-inherent-impl.rs
index 5ceb870528a..365387c3e5e 100644
--- a/src/test/compile-fail/single-primitive-inherent-impl.rs
+++ b/src/test/compile-fail/single-primitive-inherent-impl.rs
@@ -15,9 +15,9 @@
 #![no_std]
 
 // OK
-#[lang = "char"]
-impl char {}
+#[lang = "str"]
+impl str {}
 
-impl char {
-//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive
+impl str {
+//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
 }
diff --git a/src/test/compile-fail/struct-field-privacy.rs b/src/test/compile-fail/struct-field-privacy.rs
index 5b2e04e25a9..f487ef62aa4 100644
--- a/src/test/compile-fail/struct-field-privacy.rs
+++ b/src/test/compile-fail/struct-field-privacy.rs
@@ -42,7 +42,7 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B, z: inner::Z) {
     e.b; //~ ERROR: field `b` of struct `xc::B` is private
 
     z.0;
-    z.1; //~ ERROR: field `1` of tuple-struct `inner::Z` is private
+    z.1; //~ ERROR: field `1` of struct `inner::Z` is private
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/tuple-index-out-of-bounds.rs b/src/test/compile-fail/tuple-index-out-of-bounds.rs
index 4597cf3d350..35b843676b4 100644
--- a/src/test/compile-fail/tuple-index-out-of-bounds.rs
+++ b/src/test/compile-fail/tuple-index-out-of-bounds.rs
@@ -15,10 +15,10 @@ fn main() {
     origin.0;
     origin.1;
     origin.2;
-    //~^ ERROR attempted out-of-bounds tuple index `2` on type `Point`
+    //~^ ERROR no field `2` on type `Point`
     let tuple = (0, 0);
     tuple.0;
     tuple.1;
     tuple.2;
-    //~^ ERROR attempted out-of-bounds tuple index `2` on type `({integer}, {integer})`
+    //~^ ERROR no field `2` on type `({integer}, {integer})`
 }
diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs
index 83425a72f45..9c939d0d2fb 100644
--- a/src/test/mir-opt/end_region_cyclic.rs
+++ b/src/test/mir-opt/end_region_cyclic.rs
@@ -40,29 +40,29 @@ fn query() -> bool { true }
 
 // END RUST SOURCE
 // START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> () {
+// fn main() -> (){
 //     let mut _0: ();
 //     scope 1 {
-//         let _2: S<'35_0rs>;
+//         let _2: S<'36_0rs>;
+//     }
+//     scope 2 {
 //     }
-//     ...
 //     let mut _1: ();
-//     let mut _3: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
-//     let mut _4: std::option::Option<&'35_0rs S<'35_0rs>>;
+//     let mut _3: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>;
+//     let mut _4: std::option::Option<&'36_0rs S<'36_0rs>>;
 //     let mut _5: ();
-//     let mut _6: &'16s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
-//     let mut _7: std::option::Option<&'35_0rs S<'35_0rs>>;
-//     let mut _8: &'35_0rs S<'35_0rs>;
-//     let mut _9: &'35_0rs S<'35_0rs>;
+//     let mut _6: &'17s std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>;
+//     let mut _7: std::option::Option<&'36_0rs S<'36_0rs>>;
+//     let mut _8: &'36_0rs S<'36_0rs>;
+//     let mut _9: &'36_0rs S<'36_0rs>;
 //     let mut _10: ();
 //     let mut _11: bool;
 //     let mut _12: !;
 //     let mut _13: ();
-//     let mut _14: &'33s std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>;
-//     let mut _15: std::option::Option<&'35_0rs S<'35_0rs>>;
-//     let mut _16: &'35_0rs S<'35_0rs>;
-//     let mut _17: &'35_0rs S<'35_0rs>;
-//
+//     let mut _14: &'34s std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>;
+//     let mut _15: std::option::Option<&'36_0rs S<'36_0rs>>;
+//     let mut _16: &'36_0rs S<'36_0rs>;
+//     let mut _17: &'36_0rs S<'36_0rs>;
 //     bb0: {
 //         goto -> bb1;
 //     }
@@ -73,7 +73,7 @@ fn query() -> bool { true }
 //         StorageLive(_2);
 //         StorageLive(_3);
 //         StorageLive(_4);
-//         _4 = std::option::Option<&'35_0rs S<'35_0rs>>::None;
+//         _4 = std::option::Option<&'36_0rs S<'36_0rs>>::None;
 //         _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
 //     }
 //     bb3: {
@@ -81,21 +81,21 @@ fn query() -> bool { true }
 //     }
 //     bb4: {
 //         StorageDead(_4);
-//         _2 = S<'35_0rs> { r: move _3 };
+//         _2 = S<'36_0rs> { r: move _3 };
 //         StorageDead(_3);
 //         StorageLive(_6);
-//         _6 = &'16s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
+//         _6 = &'17s (_2.0: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>);
 //         StorageLive(_7);
 //         StorageLive(_8);
 //         StorageLive(_9);
-//         _9 = &'35_0rs _2;
-//         _8 = &'35_0rs (*_9);
-//         _7 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _8,);
+//         _9 = &'36_0rs _2;
+//         _8 = &'36_0rs (*_9);
+//         _7 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _8,);
 //         StorageDead(_8);
 //         _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb5, unwind: bb3];
 //     }
 //     bb5: {
-//         EndRegion('16s);
+//         EndRegion('17s);
 //         StorageDead(_7);
 //         StorageDead(_6);
 //         StorageDead(_9);
@@ -108,7 +108,7 @@ fn query() -> bool { true }
 //     bb7: {
 //         _0 = ();
 //         StorageDead(_11);
-//         EndRegion('35_0rs);
+//         EndRegion('36_0rs);
 //         StorageDead(_2);
 //         return;
 //     }
@@ -116,23 +116,23 @@ fn query() -> bool { true }
 //         _10 = ();
 //         StorageDead(_11);
 //         StorageLive(_14);
-//         _14 = &'33s (_2.0: std::cell::Cell<std::option::Option<&'35_0rs S<'35_0rs>>>);
+//         _14 = &'34s (_2.0: std::cell::Cell<std::option::Option<&'36_0rs S<'36_0rs>>>);
 //         StorageLive(_15);
 //         StorageLive(_16);
 //         StorageLive(_17);
-//         _17 = &'35_0rs _2;
-//         _16 = &'35_0rs (*_17);
-//         _15 = std::option::Option<&'35_0rs S<'35_0rs>>::Some(move _16,);
+//         _17 = &'36_0rs _2;
+//         _16 = &'36_0rs (*_17);
+//         _15 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _16,);
 //         StorageDead(_16);
 //         _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
 //     }
 //     bb9: {
-//         EndRegion('33s);
+//         EndRegion('34s);
 //         StorageDead(_15);
 //         StorageDead(_14);
 //         StorageDead(_17);
 //         _1 = ();
-//         EndRegion('35_0rs);
+//         EndRegion('36_0rs);
 //         StorageDead(_2);
 //         goto -> bb1;
 //     }
diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs
index 80e75fcee8a..79645bd3600 100644
--- a/src/test/mir-opt/validate_3.rs
+++ b/src/test/mir-opt/validate_3.rs
@@ -29,34 +29,46 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.EraseRegions.after.mir
-// fn main() -> () {
-//     ...
+// fn main() -> (){
+//     let mut _0: ();
+//     scope 1 {
+//         let _1: Test;
+//         scope 3 {
+//             let _2: &ReErased Test;
+//         }
+//         scope 4 {
+//         }
+//     }
+//     scope 2 {
+//     }
+//     let mut _3: ();
+//     let mut _4: &ReErased i32;
 //     let mut _5: &ReErased i32;
 //     bb0: {
 //         StorageLive(_1);
 //         _1 = Test { x: const 0i32 };
 //         StorageLive(_2);
-//         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 }))), [_1: Test]);
+//         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 }))), [_1: Test]);
 //         _2 = &ReErased _1;
-//         Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]);
+//         Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]);
 //         StorageLive(_4);
 //         StorageLive(_5);
-//         Validate(Suspend(ReScope(Node(ItemLocalId(17)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]);
+//         Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]);
 //         _5 = &ReErased ((*_2).0: i32);
-//         Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(17))) (imm)]);
-//         Validate(Suspend(ReScope(Node(ItemLocalId(17)))), [(*_5): i32/ReScope(Node(ItemLocalId(17))) (imm)]);
+//         Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
+//         Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
 //         _4 = &ReErased (*_5);
-//         Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(17))) (imm)]);
-//         Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(17))) i32]);
+//         Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(18))) (imm)]);
+//         Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(18))) i32]);
 //         _3 = const foo(move _4) -> bb1;
 //     }
 //     bb1: {
 //         Validate(Acquire, [_3: ()]);
-//         EndRegion(ReScope(Node(ItemLocalId(17))));
+//         EndRegion(ReScope(Node(ItemLocalId(18))));
 //         StorageDead(_4);
 //         StorageDead(_5);
 //         _0 = ();
-//         EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })));
+//         EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })));
 //         StorageDead(_2);
 //         StorageDead(_1);
 //         return;
diff --git a/src/test/run-make-fulldeps/std-core-cycle/bar.rs b/src/test/run-make-fulldeps/std-core-cycle/bar.rs
index 6def5b6f5e1..62fd2ade1ca 100644
--- a/src/test/run-make-fulldeps/std-core-cycle/bar.rs
+++ b/src/test/run-make-fulldeps/std-core-cycle/bar.rs
@@ -11,16 +11,16 @@
 #![feature(allocator_api)]
 #![crate_type = "rlib"]
 
-use std::heap::*;
+use std::alloc::*;
 
 pub struct A;
 
-unsafe impl<'a> Alloc for &'a A {
-    unsafe fn alloc(&mut self, _: Layout) -> Result<*mut u8, AllocErr> {
+unsafe impl GlobalAlloc for A {
+    unsafe fn alloc(&self, _: Layout) -> *mut Opaque {
         loop {}
     }
 
-    unsafe fn dealloc(&mut self, _ptr: *mut u8, _: Layout) {
+    unsafe fn dealloc(&self, _ptr: *mut Opaque, _: Layout) {
         loop {}
     }
 }
diff --git a/src/test/run-pass/align-struct.rs b/src/test/run-pass/align-struct.rs
index dea8462705f..2b6a151574a 100644
--- a/src/test/run-pass/align-struct.rs
+++ b/src/test/run-pass/align-struct.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 #![feature(box_syntax)]
+#![feature(repr_packed)]
 
 use std::mem;
 
@@ -60,6 +61,18 @@ struct AlignContainsPacked {
     b: Packed,
 }
 
+#[repr(C, packed(4))]
+struct Packed4C {
+    a: u32,
+    b: u64,
+}
+
+#[repr(align(16))]
+struct AlignContainsPacked4C {
+    a: Packed4C,
+    b: u64,
+}
+
 // The align limit was originally smaller (2^15).
 // Check that it works with big numbers.
 #[repr(align(0x10000))]
@@ -218,6 +231,15 @@ pub fn main() {
     assert_eq!(mem::size_of_val(&a), 16);
     assert!(is_aligned_to(&a, 16));
 
+    assert_eq!(mem::align_of::<AlignContainsPacked4C>(), 16);
+    assert_eq!(mem::size_of::<AlignContainsPacked4C>(), 32);
+    let a = AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }, b: 3 };
+    assert_eq!(mem::align_of_val(&a), 16);
+    assert_eq!(mem::align_of_val(&a.a), 4);
+    assert_eq!(mem::align_of_val(&a.b), mem::align_of::<u64>());
+    assert_eq!(mem::size_of_val(&a), 32);
+    assert!(is_aligned_to(&a, 16));
+
     let mut large = box AlignLarge {
         stuff: [0; 0x10000],
     };
diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs
index eaa5bc90805..38b8ab50cc7 100644
--- a/src/test/run-pass/allocator-alloc-one.rs
+++ b/src/test/run-pass/allocator-alloc-one.rs
@@ -14,8 +14,8 @@ use std::heap::{Heap, Alloc};
 
 fn main() {
     unsafe {
-        let ptr = Heap.alloc_one::<i32>().unwrap_or_else(|e| {
-            Heap.oom(e)
+        let ptr = Heap.alloc_one::<i32>().unwrap_or_else(|_| {
+            Heap.oom()
         });
         *ptr.as_ptr() = 4;
         assert_eq!(*ptr.as_ptr(), 4);
diff --git a/src/test/run-pass/allocator/auxiliary/custom.rs b/src/test/run-pass/allocator/auxiliary/custom.rs
index 8f4fbcd5ab1..e6a2e22983b 100644
--- a/src/test/run-pass/allocator/auxiliary/custom.rs
+++ b/src/test/run-pass/allocator/auxiliary/custom.rs
@@ -13,18 +13,18 @@
 #![feature(heap_api, allocator_api)]
 #![crate_type = "rlib"]
 
-use std::heap::{Alloc, System, AllocErr, Layout};
+use std::heap::{GlobalAlloc, System, Layout, Opaque};
 use std::sync::atomic::{AtomicUsize, Ordering};
 
 pub struct A(pub AtomicUsize);
 
-unsafe impl<'a> Alloc for &'a A {
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
+unsafe impl GlobalAlloc for A {
+    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
         self.0.fetch_add(1, Ordering::SeqCst);
         System.alloc(layout)
     }
 
-    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
+    unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
         self.0.fetch_add(1, Ordering::SeqCst);
         System.dealloc(ptr, layout)
     }
diff --git a/src/test/run-pass/allocator/custom.rs b/src/test/run-pass/allocator/custom.rs
index 22081678fb9..415d39a593e 100644
--- a/src/test/run-pass/allocator/custom.rs
+++ b/src/test/run-pass/allocator/custom.rs
@@ -15,20 +15,20 @@
 
 extern crate helper;
 
-use std::heap::{Heap, Alloc, System, Layout, AllocErr};
+use std::alloc::{self, Global, Alloc, System, Layout, Opaque};
 use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 
 static HITS: AtomicUsize = ATOMIC_USIZE_INIT;
 
 struct A;
 
-unsafe impl<'a> Alloc for &'a A {
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
+unsafe impl alloc::GlobalAlloc for A {
+    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
         HITS.fetch_add(1, Ordering::SeqCst);
         System.alloc(layout)
     }
 
-    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
+    unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
         HITS.fetch_add(1, Ordering::SeqCst);
         System.dealloc(ptr, layout)
     }
@@ -45,10 +45,10 @@ fn main() {
     unsafe {
         let layout = Layout::from_size_align(4, 2).unwrap();
 
-        let ptr = Heap.alloc(layout.clone()).unwrap();
+        let ptr = Global.alloc(layout.clone()).unwrap();
         helper::work_with(&ptr);
         assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
-        Heap.dealloc(ptr, layout.clone());
+        Global.dealloc(ptr, layout.clone());
         assert_eq!(HITS.load(Ordering::SeqCst), n + 2);
 
         let s = String::with_capacity(10);
diff --git a/src/test/run-pass/allocator/xcrate-use.rs b/src/test/run-pass/allocator/xcrate-use.rs
index 04d2ef466e7..78d604a7108 100644
--- a/src/test/run-pass/allocator/xcrate-use.rs
+++ b/src/test/run-pass/allocator/xcrate-use.rs
@@ -17,7 +17,7 @@
 extern crate custom;
 extern crate helper;
 
-use std::heap::{Heap, Alloc, System, Layout};
+use std::alloc::{Global, Alloc, System, Layout};
 use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};
 
 #[global_allocator]
@@ -28,10 +28,10 @@ fn main() {
         let n = GLOBAL.0.load(Ordering::SeqCst);
         let layout = Layout::from_size_align(4, 2).unwrap();
 
-        let ptr = Heap.alloc(layout.clone()).unwrap();
+        let ptr = Global.alloc(layout.clone()).unwrap();
         helper::work_with(&ptr);
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
-        Heap.dealloc(ptr, layout.clone());
+        Global.dealloc(ptr, layout.clone());
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
 
         let ptr = System.alloc(layout.clone()).unwrap();
diff --git a/src/test/run-pass/allocator/xcrate-use2.rs b/src/test/run-pass/allocator/xcrate-use2.rs
index 155fb5d6c5d..b8e844522dc 100644
--- a/src/test/run-pass/allocator/xcrate-use2.rs
+++ b/src/test/run-pass/allocator/xcrate-use2.rs
@@ -19,7 +19,7 @@ extern crate custom;
 extern crate custom_as_global;
 extern crate helper;
 
-use std::heap::{Heap, Alloc, System, Layout};
+use std::alloc::{Global, Alloc, GlobalAlloc, System, Layout};
 use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};
 
 static GLOBAL: custom::A = custom::A(ATOMIC_USIZE_INIT);
@@ -30,25 +30,25 @@ fn main() {
         let layout = Layout::from_size_align(4, 2).unwrap();
 
         // Global allocator routes to the `custom_as_global` global
-        let ptr = Heap.alloc(layout.clone()).unwrap();
+        let ptr = Global.alloc(layout.clone());
         helper::work_with(&ptr);
         assert_eq!(custom_as_global::get(), n + 1);
-        Heap.dealloc(ptr, layout.clone());
+        Global.dealloc(ptr, layout.clone());
         assert_eq!(custom_as_global::get(), n + 2);
 
         // Usage of the system allocator avoids all globals
-        let ptr = System.alloc(layout.clone()).unwrap();
+        let ptr = System.alloc(layout.clone());
         helper::work_with(&ptr);
         assert_eq!(custom_as_global::get(), n + 2);
         System.dealloc(ptr, layout.clone());
         assert_eq!(custom_as_global::get(), n + 2);
 
         // Usage of our personal allocator doesn't affect other instances
-        let ptr = (&GLOBAL).alloc(layout.clone()).unwrap();
+        let ptr = GLOBAL.alloc(layout.clone());
         helper::work_with(&ptr);
         assert_eq!(custom_as_global::get(), n + 2);
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1);
-        (&GLOBAL).dealloc(ptr, layout);
+        GLOBAL.dealloc(ptr, layout);
         assert_eq!(custom_as_global::get(), n + 2);
         assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2);
     }
diff --git a/src/test/run-pass/auxiliary/packed.rs b/src/test/run-pass/auxiliary/packed.rs
index 86f5f93e3cf..828be41cd41 100644
--- a/src/test/run-pass/auxiliary/packed.rs
+++ b/src/test/run-pass/auxiliary/packed.rs
@@ -8,8 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(repr_packed)]
+
 #[repr(packed)]
-pub struct S {
+pub struct P1S5 {
     a: u8,
     b: u32
 }
+
+#[repr(packed(2))]
+pub struct P2S6 {
+    a: u8,
+    b: u32,
+    c: u8
+}
+
+#[repr(C, packed(2))]
+pub struct P2CS8 {
+    a: u8,
+    b: u32,
+    c: u8
+}
diff --git a/src/test/run-pass/cast.rs b/src/test/run-pass/cast.rs
index bb60626a4bf..80fa5362a8b 100644
--- a/src/test/run-pass/cast.rs
+++ b/src/test/run-pass/cast.rs
@@ -19,4 +19,9 @@ pub fn main() {
     assert_eq!(i as u8 as i8, 'Q' as u8 as i8);
     assert_eq!(0x51 as char, 'Q');
     assert_eq!(0 as u32, false as u32);
+
+    // Test that `_` is correctly inferred.
+    let x = &"hello";
+    let mut y = x as *const _;
+    y = 0 as *const _;
 }
diff --git a/src/test/run-pass/catch-expr.rs b/src/test/run-pass/catch-expr.rs
index 310b6ea5bcc..c23bca7f49e 100644
--- a/src/test/run-pass/catch-expr.rs
+++ b/src/test/run-pass/catch-expr.rs
@@ -13,11 +13,11 @@
 struct catch {}
 
 pub fn main() {
-    let catch_result = do catch {
+    let catch_result: Option<_> = do catch {
         let x = 5;
         x
     };
-    assert_eq!(catch_result, 5);
+    assert_eq!(catch_result, Some(5));
 
     let mut catch = true;
     while catch { catch = false; }
@@ -30,16 +30,16 @@ pub fn main() {
         _ => {}
     };
 
-    let catch_err = do catch {
+    let catch_err: Result<_, i32> = do catch {
         Err(22)?;
-        Ok(1)
+        1
     };
     assert_eq!(catch_err, Err(22));
 
     let catch_okay: Result<i32, i32> = do catch {
         if false { Err(25)?; }
         Ok::<(), i32>(())?;
-        Ok(28)
+        28
     };
     assert_eq!(catch_okay, Ok(28));
 
@@ -47,14 +47,13 @@ pub fn main() {
         for i in 0..10 {
             if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
         }
-        Ok(22)
+        22
     };
     assert_eq!(catch_from_loop, Err(5));
 
     let cfg_init;
     let _res: Result<(), ()> = do catch {
         cfg_init = 5;
-        Ok(())
     };
     assert_eq!(cfg_init, 5);
 
@@ -62,19 +61,19 @@ pub fn main() {
     let _res: Result<(), ()> = do catch {
         cfg_init_2 = 6;
         Err(())?;
-        Ok(())
     };
     assert_eq!(cfg_init_2, 6);
 
     let my_string = "test".to_string();
     let res: Result<&str, ()> = do catch {
-        Ok(&my_string)
+        // Unfortunately, deref doesn't fire here (#49356)
+        &my_string[..]
     };
     assert_eq!(res, Ok("test"));
 
-    do catch {
-        ()
-    }
+    let my_opt: Option<_> = do catch { () };
+    assert_eq!(my_opt, Some(()));
 
-    ();
+    let my_opt: Option<_> = do catch { };
+    assert_eq!(my_opt, Some(()));
 }
diff --git a/src/test/run-pass/char_unicode.rs b/src/test/run-pass/char_unicode.rs
index b4884acdd07..bfc7faac06e 100644
--- a/src/test/run-pass/char_unicode.rs
+++ b/src/test/run-pass/char_unicode.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unicode)]
-
+#![feature(unicode_version)]
 
 /// Tests access to the internal Unicode Version type and value.
 pub fn main() {
diff --git a/src/test/run-pass/issue-48159.rs b/src/test/run-pass/issue-48159.rs
new file mode 100644
index 00000000000..ce4585607e9
--- /dev/null
+++ b/src/test/run-pass/issue-48159.rs
@@ -0,0 +1,37 @@
+// 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(repr_packed)]
+#![allow(non_camel_case_types)]
+
+use std::mem;
+
+pub enum c_void {}
+
+type uintptr_t = usize;
+type int16_t = u16;
+type uint16_t = int16_t;
+type uint32_t = u32;
+type intptr_t = uintptr_t;
+
+#[repr(C)]
+#[repr(packed(4))]
+pub struct kevent {
+    pub ident: uintptr_t,
+    pub filter: int16_t,
+    pub flags: uint16_t,
+    pub fflags: uint32_t,
+    pub data: intptr_t,
+    pub udata: *mut c_void,
+}
+
+fn main() {
+    assert_eq!(mem::align_of::<kevent>(), 4);
+}
diff --git a/src/test/run-pass/issue-49556.rs b/src/test/run-pass/issue-49556.rs
new file mode 100644
index 00000000000..70ccee99f66
--- /dev/null
+++ b/src/test/run-pass/issue-49556.rs
@@ -0,0 +1,22 @@
+// 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 iter<'a>(data: &'a [usize]) -> impl Iterator<Item = usize> + 'a {
+    data.iter()
+        .map(
+            |x| x // fn(&'a usize) -> &'(ReScope) usize
+        )
+        .map(
+            |x| *x // fn(&'(ReScope) usize) -> usize
+        )
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs b/src/test/run-pass/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs
new file mode 100644
index 00000000000..51b2b5a4f7c
--- /dev/null
+++ b/src/test/run-pass/issue-49588-non-shorthand-field-patterns-in-pattern-macro.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.
+
+#![deny(non_shorthand_field_patterns)]
+
+pub struct Value<A> { pub value: A }
+
+#[macro_export]
+macro_rules! pat {
+    ($a:pat) => {
+        Value { value: $a }
+    };
+}
+
+fn main() {
+    let pat!(value) = Value { value: () };
+}
diff --git a/src/test/run-pass/packed-struct-borrow-element.rs b/src/test/run-pass/packed-struct-borrow-element.rs
index e725b25efee..c8a8643ed6b 100644
--- a/src/test/run-pass/packed-struct-borrow-element.rs
+++ b/src/test/run-pass/packed-struct-borrow-element.rs
@@ -10,15 +10,36 @@
 
 // ignore-emscripten weird assertion?
 
+#![feature(repr_packed)]
+
 #[repr(packed)]
-struct Foo {
+struct Foo1 {
+    bar: u8,
+    baz: usize
+}
+
+#[repr(packed(2))]
+struct Foo2 {
+    bar: u8,
+    baz: usize
+}
+
+#[repr(C, packed(4))]
+struct Foo4C {
     bar: u8,
     baz: usize
 }
 
 pub fn main() {
-    let foo = Foo { bar: 1, baz: 2 };
+    let foo = Foo1 { bar: 1, baz: 2 };
     let brw = unsafe { &foo.baz };
+    assert_eq!(*brw, 2);
 
+    let foo = Foo2 { bar: 1, baz: 2 };
+    let brw = unsafe { &foo.baz };
+    assert_eq!(*brw, 2);
+
+    let foo = Foo4C { bar: 1, baz: 2 };
+    let brw = unsafe { &foo.baz };
     assert_eq!(*brw, 2);
 }
diff --git a/src/test/run-pass/packed-struct-generic-size.rs b/src/test/run-pass/packed-struct-generic-size.rs
index 4e1f62b28ab..127d873b2d9 100644
--- a/src/test/run-pass/packed-struct-generic-size.rs
+++ b/src/test/run-pass/packed-struct-generic-size.rs
@@ -8,18 +8,45 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(repr_packed)]
 
 use std::mem;
 
 #[repr(packed)]
-struct S<T, S> {
+struct P1<T, S> {
     a: T,
     b: u8,
     c: S
 }
 
+#[repr(packed(2))]
+struct P2<T, S> {
+    a: T,
+    b: u8,
+    c: S
+}
+
+#[repr(C, packed(4))]
+struct P4C<T, S> {
+    a: T,
+    b: u8,
+    c: S
+}
+
+macro_rules! check {
+    ($t:ty, $align:expr, $size:expr) => ({
+        assert_eq!(mem::align_of::<$t>(), $align);
+        assert_eq!(mem::size_of::<$t>(), $size);
+    });
+}
+
 pub fn main() {
-    assert_eq!(mem::size_of::<S<u8, u8>>(), 3);
+    check!(P1::<u8, u8>, 1, 3);
+    check!(P1::<u64, u16>, 1, 11);
+
+    check!(P2::<u8, u8>, 1, 3);
+    check!(P2::<u64, u16>, 2, 12);
 
-    assert_eq!(mem::size_of::<S<u64, u16>>(), 11);
+    check!(P4C::<u8, u8>, 1, 3);
+    check!(P4C::<u16, u64>, 4, 12);
 }
diff --git a/src/test/run-pass/packed-struct-match.rs b/src/test/run-pass/packed-struct-match.rs
index 3cd254014c1..c02d524d763 100644
--- a/src/test/run-pass/packed-struct-match.rs
+++ b/src/test/run-pass/packed-struct-match.rs
@@ -8,17 +8,46 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(repr_packed)]
 
 #[repr(packed)]
-struct Foo {
+struct Foo1 {
+    bar: u8,
+    baz: usize
+}
+
+#[repr(packed(2))]
+struct Foo2 {
+    bar: u8,
+    baz: usize
+}
+
+#[repr(C, packed(4))]
+struct Foo4C {
     bar: u8,
     baz: usize
 }
 
 pub fn main() {
-    let foo = Foo { bar: 1, baz: 2 };
-    match foo {
-        Foo {bar, baz} => {
+    let foo1 = Foo1 { bar: 1, baz: 2 };
+    match foo1 {
+        Foo1 {bar, baz} => {
+            assert_eq!(bar, 1);
+            assert_eq!(baz, 2);
+        }
+    }
+
+    let foo2 = Foo2 { bar: 1, baz: 2 };
+    match foo2 {
+        Foo2 {bar, baz} => {
+            assert_eq!(bar, 1);
+            assert_eq!(baz, 2);
+        }
+    }
+
+    let foo4 = Foo4C { bar: 1, baz: 2 };
+    match foo4 {
+        Foo4C {bar, baz} => {
             assert_eq!(bar, 1);
             assert_eq!(baz, 2);
         }
diff --git a/src/test/run-pass/packed-struct-size-xc.rs b/src/test/run-pass/packed-struct-size-xc.rs
index 372693433db..48f34554ca1 100644
--- a/src/test/run-pass/packed-struct-size-xc.rs
+++ b/src/test/run-pass/packed-struct-size-xc.rs
@@ -15,6 +15,15 @@ extern crate packed;
 
 use std::mem;
 
+macro_rules! check {
+    ($t:ty, $align:expr, $size:expr) => ({
+        assert_eq!(mem::align_of::<$t>(), $align);
+        assert_eq!(mem::size_of::<$t>(), $size);
+    });
+}
+
 pub fn main() {
-    assert_eq!(mem::size_of::<packed::S>(), 5);
+    check!(packed::P1S5, 1, 5);
+    check!(packed::P2S6, 2, 6);
+    check!(packed::P2CS8, 2, 8);
 }
diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs
index 754a3573339..f8e23610fe2 100644
--- a/src/test/run-pass/packed-struct-size.rs
+++ b/src/test/run-pass/packed-struct-size.rs
@@ -7,44 +7,116 @@
 // <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(repr_packed)]
 
 
 use std::mem;
 
 #[repr(packed)]
-struct S4 {
+struct P1S4 {
+    a: u8,
+    b: [u8;  3],
+}
+
+#[repr(packed(2))]
+struct P2S4 {
     a: u8,
     b: [u8;  3],
 }
 
 #[repr(packed)]
-struct S5 {
+struct P1S5 {
+    a: u8,
+    b: u32
+}
+
+#[repr(packed(2))]
+struct P2S2 {
+    a: u8,
+    b: u8
+}
+
+#[repr(packed(2))]
+struct P2S6 {
     a: u8,
     b: u32
 }
 
+#[repr(packed(2))]
+struct P2S12 {
+    a: u32,
+    b: u64
+}
+
 #[repr(packed)]
-struct S13 {
+struct P1S13 {
     a: i64,
     b: f32,
     c: u8,
 }
 
+#[repr(packed(2))]
+struct P2S14 {
+    a: i64,
+    b: f32,
+    c: u8,
+}
+
+#[repr(packed(4))]
+struct P4S16 {
+    a: u8,
+    b: f32,
+    c: i64,
+    d: u16,
+}
+
+#[repr(C, packed(4))]
+struct P4CS20 {
+    a: u8,
+    b: f32,
+    c: i64,
+    d: u16,
+}
+
 enum Foo {
     Bar = 1,
     Baz = 2
 }
 
 #[repr(packed)]
-struct S3_Foo {
+struct P1S3_Foo {
+    a: u8,
+    b: u16,
+    c: Foo
+}
+
+#[repr(packed(2))]
+struct P2_Foo {
+    a: Foo,
+}
+
+#[repr(packed(2))]
+struct P2S3_Foo {
     a: u8,
     b: u16,
     c: Foo
 }
 
 #[repr(packed)]
-struct S7_Option {
+struct P1S7_Option {
+    a: f32,
+    b: u8,
+    c: u16,
+    d: Option<Box<f64>>
+}
+
+#[repr(packed(2))]
+struct P2_Option {
+    a: Option<Box<f64>>
+}
+
+#[repr(packed(2))]
+struct P2S7_Option {
     a: f32,
     b: u8,
     c: u16,
@@ -52,15 +124,41 @@ struct S7_Option {
 }
 
 // Placing packed structs in statics should work
-static TEST_S4: S4 = S4 { a: 1, b: [2, 3, 4] };
-static TEST_S5: S5 = S5 { a: 3, b: 67 };
-static TEST_S3_Foo: S3_Foo = S3_Foo { a: 1, b: 2, c: Foo::Baz };
+static TEST_P1S4: P1S4 = P1S4 { a: 1, b: [2, 3, 4] };
+static TEST_P1S5: P1S5 = P1S5 { a: 3, b: 67 };
+static TEST_P1S3_Foo: P1S3_Foo = P1S3_Foo { a: 1, b: 2, c: Foo::Baz };
+static TEST_P2S2: P2S2 = P2S2 { a: 1, b: 2 };
+static TEST_P2S4: P2S4 = P2S4 { a: 1, b: [2, 3, 4] };
+static TEST_P2S6: P2S6 = P2S6 { a: 1, b: 2 };
+static TEST_P2S12: P2S12 = P2S12 { a: 1, b: 2 };
+static TEST_P4S16: P4S16 = P4S16 { a: 1, b: 2.0, c: 3, d: 4 };
+static TEST_P4CS20: P4CS20 = P4CS20 { a: 1, b: 2.0, c: 3, d: 4 };
 
+fn align_to(value: usize, align: usize) -> usize {
+    (value + (align - 1)) & !(align - 1)
+}
+
+macro_rules! check {
+    ($t:ty, $align:expr, $size:expr) => ({
+        assert_eq!(mem::align_of::<$t>(), $align);
+        assert_eq!(mem::size_of::<$t>(), $size);
+    });
+}
 
 pub fn main() {
-    assert_eq!(mem::size_of::<S4>(), 4);
-    assert_eq!(mem::size_of::<S5>(), 5);
-    assert_eq!(mem::size_of::<S13>(), 13);
-    assert_eq!(mem::size_of::<S3_Foo>(), 3 + mem::size_of::<Foo>());
-    assert_eq!(mem::size_of::<S7_Option>(), 7 + mem::size_of::<Option<Box<f64>>>());
+    check!(P1S4, 1, 4);
+    check!(P1S5, 1, 5);
+    check!(P1S13, 1, 13);
+    check!(P1S3_Foo, 1, 3 + mem::size_of::<Foo>());
+    check!(P1S7_Option, 1, 7 + mem::size_of::<Option<Box<f64>>>());
+
+    check!(P2S2, 1, 2);
+    check!(P2S4, 1, 4);
+    check!(P2S6, 2, 6);
+    check!(P2S12, 2, 12);
+    check!(P2S14, 2, 14);
+    check!(P4S16, 4, 16);
+    check!(P4CS20, 4, 20);
+    check!(P2S3_Foo, 2, align_to(3 + mem::size_of::<P2_Foo>(), 2));
+    check!(P2S7_Option, 2, align_to(7 + mem::size_of::<P2_Option>(), 2));
 }
diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs
index 57407b84223..9d8b3d0d074 100644
--- a/src/test/run-pass/packed-struct-vec.rs
+++ b/src/test/run-pass/packed-struct-vec.rs
@@ -8,28 +8,80 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(repr_packed)]
+
 use std::fmt;
 use std::mem;
 
 #[repr(packed)]
 #[derive(Copy, Clone)]
-struct Foo {
+struct Foo1 {
     bar: u8,
     baz: u64
 }
 
-impl PartialEq for Foo {
-    fn eq(&self, other: &Foo) -> bool {
+impl PartialEq for Foo1 {
+    fn eq(&self, other: &Foo1) -> bool {
         self.bar == other.bar && self.baz == other.baz
     }
 }
 
-impl fmt::Debug for Foo {
+impl fmt::Debug for Foo1 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let bar = self.bar;
         let baz = self.baz;
 
-        f.debug_struct("Foo")
+        f.debug_struct("Foo1")
+            .field("bar", &bar)
+            .field("baz", &baz)
+            .finish()
+    }
+}
+
+#[repr(packed(2))]
+#[derive(Copy, Clone)]
+struct Foo2 {
+    bar: u8,
+    baz: u64
+}
+
+impl PartialEq for Foo2 {
+    fn eq(&self, other: &Foo2) -> bool {
+        self.bar == other.bar && self.baz == other.baz
+    }
+}
+
+impl fmt::Debug for Foo2 {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let bar = self.bar;
+        let baz = self.baz;
+
+        f.debug_struct("Foo2")
+            .field("bar", &bar)
+            .field("baz", &baz)
+            .finish()
+    }
+}
+
+#[repr(C, packed(4))]
+#[derive(Copy, Clone)]
+struct Foo4C {
+    bar: u8,
+    baz: u64
+}
+
+impl PartialEq for Foo4C {
+    fn eq(&self, other: &Foo4C) -> bool {
+        self.bar == other.bar && self.baz == other.baz
+    }
+}
+
+impl fmt::Debug for Foo4C {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let bar = self.bar;
+        let baz = self.baz;
+
+        f.debug_struct("Foo4C")
             .field("bar", &bar)
             .field("baz", &baz)
             .finish()
@@ -37,15 +89,42 @@ impl fmt::Debug for Foo {
 }
 
 pub fn main() {
-    let foos = [Foo { bar: 1, baz: 2 }; 10];
+    let foo1s = [Foo1 { bar: 1, baz: 2 }; 10];
+
+    assert_eq!(mem::align_of::<[Foo1; 10]>(), 1);
+    assert_eq!(mem::size_of::<[Foo1; 10]>(), 90);
+
+    for i in 0..10 {
+        assert_eq!(foo1s[i], Foo1 { bar: 1, baz: 2});
+    }
+
+    for &foo in &foo1s {
+        assert_eq!(foo, Foo1 { bar: 1, baz: 2 });
+    }
+
+    let foo2s = [Foo2 { bar: 1, baz: 2 }; 10];
+
+    assert_eq!(mem::align_of::<[Foo2; 10]>(), 2);
+    assert_eq!(mem::size_of::<[Foo2; 10]>(), 100);
+
+    for i in 0..10 {
+        assert_eq!(foo2s[i], Foo2 { bar: 1, baz: 2});
+    }
+
+    for &foo in &foo2s {
+        assert_eq!(foo, Foo2 { bar: 1, baz: 2 });
+    }
+
+    let foo4s = [Foo4C { bar: 1, baz: 2 }; 10];
 
-    assert_eq!(mem::size_of::<[Foo; 10]>(), 90);
+    assert_eq!(mem::align_of::<[Foo4C; 10]>(), 4);
+    assert_eq!(mem::size_of::<[Foo4C; 10]>(), 120);
 
     for i in 0..10 {
-        assert_eq!(foos[i], Foo { bar: 1, baz: 2});
+        assert_eq!(foo4s[i], Foo4C { bar: 1, baz: 2});
     }
 
-    for &foo in &foos {
-        assert_eq!(foo, Foo { bar: 1, baz: 2 });
+    for &foo in &foo4s {
+        assert_eq!(foo, Foo4C { bar: 1, baz: 2 });
     }
 }
diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs
index b0c8684cfe3..9def6ac28e5 100644
--- a/src/test/run-pass/packed-tuple-struct-size.rs
+++ b/src/test/run-pass/packed-tuple-struct-size.rs
@@ -8,18 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
+#![feature(repr_packed)]
 
 use std::mem;
 
 #[repr(packed)]
-struct S4(u8,[u8;  3]);
+struct P1S4(u8,[u8;  3]);
+
+#[repr(packed(2))]
+struct P2S4(u8,[u8;  3]);
 
 #[repr(packed)]
-struct S5(u8, u32);
+struct P1S5(u8, u32);
+
+#[repr(packed(2))]
+struct P2S6(u8, u32);
 
 #[repr(packed)]
-struct S13(i64, f32, u8);
+struct P1S13(i64, f32, u8);
+
+#[repr(packed(2))]
+struct P2S14(i64, f32, u8);
+
+#[repr(packed(4))]
+struct P4S16(u8, f32, i64, u16);
+
+#[repr(C, packed(4))]
+struct P4CS20(u8, f32, i64, u16);
 
 enum Foo {
     Bar = 1,
@@ -27,21 +42,46 @@ enum Foo {
 }
 
 #[repr(packed)]
-struct S3_Foo(u8, u16, Foo);
+struct P1S3_Foo(u8, u16, Foo);
+
+#[repr(packed(2))]
+struct P2_Foo(Foo);
+
+#[repr(packed(2))]
+struct P2S3_Foo(u8, u16, Foo);
 
 #[repr(packed)]
-struct S7_Option(f32, u8, u16, Option<Box<f64>>);
+struct P1S7_Option(f32, u8, u16, Option<Box<f64>>);
 
-pub fn main() {
-    assert_eq!(mem::size_of::<S4>(), 4);
+#[repr(packed(2))]
+struct P2_Option(Option<Box<f64>>);
+
+#[repr(packed(2))]
+struct P2S7_Option(f32, u8, u16, Option<Box<f64>>);
 
-    assert_eq!(mem::size_of::<S5>(), 5);
+fn align_to(value: usize, align: usize) -> usize {
+    (value + (align - 1)) & !(align - 1)
+}
 
-    assert_eq!(mem::size_of::<S13>(), 13);
+macro_rules! check {
+    ($t:ty, $align:expr, $size:expr) => ({
+        assert_eq!(mem::align_of::<$t>(), $align);
+        assert_eq!(mem::size_of::<$t>(), $size);
+    });
+}
 
-    assert_eq!(mem::size_of::<S3_Foo>(),
-               3 + mem::size_of::<Foo>());
+pub fn main() {
+    check!(P1S4, 1, 4);
+    check!(P1S5, 1, 5);
+    check!(P1S13, 1, 13);
+    check!(P1S3_Foo, 1, 3 + mem::size_of::<Foo>());
+    check!(P1S7_Option, 1, 7 + mem::size_of::<Option<Box<f64>>>());
 
-    assert_eq!(mem::size_of::<S7_Option>(),
-              7 + mem::size_of::<Option<Box<f64>>>());
+    check!(P2S4, 1, 4);
+    check!(P2S6, 2, 6);
+    check!(P2S14, 2, 14);
+    check!(P4S16, 4, 16);
+    check!(P4CS20, 4, 20);
+    check!(P2S3_Foo, 2, align_to(3 + mem::size_of::<P2_Foo>(), 2));
+    check!(P2S7_Option, 2, align_to(7 + mem::size_of::<P2_Option>(), 2));
 }
diff --git a/src/test/run-pass/realloc-16687.rs b/src/test/run-pass/realloc-16687.rs
index eddcd5a584a..38cc23c16a9 100644
--- a/src/test/run-pass/realloc-16687.rs
+++ b/src/test/run-pass/realloc-16687.rs
@@ -13,10 +13,10 @@
 // Ideally this would be revised to use no_std, but for now it serves
 // well enough to reproduce (and illustrate) the bug from #16687.
 
-#![feature(heap_api, allocator_api)]
+#![feature(heap_api, allocator_api, nonnull_cast)]
 
-use std::heap::{Heap, Alloc, Layout};
-use std::ptr;
+use std::alloc::{Global, Alloc, Layout};
+use std::ptr::{self, NonNull};
 
 fn main() {
     unsafe {
@@ -50,13 +50,13 @@ unsafe fn test_triangle() -> bool {
             println!("allocate({:?})", layout);
         }
 
-        let ret = Heap.alloc(layout.clone()).unwrap_or_else(|e| Heap.oom(e));
+        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| Global.oom());
 
         if PRINT {
             println!("allocate({:?}) = {:?}", layout, ret);
         }
 
-        ret
+        ret.cast().as_ptr()
     }
 
     unsafe fn deallocate(ptr: *mut u8, layout: Layout) {
@@ -64,7 +64,7 @@ unsafe fn test_triangle() -> bool {
             println!("deallocate({:?}, {:?}", ptr, layout);
         }
 
-        Heap.dealloc(ptr, layout);
+        Global.dealloc(NonNull::new_unchecked(ptr).as_opaque(), layout);
     }
 
     unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 {
@@ -72,14 +72,14 @@ unsafe fn test_triangle() -> bool {
             println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new);
         }
 
-        let ret = Heap.realloc(ptr, old.clone(), new.clone())
-            .unwrap_or_else(|e| Heap.oom(e));
+        let ret = Global.realloc(NonNull::new_unchecked(ptr).as_opaque(), old.clone(), new.size())
+            .unwrap_or_else(|_| Global.oom());
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
                      ptr, old, new, ret);
         }
-        ret
+        ret.cast().as_ptr()
     }
 
     fn idx_to_size(i: usize) -> usize { (i+1) * 10 }
diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs
index 8f278a315d1..3c37243c8b9 100644
--- a/src/test/run-pass/regions-mock-trans.rs
+++ b/src/test/run-pass/regions-mock-trans.rs
@@ -13,6 +13,7 @@
 #![feature(allocator_api)]
 
 use std::heap::{Alloc, Heap, Layout};
+use std::ptr::NonNull;
 
 struct arena(());
 
@@ -32,8 +33,8 @@ struct Ccx {
 fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
     unsafe {
         let ptr = Heap.alloc(Layout::new::<Bcx>())
-            .unwrap_or_else(|e| Heap.oom(e));
-        &*(ptr as *const _)
+            .unwrap_or_else(|_| Heap.oom());
+        &*(ptr.as_ptr() as *const _)
     }
 }
 
@@ -45,7 +46,7 @@ fn g(fcx : &Fcx) {
     let bcx = Bcx { fcx: fcx };
     let bcx2 = h(&bcx);
     unsafe {
-        Heap.dealloc(bcx2 as *const _ as *mut _, Layout::new::<Bcx>());
+        Heap.dealloc(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::<Bcx>());
     }
 }
 
diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs
index 2f50e63153e..0bb18d8729a 100644
--- a/src/test/run-pass/type-sizes.rs
+++ b/src/test/run-pass/type-sizes.rs
@@ -42,6 +42,12 @@ enum ReorderedEnum {
     B(u8, u16, u8),
 }
 
+enum NicheFilledEnumWithInhabitedVariant {
+    A(&'static ()),
+    B(&'static (), !),
+    C,
+}
+
 pub fn main() {
     assert_eq!(size_of::<u8>(), 1 as usize);
     assert_eq!(size_of::<u32>(), 4 as usize);
@@ -67,4 +73,5 @@ pub fn main() {
     assert_eq!(size_of::<e3>(), 4 as usize);
     assert_eq!(size_of::<ReorderedStruct>(), 4);
     assert_eq!(size_of::<ReorderedEnum>(), 6);
+    assert_eq!(size_of::<NicheFilledEnumWithInhabitedVariant>(), size_of::<&'static ()>());
 }
diff --git a/src/test/run-pass/union/union-packed.rs b/src/test/run-pass/union/union-packed.rs
index 6a61280823e..61bb04fece0 100644
--- a/src/test/run-pass/union/union-packed.rs
+++ b/src/test/run-pass/union/union-packed.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(untagged_unions)]
+#![feature(repr_packed)]
 
 use std::mem::{size_of, size_of_val, align_of, align_of_val};
 
@@ -18,7 +19,13 @@ struct S {
 }
 
 #[repr(packed)]
-struct Sp {
+struct Sp1 {
+    a: u16,
+    b: [u8; 3],
+}
+
+#[repr(packed(2))]
+struct Sp2 {
     a: u16,
     b: [u8; 3],
 }
@@ -29,15 +36,30 @@ union U {
 }
 
 #[repr(packed)]
-union Up {
+union Up1 {
+    a: u16,
+    b: [u8; 3],
+}
+
+#[repr(packed(2))]
+union Up2 {
+    a: u16,
+    b: [u8; 3],
+}
+
+#[repr(C, packed(4))]
+union Up4c {
     a: u16,
     b: [u8; 3],
 }
 
 const CS: S = S { a: 0, b: [0, 0, 0] };
-const CSP: Sp = Sp { a: 0, b: [0, 0, 0] };
+const CSP1: Sp1 = Sp1 { a: 0, b: [0, 0, 0] };
+const CSP2: Sp2 = Sp2 { a: 0, b: [0, 0, 0] };
 const CU: U = U { b: [0, 0, 0] };
-const CUP: Up = Up { b: [0, 0, 0] };
+const CUP1: Up1 = Up1 { b: [0, 0, 0] };
+const CUP2: Up2 = Up2 { b: [0, 0, 0] };
+const CUP4C: Up4c = Up4c { b: [0, 0, 0] };
 
 fn main() {
     let s = S { a: 0, b: [0, 0, 0] };
@@ -48,13 +70,21 @@ fn main() {
     assert_eq!(align_of_val(&s), 2);
     assert_eq!(align_of_val(&CS), 2);
 
-    let sp = Sp { a: 0, b: [0, 0, 0] };
-    assert_eq!(size_of::<Sp>(), 5);
-    assert_eq!(size_of_val(&sp), 5);
-    assert_eq!(size_of_val(&CSP), 5);
-    assert_eq!(align_of::<Sp>(), 1);
-    assert_eq!(align_of_val(&sp), 1);
-    assert_eq!(align_of_val(&CSP), 1);
+    let sp1 = Sp1 { a: 0, b: [0, 0, 0] };
+    assert_eq!(size_of::<Sp1>(), 5);
+    assert_eq!(size_of_val(&sp1), 5);
+    assert_eq!(size_of_val(&CSP1), 5);
+    assert_eq!(align_of::<Sp1>(), 1);
+    assert_eq!(align_of_val(&sp1), 1);
+    assert_eq!(align_of_val(&CSP1), 1);
+
+    let sp2 = Sp2 { a: 0, b: [0, 0, 0] };
+    assert_eq!(size_of::<Sp2>(), 6);
+    assert_eq!(size_of_val(&sp2), 6);
+    assert_eq!(size_of_val(&CSP2), 6);
+    assert_eq!(align_of::<Sp2>(), 2);
+    assert_eq!(align_of_val(&sp2), 2);
+    assert_eq!(align_of_val(&CSP2), 2);
 
     let u = U { b: [0, 0, 0] };
     assert_eq!(size_of::<U>(), 4);
@@ -64,19 +94,35 @@ fn main() {
     assert_eq!(align_of_val(&u), 2);
     assert_eq!(align_of_val(&CU), 2);
 
-    let up = Up { b: [0, 0, 0] };
-    assert_eq!(size_of::<Up>(), 3);
-    assert_eq!(size_of_val(&up), 3);
-    assert_eq!(size_of_val(&CUP), 3);
-    assert_eq!(align_of::<Up>(), 1);
-    assert_eq!(align_of_val(&up), 1);
-    assert_eq!(align_of_val(&CUP), 1);
+    let Up1 = Up1 { b: [0, 0, 0] };
+    assert_eq!(size_of::<Up1>(), 3);
+    assert_eq!(size_of_val(&Up1), 3);
+    assert_eq!(size_of_val(&CUP1), 3);
+    assert_eq!(align_of::<Up1>(), 1);
+    assert_eq!(align_of_val(&Up1), 1);
+    assert_eq!(align_of_val(&CUP1), 1);
+
+    let up2 = Up2 { b: [0, 0, 0] };
+    assert_eq!(size_of::<Up2>(), 4);
+    assert_eq!(size_of_val(&up2), 4);
+    assert_eq!(size_of_val(&CUP2), 4);
+    assert_eq!(align_of::<Up2>(), 2);
+    assert_eq!(align_of_val(&up2), 2);
+    assert_eq!(align_of_val(&CUP2), 2);
+
+    let up4c = Up4c { b: [0, 0, 0] };
+    assert_eq!(size_of::<Up4c>(), 4);
+    assert_eq!(size_of_val(&up4c), 4);
+    assert_eq!(size_of_val(&CUP4C), 4);
+    assert_eq!(align_of::<Up4c>(), 2);
+    assert_eq!(align_of_val(&up4c), 2);
+    assert_eq!(align_of_val(&CUP4C), 2);
 
     hybrid::check_hybrid();
 }
 
 mod hybrid {
-    use std::mem::size_of;
+    use std::mem::{size_of, align_of};
 
     #[repr(packed)]
     struct S1 {
@@ -96,9 +142,37 @@ mod hybrid {
         u: U,
     }
 
+    #[repr(C, packed(2))]
+    struct S1C {
+        a: u16,
+        b: u8,
+    }
+
+    #[repr(C, packed(2))]
+    union UC {
+        s: S1,
+        c: u16,
+    }
+
+    #[repr(C, packed(2))]
+    struct S2C {
+        d: u8,
+        u: UC,
+    }
+
     pub fn check_hybrid() {
+        assert_eq!(align_of::<S1>(), 1);
         assert_eq!(size_of::<S1>(), 3);
+        assert_eq!(align_of::<U>(), 1);
         assert_eq!(size_of::<U>(), 3);
+        assert_eq!(align_of::<S2>(), 1);
         assert_eq!(size_of::<S2>(), 4);
+
+        assert_eq!(align_of::<S1C>(), 2);
+        assert_eq!(size_of::<S1C>(), 4);
+        assert_eq!(align_of::<UC>(), 2);
+        assert_eq!(size_of::<UC>(), 4);
+        assert_eq!(align_of::<S2C>(), 2);
+        assert_eq!(size_of::<S2C>(), 6);
     }
 }
diff --git a/src/test/rustdoc/all.rs b/src/test/rustdoc/all.rs
new file mode 100644
index 00000000000..ec391319b18
--- /dev/null
+++ b/src/test/rustdoc/all.rs
@@ -0,0 +1,30 @@
+// 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_name = "foo"]
+
+// @has foo/all.html '//a[@href="struct.Struct.html"]' 'Struct'
+// @has foo/all.html '//a[@href="enum.Enum.html"]' 'Enum'
+// @has foo/all.html '//a[@href="union.Union.html"]' 'Union'
+// @has foo/all.html '//a[@href="constant.CONST.html"]' 'CONST'
+// @has foo/all.html '//a[@href="static.STATIC.html"]' 'STATIC'
+// @has foo/all.html '//a[@href="fn.function.html"]' 'function'
+
+pub struct Struct;
+pub enum Enum {
+    X,
+    Y,
+}
+pub union Union {
+    x: u32,
+}
+pub const CONST: u32 = 0;
+pub static STATIC: &str = "baguette";
+pub fn function() {}
diff --git a/src/test/ui/asm-out-assign-imm.rs b/src/test/ui/asm-out-assign-imm.rs
index 49084e01a15..055a169deda 100644
--- a/src/test/ui/asm-out-assign-imm.rs
+++ b/src/test/ui/asm-out-assign-imm.rs
@@ -12,6 +12,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-mips
 
 #![feature(asm)]
 
diff --git a/src/test/ui/asm-out-assign-imm.stderr b/src/test/ui/asm-out-assign-imm.stderr
index 4ec758b97f2..d9fd4b26c39 100644
--- a/src/test/ui/asm-out-assign-imm.stderr
+++ b/src/test/ui/asm-out-assign-imm.stderr
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `x`
-  --> $DIR/asm-out-assign-imm.rs:29:9
+  --> $DIR/asm-out-assign-imm.rs:30:9
    |
 LL |     x = 1;
    |     ----- first assignment to `x`
diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr
new file mode 100644
index 00000000000..deb2e7ed4a3
--- /dev/null
+++ b/src/test/ui/augmented-assignments.nll.stderr
@@ -0,0 +1,26 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+  --> $DIR/augmented-assignments.rs:26:5
+   |
+LL |       x   //~ error: use of moved value: `x`
+   |       -
+   |       |
+   |  _____borrow of `x` occurs here
+   | |
+LL | |     //~^ value used here after move
+LL | |     +=
+LL | |     x;  //~ value moved here
+   | |     -
+   | |     |
+   | |_____move out of `x` occurs here
+   |       borrow later used here
+
+error[E0596]: cannot borrow immutable item `y` as mutable
+  --> $DIR/augmented-assignments.rs:30:5
+   |
+LL |     y   //~ error: cannot borrow immutable local variable `y` as mutable
+   |     ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0505, E0596.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
new file mode 100644
index 00000000000..1b370567ed1
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
@@ -0,0 +1,25 @@
+error[E0382]: use of moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:46:14
+   |
+LL |     let _x = a.x;
+   |              --- value moved here
+LL |     //~^ value moved here
+LL |     let _y = a.y; //~ ERROR use of moved
+   |              ^^^ value used here after move
+   |
+   = note: move occurs because `a.y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:108:14
+   |
+LL |     let _x = a.x.x;
+   |              ----- value moved here
+LL |     //~^ value moved here
+LL |     let _y = a.y; //~ ERROR use of collaterally moved
+   |              ^^^ value used here after move
+   |
+   = note: move occurs because `a.y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr
new file mode 100644
index 00000000000..a21a6e36778
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-closures-two-mut.nll.stderr
@@ -0,0 +1,78 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:24:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+   |                        ^^ - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     //~| ERROR cannot borrow `x` as mutable more than once
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:35:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     //~| ERROR cannot borrow `x` as mutable more than once
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:42:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+   |                        ^^          - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     //~| ERROR cannot borrow `x` as mutable more than once
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:49:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+   |                        ^^                                  - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
+  --> $DIR/borrowck-closures-two-mut.rs:61:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - previous borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+...
+LL | }
+   | - first borrow ends here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr
new file mode 100644
index 00000000000..b931bc45b77
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `books` does not live long enough
+  --> $DIR/borrowck-escaping-closure-error-1.rs:23:11
+   |
+LL |     spawn(|| books.push(4));
+   |           ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+LL |     //~^ ERROR E0373
+LL | }
+   | - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr
new file mode 100644
index 00000000000..2b5070977a3
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `books` does not live long enough
+  --> $DIR/borrowck-escaping-closure-error-2.rs:21:14
+   |
+LL |     Box::new(|| books.push(4))
+   |              ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+LL |     //~^ ERROR E0373
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 19:1...
+  --> $DIR/borrowck-escaping-closure-error-2.rs:19:1
+   |
+LL | fn foo<'a>(x: &'a i32) -> Box<FnMut()+'a> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/borrowck-in-static.nll.stderr b/src/test/ui/borrowck/borrowck-in-static.nll.stderr
new file mode 100644
index 00000000000..927d8c37458
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-in-static.nll.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-in-static.rs:15:17
+   |
+LL |     Box::new(|| x) //~ ERROR cannot move out of captured outer variable
+   |                 ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
new file mode 100644
index 00000000000..c563a28b317
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
@@ -0,0 +1,40 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:23:19
+   |
+LL |         Foo::Foo1(num1,
+   |                   ^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:24:19
+   |
+LL |                   num2) => (),
+   |                   ^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:25:19
+   |
+LL |         Foo::Foo2(num) => (),
+   |                   ^^^ cannot move out of borrowed content
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-error-with-note.rs:42:16
+   |
+LL |             f: _s,
+   |                ^^ cannot move out of here
+
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/borrowck-move-error-with-note.rs:43:16
+   |
+LL |             g: _t
+   |                ^^ cannot move out of here
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-error-with-note.rs:59:9
+   |
+LL |         n => {
+   |         ^ cannot move out of borrowed content
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0507, E0509.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
new file mode 100644
index 00000000000..a430c97158a
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:30:33
+   |
+LL |                 &[Foo { string: a },
+   |                                 ^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:34:33
+   |
+LL |                   Foo { string: b }] => {
+   |                                 ^ cannot move out of borrowed content
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr
new file mode 100644
index 00000000000..951907876b9
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/borrowck-report-with-custom-diagnostic.rs:12:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     // Original borrow ends at end of function
+LL | |     let mut x = 1;
+LL | |     let y = &mut x;
+...  |
+LL | |     //~^ immutable borrow occurs here
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
index a6553160557..cdfee2e8a70 100644
--- a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
+++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.rs
@@ -7,9 +7,9 @@
 // <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)]
 #![allow(dead_code)]
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     // Original borrow ends at end of function
     let mut x = 1;
     let y = &mut x;
diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
new file mode 100644
index 00000000000..d5a66a6c706
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
@@ -0,0 +1,51 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:42:15
+   |
+LL |         &mut [_a, //~ ERROR cannot move out
+   |               ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:13
+   |
+LL |     let a = vec[0]; //~ ERROR cannot move out
+   |             ^^^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:65:10
+   |
+LL |          _b] => {}
+   |          ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:68:13
+   |
+LL |     let a = vec[0]; //~ ERROR cannot move out
+   |             ^^^^^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:76:15
+   |
+LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+   |               ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:76:19
+   |
+LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+   |                   ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:76:23
+   |
+LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+   |                       ^^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-vec-pattern-nesting.rs:80:13
+   |
+LL |     let a = vec[0]; //~ ERROR cannot move out
+   |             ^^^^^^ cannot move out of borrowed content
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr
new file mode 100644
index 00000000000..ecd17edb079
--- /dev/null
+++ b/src/test/ui/borrowck/issue-45983.nll.stderr
@@ -0,0 +1,30 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/issue-45983.rs:17:27
+   |
+LL |     give_any(|y| x = Some(y));
+   |                           ^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/issue-45983.rs:17:27
+   |
+LL |     give_any(|y| x = Some(y));
+   |                           ^
+
+error[E0594]: cannot assign to immutable item `x`
+  --> $DIR/issue-45983.rs:17:18
+   |
+LL |     give_any(|y| x = Some(y));
+   |                  ^^^^^^^^^^^ cannot mutate
+   |
+   = note: Value not mutable causing this error: `x`
+
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/issue-45983.rs:17:14
+   |
+LL |     give_any(|y| x = Some(y));
+   |              ^^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/borrowck/issue-7573.nll.stderr b/src/test/ui/borrowck/issue-7573.nll.stderr
new file mode 100644
index 00000000000..c55c49604d0
--- /dev/null
+++ b/src/test/ui/borrowck/issue-7573.nll.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/issue-7573.rs:27:31
+   |
+LL |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
+   |                               ^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/issue-7573.rs:32:9
+   |
+LL |         lines_to_use.push(installed_id);
+   |         ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr
new file mode 100644
index 00000000000..fc288e6b1d6
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr
@@ -0,0 +1,21 @@
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:20:25
+   |
+LL |             (self.func)(arg) //~ ERROR cannot borrow
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:26:25
+   |
+LL |             (self.func)(arg) //~ ERROR cannot borrow
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:33:25
+   |
+LL |             (self.func)(arg) //~ ERROR cannot borrow
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
new file mode 100644
index 00000000000..dab769820a6
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/mut-borrow-outside-loop.rs:13:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut void = ();
+LL | |
+LL | |     let first = &mut void;
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.rs b/src/test/ui/borrowck/mut-borrow-outside-loop.rs
index a1ab41bab33..edc877718ad 100644
--- a/src/test/ui/borrowck/mut-borrow-outside-loop.rs
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 // ensure borrowck messages are correct outside special case
-
-fn main() {
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut void = ();
 
     let first = &mut void;
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr
new file mode 100644
index 00000000000..d34a716bb2b
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/regions-escape-bound-fn-2.rs:18:27
+   |
+LL |     with_int(|y| x = Some(y));
+   |                           ^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/regions-escape-bound-fn-2.rs:18:27
+   |
+LL |     with_int(|y| x = Some(y));
+   |                           ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr
new file mode 100644
index 00000000000..b69c172bcdc
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/regions-escape-bound-fn.rs:18:22
+   |
+LL |     with_int(|y| x = Some(y));
+   |                      ^^^^^^^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/regions-escape-bound-fn.rs:18:27
+   |
+LL |     with_int(|y| x = Some(y));
+   |                           ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr
new file mode 100644
index 00000000000..788654a2ecc
--- /dev/null
+++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/regions-escape-unboxed-closure.rs:16:27
+   |
+LL |     with_int(&mut |y| x = Some(y));
+   |                           ^^^^^^^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/regions-escape-unboxed-closure.rs:16:32
+   |
+LL |     with_int(&mut |y| x = Some(y));
+   |                                ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
new file mode 100644
index 00000000000..7464e33e8c1
--- /dev/null
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.nll.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
+   |
+LL |         y.into_iter();
+   |         ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/catch-block-type-error.rs b/src/test/ui/catch-block-type-error.rs
new file mode 100644
index 00000000000..10130ef1e5d
--- /dev/null
+++ b/src/test/ui/catch-block-type-error.rs
@@ -0,0 +1,26 @@
+// 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(catch_expr)]
+
+fn foo() -> Option<()> { Some(()) }
+
+fn main() {
+    let _: Option<f32> = do catch {
+        foo()?;
+        42
+        //~^ ERROR type mismatch
+    };
+
+    let _: Option<i32> = do catch {
+        foo()?;
+    };
+    //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/catch-block-type-error.stderr b/src/test/ui/catch-block-type-error.stderr
new file mode 100644
index 00000000000..0ae8d4862f7
--- /dev/null
+++ b/src/test/ui/catch-block-type-error.stderr
@@ -0,0 +1,21 @@
+error[E0271]: type mismatch resolving `<std::option::Option<f32> as std::ops::Try>::Ok == {integer}`
+  --> $DIR/catch-block-type-error.rs:18:9
+   |
+LL |         42
+   |         ^^ expected f32, found integral variable
+   |
+   = note: expected type `f32`
+              found type `{integer}`
+
+error[E0271]: type mismatch resolving `<std::option::Option<i32> as std::ops::Try>::Ok == ()`
+  --> $DIR/catch-block-type-error.rs:24:5
+   |
+LL |     };
+   |     ^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs
index 010cb77edc3..74feb0105cc 100644
--- a/src/test/ui/chalkify/lower_trait.rs
+++ b/src/test/ui/chalkify/lower_trait.rs
@@ -11,6 +11,9 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
 trait Foo<S, T, U> {
     fn s(S) -> S;
     fn t(T) -> T;
diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr
index 6da1e2fd8ed..45753c3bb90 100644
--- a/src/test/ui/chalkify/lower_trait.stderr
+++ b/src/test/ui/chalkify/lower_trait.stderr
@@ -4,5 +4,23 @@ error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
 LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs
new file mode 100644
index 00000000000..e5eaf4591ec
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_higher_rank.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.
+
+#![feature(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
+{
+    fn s(F) -> F;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr
new file mode 100644
index 00000000000..9aed0c018c9
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_higher_rank.stderr
@@ -0,0 +1,26 @@
+error: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs
new file mode 100644
index 00000000000..b2ce3ca48b2
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_where_clause.rs
@@ -0,0 +1,31 @@
+// 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(rustc_attrs)]
+
+use std::fmt::{Debug, Display};
+use std::borrow::Borrow;
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR RegionOutlives
+                              //~| ERROR TypeOutlives
+trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
+    fn s(S) -> S;
+    fn t(T) -> T;
+    fn u(U) -> U;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr
new file mode 100644
index 00000000000..a9ecaec3aff
--- /dev/null
+++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr
@@ -0,0 +1,44 @@
+error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr
new file mode 100644
index 00000000000..18edf2addc5
--- /dev/null
+++ b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr
@@ -0,0 +1,44 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/expect-region-supply-region.rs:28:13
+   |
+LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |             ^^^^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/expect-region-supply-region.rs:38:13
+   |
+LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |             ^^^^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/expect-region-supply-region.rs:47:33
+   |
+LL |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/expect-region-supply-region.rs:52:13
+   |
+LL |         f = Some(x);
+   |             ^^^^^^^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/expect-region-supply-region.rs:28:18
+   |
+LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |                  ^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/expect-region-supply-region.rs:38:18
+   |
+LL |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |                  ^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/expect-region-supply-region.rs:52:18
+   |
+LL |         f = Some(x);
+   |                  ^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/closure_context/issue-42065.nll.stderr b/src/test/ui/closure_context/issue-42065.nll.stderr
new file mode 100644
index 00000000000..bda8a3b85f7
--- /dev/null
+++ b/src/test/ui/closure_context/issue-42065.nll.stderr
@@ -0,0 +1,11 @@
+error[E0382]: use of moved value: `debug_dump_dict`
+  --> $DIR/issue-42065.rs:21:5
+   |
+LL |     debug_dump_dict();
+   |     --------------- value moved here
+LL |     debug_dump_dict();
+   |     ^^^^^^^^^^^^^^^ value used here after move
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
new file mode 100644
index 00000000000..4526616e488
--- /dev/null
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/huge_multispan_highlight.rs:100:13
+   |
+LL |     let y = &mut x; //~ ERROR cannot borrow
+   |             ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/codemap_tests/issue-11715.nll.stderr b/src/test/ui/codemap_tests/issue-11715.nll.stderr
new file mode 100644
index 00000000000..952ccdb98da
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-11715.nll.stderr
@@ -0,0 +1,12 @@
+error: compilation successful
+  --> $DIR/issue-11715.rs:97:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut x = "foo";
+LL | |     let y = &mut x;
+LL | |     let z = &mut x; //~ ERROR cannot borrow
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/issue-11715.rs b/src/test/ui/codemap_tests/issue-11715.rs
index 75581d38927..03c85fbfcd7 100644
--- a/src/test/ui/codemap_tests/issue-11715.rs
+++ b/src/test/ui/codemap_tests/issue-11715.rs
@@ -93,8 +93,8 @@
 
 
 
-
-fn main() {
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut x = "foo";
     let y = &mut x;
     let z = &mut x; //~ ERROR cannot borrow
diff --git a/src/test/ui/codemap_tests/one_line.nll.stderr b/src/test/ui/codemap_tests/one_line.nll.stderr
new file mode 100644
index 00000000000..52ce3787f58
--- /dev/null
+++ b/src/test/ui/codemap_tests/one_line.nll.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/one_line.rs:13:12
+   |
+LL |     v.push(v.pop().unwrap()); //~ ERROR cannot borrow
+   |     -------^----------------
+   |     |      |
+   |     |      second mutable borrow occurs here
+   |     first mutable borrow occurs here
+   |     borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/codemap_tests/overlapping_spans.nll.stderr b/src/test/ui/codemap_tests/overlapping_spans.nll.stderr
new file mode 100644
index 00000000000..b6630b2e666
--- /dev/null
+++ b/src/test/ui/codemap_tests/overlapping_spans.nll.stderr
@@ -0,0 +1,9 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/overlapping_spans.rs:21:14
+   |
+LL |         S {f:_s} => {} //~ ERROR cannot move out
+   |              ^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/codemap_tests/tab_3.nll.stderr b/src/test/ui/codemap_tests/tab_3.nll.stderr
new file mode 100644
index 00000000000..c56cb7772c8
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab_3.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `some_vec`
+  --> $DIR/tab_3.rs:17:20
+   |
+LL |     some_vec.into_iter();
+   |     -------- value moved here
+LL |     {
+LL |         println!("{:?}", some_vec); //~ ERROR use of moved
+   |                          ^^^^^^^^ value borrowed here after move
+   |
+   = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/command-line-diagnostics.nll.stderr b/src/test/ui/command-line-diagnostics.nll.stderr
new file mode 100644
index 00000000000..2d5a31f0586
--- /dev/null
+++ b/src/test/ui/command-line-diagnostics.nll.stderr
@@ -0,0 +1,11 @@
+error[E0384]: cannot assign twice to immutable variable `x`
+  --> $DIR/command-line-diagnostics.rs:16:5
+   |
+LL |     let x = 42;
+   |             -- first assignment to `x`
+LL |     x = 43;
+   |     ^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/did_you_mean/issue-31424.nll.stderr b/src/test/ui/did_you_mean/issue-31424.nll.stderr
new file mode 100644
index 00000000000..6b63f64c699
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-31424.nll.stderr
@@ -0,0 +1,15 @@
+error[E0596]: cannot borrow immutable item `self` as mutable
+  --> $DIR/issue-31424.rs:17:9
+   |
+LL |         (&mut self).bar(); //~ ERROR cannot borrow
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `self` as mutable
+  --> $DIR/issue-31424.rs:23:9
+   |
+LL |         (&mut self).bar(); //~ ERROR cannot borrow
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-34126.nll.stderr b/src/test/ui/did_you_mean/issue-34126.nll.stderr
new file mode 100644
index 00000000000..afdc26a75c7
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34126.nll.stderr
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-34126.rs:16:18
+   |
+LL |         self.run(&mut self); //~ ERROR cannot borrow
+   |         ---------^^^^^^^^^-
+   |         |        |
+   |         |        mutable borrow occurs here
+   |         immutable borrow occurs here
+   |         borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/did_you_mean/issue-34337.nll.stderr b/src/test/ui/did_you_mean/issue-34337.nll.stderr
new file mode 100644
index 00000000000..258e1bb1ad7
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-34337.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `key` as mutable
+  --> $DIR/issue-34337.rs:16:9
+   |
+LL |     get(&mut key); //~ ERROR cannot borrow
+   |         ^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-35937.nll.stderr b/src/test/ui/did_you_mean/issue-35937.nll.stderr
new file mode 100644
index 00000000000..7b5f452d322
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-35937.nll.stderr
@@ -0,0 +1,28 @@
+error[E0596]: cannot borrow immutable item `f.v` as mutable
+  --> $DIR/issue-35937.rs:17:5
+   |
+LL |     f.v.push("cat".to_string()); //~ ERROR cannot borrow
+   |     ^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `f`
+
+error[E0384]: cannot assign twice to immutable variable `s.x`
+  --> $DIR/issue-35937.rs:26:5
+   |
+LL |     let s = S { x: 42 };
+   |             ----------- first assignment to `s.x`
+LL |     s.x += 1; //~ ERROR cannot assign
+   |     ^^^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `s.x`
+  --> $DIR/issue-35937.rs:30:5
+   |
+LL | fn bar(s: S) {
+   |        - first assignment to `s.x`
+LL |     s.x += 1; //~ ERROR cannot assign
+   |     ^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0384, E0596.
+For more information about an error, try `rustc --explain E0384`.
diff --git a/src/test/ui/did_you_mean/issue-37139.nll.stderr b/src/test/ui/did_you_mean/issue-37139.nll.stderr
new file mode 100644
index 00000000000..29c7192a98b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-37139.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/issue-37139.rs:22:18
+   |
+LL |             test(&mut x); //~ ERROR cannot borrow immutable
+   |                  ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-1.nll.stderr b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
new file mode 100644
index 00000000000..099479eaf2b
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-1.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable item `*self.s` as mutable
+  --> $DIR/issue-38147-1.rs:27:9
+   |
+LL |         self.s.push('x'); //~ ERROR cannot borrow data mutably
+   |         ^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*self`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-2.nll.stderr b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
new file mode 100644
index 00000000000..c8e231ea3b3
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `*self.s` as mutable
+  --> $DIR/issue-38147-2.rs:17:9
+   |
+LL |         self.s.push('x');
+   |         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-3.nll.stderr b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
new file mode 100644
index 00000000000..c5d6551b647
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `*self.s` as mutable
+  --> $DIR/issue-38147-3.rs:17:9
+   |
+LL |         self.s.push('x');
+   |         ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-38147-4.nll.stderr b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
new file mode 100644
index 00000000000..5649fc903a0
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-38147-4.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable item `*f.s` as mutable
+  --> $DIR/issue-38147-4.rs:16:5
+   |
+LL |     f.s.push('x'); //~ ERROR cannot borrow data mutably
+   |     ^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr
new file mode 100644
index 00000000000..6e57796aa45
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr
@@ -0,0 +1,98 @@
+error[E0596]: cannot borrow immutable item `z.x` as mutable
+  --> $DIR/issue-39544.rs:21:13
+   |
+LL |     let _ = &mut z.x; //~ ERROR cannot borrow
+   |             ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `z`
+
+error[E0596]: cannot borrow immutable item `self.x` as mutable
+  --> $DIR/issue-39544.rs:26:17
+   |
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*self`
+
+error[E0596]: cannot borrow immutable item `self.x` as mutable
+  --> $DIR/issue-39544.rs:30:17
+   |
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*self`
+
+error[E0596]: cannot borrow immutable item `other.x` as mutable
+  --> $DIR/issue-39544.rs:31:17
+   |
+LL |         let _ = &mut other.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*other`
+
+error[E0596]: cannot borrow immutable item `self.x` as mutable
+  --> $DIR/issue-39544.rs:35:17
+   |
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*self`
+
+error[E0596]: cannot borrow immutable item `other.x` as mutable
+  --> $DIR/issue-39544.rs:36:17
+   |
+LL |         let _ = &mut other.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*other`
+
+error[E0596]: cannot borrow immutable item `self.x` as mutable
+  --> $DIR/issue-39544.rs:40:17
+   |
+LL |         let _ = &mut self.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*self`
+
+error[E0596]: cannot borrow immutable item `other.x` as mutable
+  --> $DIR/issue-39544.rs:41:17
+   |
+LL |         let _ = &mut other.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*other`
+
+error[E0596]: cannot borrow immutable item `other.x` as mutable
+  --> $DIR/issue-39544.rs:45:17
+   |
+LL |         let _ = &mut other.x; //~ ERROR cannot borrow
+   |                 ^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*other`
+
+error[E0596]: cannot borrow immutable item `z.x` as mutable
+  --> $DIR/issue-39544.rs:51:13
+   |
+LL |     let _ = &mut z.x; //~ ERROR cannot borrow
+   |             ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `z`
+
+error[E0596]: cannot borrow immutable item `w.x` as mutable
+  --> $DIR/issue-39544.rs:52:13
+   |
+LL |     let _ = &mut w.x; //~ ERROR cannot borrow
+   |             ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*w`
+
+error[E0594]: cannot assign to immutable item `*x.0`
+  --> $DIR/issue-39544.rs:58:5
+   |
+LL |     *x.0 = 1;
+   |     ^^^^^^^^ cannot mutate
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/did_you_mean/issue-40823.nll.stderr b/src/test/ui/did_you_mean/issue-40823.nll.stderr
new file mode 100644
index 00000000000..489e1c39c46
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-40823.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `*buf` as mutable
+  --> $DIR/issue-40823.rs:13:5
+   |
+LL |     buf.iter_mut(); //~ ERROR cannot borrow immutable borrowed content
+   |     ^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs
new file mode 100644
index 00000000000..45265173419
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs
@@ -0,0 +1,44 @@
+// 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 gratitude() {
+    let for_you = false;
+    if not for_you {
+        //~^ ERROR unexpected `for_you` after identifier
+        println!("I couldn't");
+    }
+}
+
+fn qualification() {
+    let the_worst = true;
+    while not the_worst {
+        //~^ ERROR unexpected `the_worst` after identifier
+        println!("still pretty bad");
+    }
+}
+
+fn should_we() {
+    let not = true;
+    if not  // lack of braces is [sic]
+        println!("Then when?");
+    //~^ ERROR expected `{`, found `;
+    //~| ERROR unexpected `println` after identifier
+}
+
+fn sleepy() {
+    let resource = not 2;
+    //~^ ERROR unexpected `2` after identifier
+}
+
+fn main() {
+    let be_smothered_out_before = true;
+    let young_souls = not be_smothered_out_before;
+    //~^ ERROR unexpected `be_smothered_out_before` after identifier
+}
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
new file mode 100644
index 00000000000..db3478116cb
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -0,0 +1,50 @@
+error: unexpected `for_you` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:13:12
+   |
+LL |     if not for_you {
+   |        ----^^^^^^^
+   |        |
+   |        help: use `!` to perform logical negation
+
+error: unexpected `the_worst` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:21:15
+   |
+LL |     while not the_worst {
+   |           ----^^^^^^^^^
+   |           |
+   |           help: use `!` to perform logical negation
+
+error: unexpected `println` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:30:9
+   |
+LL |     if not  // lack of braces is [sic]
+   |        ----- help: use `!` to perform logical negation
+LL |         println!("Then when?");
+   |         ^^^^^^^
+
+error: expected `{`, found `;`
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:30:31
+   |
+LL |     if not  // lack of braces is [sic]
+   |     -- this `if` statement has a condition, but no block
+LL |         println!("Then when?");
+   |                               ^
+
+error: unexpected `2` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:36:24
+   |
+LL |     let resource = not 2;
+   |                    ----^
+   |                    |
+   |                    help: use `!` to perform logical negation
+
+error: unexpected `be_smothered_out_before` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:42:27
+   |
+LL |     let young_souls = not be_smothered_out_before;
+   |                       ----^^^^^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       help: use `!` to perform logical negation
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr
new file mode 100644
index 00000000000..692f697e889
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/dropck-eyepatch-extern-crate.rs:27:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     use std::cell::Cell;
+LL | |     let c_long;
+LL | |     let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
+...  |
+LL | |     println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs b/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs
index 4f88b0e6fcc..e06b47a8d79 100644
--- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs
+++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.rs
@@ -19,12 +19,12 @@
 //
 // See also dropck-eyepatch.rs for more information about the general
 // structure of the test.
-
+#![feature(rustc_attrs)]
 extern crate dropck_eyepatch_extern_crate as other;
 
 use other::{Dt,Dr,Pt,Pr,St,Sr};
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     use std::cell::Cell;
     let c_long;
     let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr
new file mode 100644
index 00000000000..f50168fd586
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/dropck-eyepatch-reorder.rs:44:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     use std::cell::Cell;
+LL | |     let c_long;
+LL | |     let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
+...  |
+LL | |     println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.rs b/src/test/ui/dropck/dropck-eyepatch-reorder.rs
index eda8d85f6ec..832eeacbec5 100644
--- a/src/test/ui/dropck/dropck-eyepatch-reorder.rs
+++ b/src/test/ui/dropck/dropck-eyepatch-reorder.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(dropck_eyepatch)]
+#![feature(dropck_eyepatch, rustc_attrs)]
 
 // The point of this test is to test uses of `#[may_dangle]` attribute
 // where the formal declaration order (in the impl generics) does not
@@ -41,7 +41,7 @@ unsafe impl<'b, #[may_dangle] 'a, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
 }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     use std::cell::Cell;
     let c_long;
     let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
diff --git a/src/test/ui/dropck/dropck-eyepatch.nll.stderr b/src/test/ui/dropck/dropck-eyepatch.nll.stderr
new file mode 100644
index 00000000000..8c55fdbc0b8
--- /dev/null
+++ b/src/test/ui/dropck/dropck-eyepatch.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/dropck-eyepatch.rs:67:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     use std::cell::Cell;
+LL | |     let c_long;
+LL | |     let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
+...  |
+LL | |     println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/dropck/dropck-eyepatch.rs b/src/test/ui/dropck/dropck-eyepatch.rs
index af173a2e979..cfa67837485 100644
--- a/src/test/ui/dropck/dropck-eyepatch.rs
+++ b/src/test/ui/dropck/dropck-eyepatch.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(dropck_eyepatch)]
+#![feature(dropck_eyepatch, rustc_attrs)]
 
 // The point of this test is to illustrate that the `#[may_dangle]`
 // attribute specifically allows, in the context of a type
@@ -64,7 +64,7 @@ unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
     fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
 }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     use std::cell::Cell;
     let c_long;
     let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
diff --git a/src/test/ui/error-codes/E0017.nll.stderr b/src/test/ui/error-codes/E0017.nll.stderr
new file mode 100644
index 00000000000..ec31f5d05d7
--- /dev/null
+++ b/src/test/ui/error-codes/E0017.nll.stderr
@@ -0,0 +1,28 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/E0017.rs:14:30
+   |
+LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017
+   |                              ^^^^^^ constants require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0017.rs:15:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+   |                                       ^^^^^^ statics require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0017.rs:17:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+   |                                      ^^^^^^ statics require immutable values
+
+error[E0596]: cannot borrow immutable item `X` as mutable
+  --> $DIR/E0017.rs:15:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+   |                                       ^^^^^^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0017, E0596.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/error-codes/E0161.nll.stderr b/src/test/ui/error-codes/E0161.nll.stderr
new file mode 100644
index 00000000000..6aaff743383
--- /dev/null
+++ b/src/test/ui/error-codes/E0161.nll.stderr
@@ -0,0 +1,16 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/E0161.rs:14:28
+   |
+LL |     let _x: Box<str> = box *"hello"; //~ ERROR E0161
+   |                            ^^^^^^^^ cannot move out of borrowed content
+
+error[E0161]: cannot move a value of type str: the size of str cannot be statically determined
+  --> $DIR/E0161.rs:14:28
+   |
+LL |     let _x: Box<str> = box *"hello"; //~ ERROR E0161
+   |                            ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/src/test/ui/error-codes/E0388.nll.stderr b/src/test/ui/error-codes/E0388.nll.stderr
new file mode 100644
index 00000000000..6a4bd6b31a1
--- /dev/null
+++ b/src/test/ui/error-codes/E0388.nll.stderr
@@ -0,0 +1,28 @@
+error[E0017]: references in constants may only refer to immutable values
+  --> $DIR/E0388.rs:14:30
+   |
+LL | const CR: &'static mut i32 = &mut C; //~ ERROR E0017
+   |                              ^^^^^^ constants require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:15:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+   |                                       ^^^^^^ statics require immutable values
+
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/E0388.rs:17:38
+   |
+LL | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+   |                                      ^^^^^^ statics require immutable values
+
+error[E0596]: cannot borrow immutable item `X` as mutable
+  --> $DIR/E0388.rs:15:39
+   |
+LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+   |                                       ^^^^^^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0017, E0596.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/error-codes/E0389.nll.stderr b/src/test/ui/error-codes/E0389.nll.stderr
new file mode 100644
index 00000000000..13ba653a5ca
--- /dev/null
+++ b/src/test/ui/error-codes/E0389.nll.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to immutable item `fancy_ref.num`
+  --> $DIR/E0389.rs:18:5
+   |
+LL |     fancy_ref.num = 6; //~ ERROR E0389
+   |     ^^^^^^^^^^^^^^^^^ cannot mutate
+   |
+   = note: Value not mutable causing this error: `*fancy_ref`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/error-codes/E0499.nll.stderr b/src/test/ui/error-codes/E0499.nll.stderr
new file mode 100644
index 00000000000..27a71df147e
--- /dev/null
+++ b/src/test/ui/error-codes/E0499.nll.stderr
@@ -0,0 +1,12 @@
+error: compilation successful
+  --> $DIR/E0499.rs:11:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut i = 0;
+LL | |     let mut x = &mut i;
+LL | |     let mut a = &mut i; //~ ERROR E0499
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0499.rs b/src/test/ui/error-codes/E0499.rs
index 9a64bfe2ea9..c3997236934 100644
--- a/src/test/ui/error-codes/E0499.rs
+++ b/src/test/ui/error-codes/E0499.rs
@@ -7,8 +7,8 @@
 // <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() {
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut i = 0;
     let mut x = &mut i;
     let mut a = &mut i; //~ ERROR E0499
diff --git a/src/test/ui/error-codes/E0502.nll.stderr b/src/test/ui/error-codes/E0502.nll.stderr
new file mode 100644
index 00000000000..67a08661040
--- /dev/null
+++ b/src/test/ui/error-codes/E0502.nll.stderr
@@ -0,0 +1,9 @@
+error: compilation successful
+  --> $DIR/E0502.rs:17:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0502.rs b/src/test/ui/error-codes/E0502.rs
index fce8513ca64..9c126bdcde8 100644
--- a/src/test/ui/error-codes/E0502.rs
+++ b/src/test/ui/error-codes/E0502.rs
@@ -7,12 +7,12 @@
 // <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)]
 fn bar(x: &mut i32) {}
 fn foo(a: &mut i32) {
     let ref y = a;
     bar(a); //~ ERROR E0502
 }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
 }
diff --git a/src/test/ui/error-codes/E0503.nll.stderr b/src/test/ui/error-codes/E0503.nll.stderr
new file mode 100644
index 00000000000..6c5e99d8769
--- /dev/null
+++ b/src/test/ui/error-codes/E0503.nll.stderr
@@ -0,0 +1,12 @@
+error: compilation successful
+  --> $DIR/E0503.rs:11:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut value = 3;
+LL | |     let _borrow = &mut value;
+LL | |     let _sum = value + 1; //~ ERROR E0503
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0503.rs b/src/test/ui/error-codes/E0503.rs
index 810eb8d9b07..1822a8925d3 100644
--- a/src/test/ui/error-codes/E0503.rs
+++ b/src/test/ui/error-codes/E0503.rs
@@ -7,8 +7,8 @@
 // <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() {
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut value = 3;
     let _borrow = &mut value;
     let _sum = value + 1; //~ ERROR E0503
diff --git a/src/test/ui/error-codes/E0504.nll.stderr b/src/test/ui/error-codes/E0504.nll.stderr
new file mode 100644
index 00000000000..ec30bb306fc
--- /dev/null
+++ b/src/test/ui/error-codes/E0504.nll.stderr
@@ -0,0 +1,18 @@
+error[E0505]: cannot move out of `fancy_num` because it is borrowed
+  --> $DIR/E0504.rs:19:13
+   |
+LL |       let fancy_ref = &fancy_num;
+   |                       ---------- borrow of `fancy_num` occurs here
+LL | 
+LL |       let x = move || {
+   |  _____________^
+LL | |         println!("child function: {}", fancy_num.num); //~ ERROR E0504
+LL | |     };
+   | |_____^ move out of `fancy_num` occurs here
+...
+LL |       println!("main function: {}", fancy_ref.num);
+   |                                     ------------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/error-codes/E0505.nll.stderr b/src/test/ui/error-codes/E0505.nll.stderr
new file mode 100644
index 00000000000..556e0c73d1a
--- /dev/null
+++ b/src/test/ui/error-codes/E0505.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/E0505.rs:15:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let x = Value{};
+LL | |     {
+LL | |         let _ref_to_val: &Value = &x;
+LL | |         eat(x); //~ ERROR E0505
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0505.rs b/src/test/ui/error-codes/E0505.rs
index 2d534b8a44a..dd2980936c0 100644
--- a/src/test/ui/error-codes/E0505.rs
+++ b/src/test/ui/error-codes/E0505.rs
@@ -7,12 +7,12 @@
 // <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 Value {}
 
 fn eat(val: Value) {}
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let x = Value{};
     {
         let _ref_to_val: &Value = &x;
diff --git a/src/test/ui/error-codes/E0509.nll.stderr b/src/test/ui/error-codes/E0509.nll.stderr
new file mode 100644
index 00000000000..56d970494a0
--- /dev/null
+++ b/src/test/ui/error-codes/E0509.nll.stderr
@@ -0,0 +1,9 @@
+error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait
+  --> $DIR/E0509.rs:26:23
+   |
+LL |     let fancy_field = drop_struct.fancy; //~ ERROR E0509
+   |                       ^^^^^^^^^^^^^^^^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
diff --git a/src/test/ui/error-codes/E0597.nll.stderr b/src/test/ui/error-codes/E0597.nll.stderr
new file mode 100644
index 00000000000..56119e4226e
--- /dev/null
+++ b/src/test/ui/error-codes/E0597.nll.stderr
@@ -0,0 +1,13 @@
+error: compilation successful
+  --> $DIR/E0597.rs:15:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut x = Foo { x: None };
+LL | |     let y = 0;
+LL | |     x.x = Some(&y);
+LL | |     //~^ `y` does not live long enough [E0597]
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0597.rs b/src/test/ui/error-codes/E0597.rs
index 2f4a1da91d8..74178a69444 100644
--- a/src/test/ui/error-codes/E0597.rs
+++ b/src/test/ui/error-codes/E0597.rs
@@ -7,12 +7,12 @@
 // <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 Foo<'a> {
     x: Option<&'a u32>,
 }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut x = Foo { x: None };
     let y = 0;
     x.x = Some(&y);
diff --git a/src/test/ui/error-codes/E0609.stderr b/src/test/ui/error-codes/E0609.stderr
index 24581889ae9..dd793b29feb 100644
--- a/src/test/ui/error-codes/E0609.stderr
+++ b/src/test/ui/error-codes/E0609.stderr
@@ -7,10 +7,10 @@ LL |     let _ = x.foo; //~ ERROR E0609
    = note: available fields are: `x`
 
 error[E0609]: no field `1` on type `Bar`
-  --> $DIR/E0609.rs:21:5
+  --> $DIR/E0609.rs:21:7
    |
 LL |     y.1; //~ ERROR E0609
-   |     ^^^
+   |       ^ unknown field
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0611.stderr b/src/test/ui/error-codes/E0611.stderr
deleted file mode 100644
index c4b86e76c14..00000000000
--- a/src/test/ui/error-codes/E0611.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0611]: field `0` of tuple-struct `a::Foo` is private
-  --> $DIR/E0611.rs:21:4
-   |
-LL |    y.0; //~ ERROR E0611
-   |    ^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0611`.
diff --git a/src/test/ui/error-codes/E0612.stderr b/src/test/ui/error-codes/E0612.stderr
deleted file mode 100644
index 18013697a83..00000000000
--- a/src/test/ui/error-codes/E0612.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0612]: attempted out-of-bounds tuple index `1` on type `Foo`
-  --> $DIR/E0612.rs:15:4
-   |
-LL |    y.1; //~ ERROR E0612
-   |    ^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0612`.
diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr
new file mode 100644
index 00000000000..e9f09795691
--- /dev/null
+++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:25:5
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
+   |     ^^^^^^
+
+error: free region `` does not outlive free region `'_#2r`
+  --> $DIR/E0621-does-not-trigger-for-closures.rs:25:26
+   |
+LL |     invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
+   |                          ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0611.rs b/src/test/ui/error-codes/ex-E0611.rs
index 1e392d194b1..4e580242e64 100644
--- a/src/test/ui/error-codes/E0611.rs
+++ b/src/test/ui/error-codes/ex-E0611.rs
@@ -18,5 +18,5 @@ mod a {
 
 fn main() {
    let y = a::Foo::new();
-   y.0; //~ ERROR E0611
+   y.0; //~ ERROR field `0` of struct `a::Foo` is private
 }
diff --git a/src/test/ui/error-codes/ex-E0611.stderr b/src/test/ui/error-codes/ex-E0611.stderr
new file mode 100644
index 00000000000..2f5066542db
--- /dev/null
+++ b/src/test/ui/error-codes/ex-E0611.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `0` of struct `a::Foo` is private
+  --> $DIR/ex-E0611.rs:21:4
+   |
+LL |    y.0; //~ ERROR field `0` of struct `a::Foo` is private
+   |    ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/error-codes/E0612.rs b/src/test/ui/error-codes/ex-E0612.rs
index 429a8bb7eb7..46e26c87e5f 100644
--- a/src/test/ui/error-codes/E0612.rs
+++ b/src/test/ui/error-codes/ex-E0612.rs
@@ -12,5 +12,5 @@ struct Foo(u32);
 
 fn main() {
    let y = Foo(0);
-   y.1; //~ ERROR E0612
+   y.1; //~ ERROR no field `1` on type `Foo`
 }
diff --git a/src/test/ui/error-codes/ex-E0612.stderr b/src/test/ui/error-codes/ex-E0612.stderr
new file mode 100644
index 00000000000..a07efc939ab
--- /dev/null
+++ b/src/test/ui/error-codes/ex-E0612.stderr
@@ -0,0 +1,9 @@
+error[E0609]: no field `1` on type `Foo`
+  --> $DIR/ex-E0612.rs:15:6
+   |
+LL |    y.1; //~ ERROR no field `1` on type `Foo`
+   |      ^ did you mean `0`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/feature-gate-infer_outlives_requirements.rs b/src/test/ui/feature-gate-infer_outlives_requirements.rs
new file mode 100644
index 00000000000..01ccc50a130
--- /dev/null
+++ b/src/test/ui/feature-gate-infer_outlives_requirements.rs
@@ -0,0 +1,18 @@
+// 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.
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type T needs to outlive lifetime 'a.
+struct Foo<'a, T> {
+    bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
+}
+
+fn main() { }
diff --git a/src/test/ui/feature-gate-infer_outlives_requirements.stderr b/src/test/ui/feature-gate-infer_outlives_requirements.stderr
new file mode 100644
index 00000000000..560e494b582
--- /dev/null
+++ b/src/test/ui/feature-gate-infer_outlives_requirements.stderr
@@ -0,0 +1,17 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/feature-gate-infer_outlives_requirements.rs:15:5
+   |
+LL | struct Foo<'a, T> {
+   |                - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a [T]` does not outlive the data it points at
+  --> $DIR/feature-gate-infer_outlives_requirements.rs:15:5
+   |
+LL |     bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/feature-gate-nll.nll.stderr b/src/test/ui/feature-gate-nll.nll.stderr
new file mode 100644
index 00000000000..81de0d14aa7
--- /dev/null
+++ b/src/test/ui/feature-gate-nll.nll.stderr
@@ -0,0 +1,13 @@
+error: compilation successful
+  --> $DIR/feature-gate-nll.rs:13:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut x = 33;
+LL | |
+LL | |     let p = &x;
+LL | |     x = 22; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate-nll.rs b/src/test/ui/feature-gate-nll.rs
index f34a9cddf98..752b1fa821f 100644
--- a/src/test/ui/feature-gate-nll.rs
+++ b/src/test/ui/feature-gate-nll.rs
@@ -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.
-
+#![feature(rustc_attrs)]
 #![allow(dead_code)]
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut x = 33;
 
     let p = &x;
diff --git a/src/libstd_unicode/tests/lib.rs b/src/test/ui/feature-gate-repr_packed.rs
index 9535ec18763..12bb152b467 100644
--- a/src/libstd_unicode/tests/lib.rs
+++ b/src/test/ui/feature-gate-repr_packed.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2017 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,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(str_internals, unicode)]
+#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
+struct Foo(u64);
 
-extern crate std_unicode;
-
-mod lossy;
+fn main() {}
diff --git a/src/test/ui/feature-gate-repr_packed.stderr b/src/test/ui/feature-gate-repr_packed.stderr
new file mode 100644
index 00000000000..d0faf9d90bd
--- /dev/null
+++ b/src/test/ui/feature-gate-repr_packed.stderr
@@ -0,0 +1,11 @@
+error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158)
+  --> $DIR/feature-gate-repr_packed.rs:11:1
+   |
+LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_packed)] 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/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr
new file mode 100644
index 00000000000..1801da6c8b2
--- /dev/null
+++ b/src/test/ui/generator/borrowing.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/borrowing.rs:15:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let _b = {
+LL | |         let a = 3;
+LL | |         unsafe { (|| yield &a).resume() }
+...  |
+LL | |     };
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs
index e56927d8182..f80aca9fb00 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)]
+#![feature(generators, generator_trait, rustc_attrs)]
 
 use std::ops::Generator;
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     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
new file mode 100644
index 00000000000..72ebaab3278
--- /dev/null
+++ b/src/test/ui/generator/dropck.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/dropck.rs:16:1
+   |
+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 | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs
index b2240fb225f..8f4ba64fd57 100644
--- a/src/test/ui/generator/dropck.rs
+++ b/src/test/ui/generator/dropck.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generators, generator_trait, box_leak)]
+#![feature(generators, generator_trait, box_leak, rustc_attrs)]
 
 use std::cell::RefCell;
 use std::ops::Generator;
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let (cell, mut gen);
     cell = Box::new(RefCell::new(0));
     let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
diff --git a/src/test/ui/generator/pattern-borrow.nll.stderr b/src/test/ui/generator/pattern-borrow.nll.stderr
new file mode 100644
index 00000000000..ec8adf9d37c
--- /dev/null
+++ b/src/test/ui/generator/pattern-borrow.nll.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/pattern-borrow.rs:15:1
+   |
+LL | fn main() { #![rustc_error] } // rust-lang/rust#49855
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generator/pattern-borrow.rs b/src/test/ui/generator/pattern-borrow.rs
index 557a5e62f7e..dd63b9eaa5b 100644
--- a/src/test/ui/generator/pattern-borrow.rs
+++ b/src/test/ui/generator/pattern-borrow.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generators)]
+#![feature(generators, rustc_attrs)]
 
 enum Test { A(i32), B, }
 
-fn main() { }
+fn main() { #![rustc_error] } // rust-lang/rust#49855
 
 fn fun(test: Test) {
     move || {
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
new file mode 100644
index 00000000000..08839c23c37
--- /dev/null
+++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr
@@ -0,0 +1,12 @@
+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
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generator/yield-in-args.nll.stderr b/src/test/ui/generator/yield-in-args.nll.stderr
new file mode 100644
index 00000000000..6242ec0f548
--- /dev/null
+++ b/src/test/ui/generator/yield-in-args.nll.stderr
@@ -0,0 +1,9 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/yield-in-args.rs:18:13
+   |
+LL |         foo(&b, yield); //~ ERROR
+   |             ^^  ----- possible yield occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0626`.
diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr
new file mode 100644
index 00000000000..be4852aaf06
--- /dev/null
+++ b/src/test/ui/generator/yield-while-iterating.nll.stderr
@@ -0,0 +1,55 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/yield-while-iterating.rs:22:18
+   |
+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
+   |
+LL |       let mut b = || {
+   |  _________________-
+LL | |         for p in &mut x {
+LL | |             yield p;
+LL | |         }
+LL | |     };
+   | |_____- mutable borrow occurs here
+LL |       println!("{}", x[0]); //~ ERROR
+   |                      ^ immutable borrow occurs here
+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
+
+Some errors occurred: E0502, E0597, E0626.
+For more information about an error, try `rustc --explain E0502`.
diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
new file mode 100644
index 00000000000..14989079527
--- /dev/null
+++ b/src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
@@ -0,0 +1,18 @@
+error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
+  --> $DIR/yield-while-ref-reborrowed.rs:45:20
+   |
+LL |       let mut b = || {
+   |  _________________-
+LL | |         let a = &mut *x;
+LL | |         yield();
+LL | |         println!("{}", a);
+LL | |     };
+   | |_____- closure construction occurs here
+LL |       println!("{}", x); //~ ERROR
+   |                      ^ borrow occurs here
+LL |       b.resume();
+   |       - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0501`.
diff --git a/src/test/compile-fail/hygiene/assoc_item_ctxt.rs b/src/test/ui/hygiene/assoc_item_ctxt.rs
index e336b0df13f..e336b0df13f 100644
--- a/src/test/compile-fail/hygiene/assoc_item_ctxt.rs
+++ b/src/test/ui/hygiene/assoc_item_ctxt.rs
diff --git a/src/test/ui/hygiene/assoc_item_ctxt.stderr b/src/test/ui/hygiene/assoc_item_ctxt.stderr
new file mode 100644
index 00000000000..8b410405ae5
--- /dev/null
+++ b/src/test/ui/hygiene/assoc_item_ctxt.stderr
@@ -0,0 +1,25 @@
+error[E0407]: method `method` is not a member of trait `Tr`
+  --> $DIR/assoc_item_ctxt.rs:45:13
+   |
+LL |             fn method() {} //~ ERROR method `method` is not a member of trait `Tr`
+   |             ^^^^^^^^^^^^^^ not a member of trait `Tr`
+...
+LL |     mac_trait_impl!();
+   |     ------------------ in this macro invocation
+
+error[E0046]: not all trait items implemented, missing: `method`
+  --> $DIR/assoc_item_ctxt.rs:44:9
+   |
+LL |         fn method();
+   |         ------------ `method` from trait
+...
+LL |         impl Tr for u8 { //~ ERROR not all trait items implemented, missing: `method`
+   |         ^^^^^^^^^^^^^^ missing `method` in implementation
+...
+LL |     mac_trait_impl!();
+   |     ------------------ in this macro invocation
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0046, E0407.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/compile-fail/hygiene/assoc_ty_bindings.rs b/src/test/ui/hygiene/assoc_ty_bindings.rs
index 46a138749ff..46a138749ff 100644
--- a/src/test/compile-fail/hygiene/assoc_ty_bindings.rs
+++ b/src/test/ui/hygiene/assoc_ty_bindings.rs
diff --git a/src/test/ui/hygiene/assoc_ty_bindings.stderr b/src/test/ui/hygiene/assoc_ty_bindings.stderr
new file mode 100644
index 00000000000..0adf80994f7
--- /dev/null
+++ b/src/test/ui/hygiene/assoc_ty_bindings.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/assoc_ty_bindings.rs:49:1
+   |
+LL | fn main() {} //~ ERROR compilation successful
+   | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/hygiene/auxiliary/intercrate.rs b/src/test/ui/hygiene/auxiliary/intercrate.rs
index aa67e5c5f4d..aa67e5c5f4d 100644
--- a/src/test/compile-fail/hygiene/auxiliary/intercrate.rs
+++ b/src/test/ui/hygiene/auxiliary/intercrate.rs
diff --git a/src/test/ui/hygiene/fields-definition.rs b/src/test/ui/hygiene/fields-definition.rs
new file mode 100644
index 00000000000..c92bf55a723
--- /dev/null
+++ b/src/test/ui/hygiene/fields-definition.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(decl_macro)]
+
+macro modern($a: ident) {
+    struct Modern {
+        a: u8,
+        $a: u8, // OK
+    }
+}
+
+macro_rules! legacy {
+    ($a: ident) => {
+        struct Legacy {
+            a: u8,
+            $a: u8, //~ ERROR field `a` is already declared
+        }
+    }
+}
+
+modern!(a);
+legacy!(a);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/fields-definition.stderr b/src/test/ui/hygiene/fields-definition.stderr
new file mode 100644
index 00000000000..73f524b7d2a
--- /dev/null
+++ b/src/test/ui/hygiene/fields-definition.stderr
@@ -0,0 +1,14 @@
+error[E0124]: field `a` is already declared
+  --> $DIR/fields-definition.rs:24:17
+   |
+LL |             a: u8,
+   |             ----- `a` first declared here
+LL |             $a: u8, //~ ERROR field `a` is already declared
+   |                 ^^ field already declared
+...
+LL | legacy!(a);
+   | ----------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0124`.
diff --git a/src/test/ui/hygiene/fields-move.rs b/src/test/ui/hygiene/fields-move.rs
new file mode 100644
index 00000000000..a6e3b2b2d8b
--- /dev/null
+++ b/src/test/ui/hygiene/fields-move.rs
@@ -0,0 +1,40 @@
+// 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 #46314
+
+#![feature(decl_macro)]
+
+#[derive(Debug)]
+struct NonCopy(String);
+
+struct Foo {
+    x: NonCopy,
+}
+
+macro copy_modern($foo: ident) {
+   $foo.x
+}
+
+macro_rules! copy_legacy {
+    ($foo: ident) => {
+        $foo.x //~ ERROR use of moved value: `foo.x`
+    }
+}
+
+fn assert_two_copies(a: NonCopy, b: NonCopy) {
+   println!("Got two copies: {:?}, {:?}", a, b);
+}
+
+fn main() {
+    let foo = Foo { x: NonCopy("foo".into()) };
+    assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+    assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+}
diff --git a/src/test/ui/hygiene/fields-move.stderr b/src/test/ui/hygiene/fields-move.stderr
new file mode 100644
index 00000000000..ba9de09f9d2
--- /dev/null
+++ b/src/test/ui/hygiene/fields-move.stderr
@@ -0,0 +1,39 @@
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:38:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |     assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:28:9
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |         $foo.x //~ ERROR use of moved value: `foo.x`
+   |         ^^^^^^ value used here after move
+...
+LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                       ----------------- in this macro invocation
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo.x`
+  --> $DIR/fields-move.rs:39:42
+   |
+LL |    $foo.x
+   |    ------ value moved here
+...
+LL |     assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
+   |                                          ^^^^^ value used here after move
+   |
+   = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.rs b/src/test/ui/hygiene/fields-numeric-borrowck.rs
new file mode 100644
index 00000000000..50ace39e709
--- /dev/null
+++ b/src/test/ui/hygiene/fields-numeric-borrowck.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.
+
+struct S(u8);
+
+fn main() {
+    let mut s = S(0);
+    let borrow1 = &mut s.0;
+    let S { 0: ref mut borrow2 } = s;
+    //~^ ERROR cannot borrow `s.0` as mutable more than once at a time
+}
diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.stderr b/src/test/ui/hygiene/fields-numeric-borrowck.stderr
new file mode 100644
index 00000000000..ccd898fff27
--- /dev/null
+++ b/src/test/ui/hygiene/fields-numeric-borrowck.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `s.0` as mutable more than once at a time
+  --> $DIR/fields-numeric-borrowck.rs:16:16
+   |
+LL |     let borrow1 = &mut s.0;
+   |                        --- first mutable borrow occurs here
+LL |     let S { 0: ref mut borrow2 } = s;
+   |                ^^^^^^^^^^^^^^^ second mutable borrow occurs here
+LL |     //~^ ERROR cannot borrow `s.0` as mutable more than once at a time
+LL | }
+   | - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/compile-fail/hygiene/fields.rs b/src/test/ui/hygiene/fields.rs
index 64217770b13..64217770b13 100644
--- a/src/test/compile-fail/hygiene/fields.rs
+++ b/src/test/ui/hygiene/fields.rs
diff --git a/src/test/ui/hygiene/fields.stderr b/src/test/ui/hygiene/fields.stderr
new file mode 100644
index 00000000000..c4be1834c04
--- /dev/null
+++ b/src/test/ui/hygiene/fields.stderr
@@ -0,0 +1,38 @@
+error: type `foo::S` is private
+  --> $DIR/fields.rs:25:17
+   |
+LL |         let s = S { x: 0 }; //~ ERROR type `foo::S` is private
+   |                 ^^^^^^^^^^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: type `foo::S` is private
+  --> $DIR/fields.rs:26:17
+   |
+LL |         let _ = s.x; //~ ERROR type `foo::S` is private
+   |                 ^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: type `foo::T` is private
+  --> $DIR/fields.rs:28:17
+   |
+LL |         let t = T(0); //~ ERROR type `foo::T` is private
+   |                 ^^^^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: type `foo::T` is private
+  --> $DIR/fields.rs:29:17
+   |
+LL |         let _ = t.0; //~ ERROR type `foo::T` is private
+   |                 ^
+...
+LL |     let s = foo::m!(S, x);
+   |             ------------- in this macro invocation
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/compile-fail/for-loop-hygiene.rs b/src/test/ui/hygiene/for-loop.rs
index d9386421970..d9386421970 100644
--- a/src/test/compile-fail/for-loop-hygiene.rs
+++ b/src/test/ui/hygiene/for-loop.rs
diff --git a/src/test/ui/hygiene/for-loop.stderr b/src/test/ui/hygiene/for-loop.stderr
new file mode 100644
index 00000000000..7e606b2358c
--- /dev/null
+++ b/src/test/ui/hygiene/for-loop.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `iter` in this scope
+  --> $DIR/for-loop.rs:16:9
+   |
+LL |         iter.next();  //~ ERROR cannot find value `iter` in this scope
+   |         ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/compile-fail/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs
index 7ba217061c6..7ba217061c6 100644
--- a/src/test/compile-fail/hygiene/globs.rs
+++ b/src/test/ui/hygiene/globs.rs
diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr
new file mode 100644
index 00000000000..d77242e135d
--- /dev/null
+++ b/src/test/ui/hygiene/globs.stderr
@@ -0,0 +1,49 @@
+error[E0425]: cannot find function `f` in this scope
+  --> $DIR/globs.rs:32:9
+   |
+LL |         f(); //~ ERROR cannot find function `f` in this scope
+   |         ^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use foo::f;
+   |
+LL | use foo::f;
+   |
+LL | use foo::f;
+   |
+
+error[E0425]: cannot find function `g` in this scope
+  --> $DIR/globs.rs:25:5
+   |
+LL |       g(); //~ ERROR cannot find function `g` in this scope
+   |       ^ not found in this scope
+...
+LL | /     m! {
+LL | |         use bar::*;
+LL | |         g();
+LL | |         f(); //~ ERROR cannot find function `f` in this scope
+LL | |     }
+   | |_____- in this macro invocation
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use bar::g;
+   |
+LL | use foo::test2::test::g;
+   |
+LL | use foo::test::g;
+   |
+LL | use foo::test::g;
+   |
+
+error[E0425]: cannot find function `f` in this scope
+  --> $DIR/globs.rs:64:17
+   |
+LL | n!(f);
+   | ------ in this macro invocation
+...
+LL |                 f //~ ERROR cannot find function `f` in this scope
+   |                 ^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/compile-fail/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs
index cdba559445d..cdba559445d 100644
--- a/src/test/compile-fail/hygiene/impl_items.rs
+++ b/src/test/ui/hygiene/impl_items.rs
diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr
new file mode 100644
index 00000000000..dbcf53554cf
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items.stderr
@@ -0,0 +1,11 @@
+error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
+  --> $DIR/impl_items.rs:22:23
+   |
+LL |         let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
+   |                       ^
+...
+LL |     foo::m!();
+   |     ---------- in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/hygiene/intercrate.rs b/src/test/ui/hygiene/intercrate.rs
index 50fc985ba34..50fc985ba34 100644
--- a/src/test/compile-fail/hygiene/intercrate.rs
+++ b/src/test/ui/hygiene/intercrate.rs
diff --git a/src/test/ui/hygiene/intercrate.stderr b/src/test/ui/hygiene/intercrate.stderr
new file mode 100644
index 00000000000..ecbc6e7b147
--- /dev/null
+++ b/src/test/ui/hygiene/intercrate.stderr
@@ -0,0 +1,10 @@
+error: type `fn() -> u32 {intercrate::foo::bar::f}` is private
+  --> $DIR/intercrate.rs:22:16
+   |
+LL |     assert_eq!(intercrate::foo::m!(), 1);
+   |                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/hygiene/nested_macro_privacy.rs b/src/test/ui/hygiene/nested_macro_privacy.rs
index 6612359649c..6612359649c 100644
--- a/src/test/compile-fail/hygiene/nested_macro_privacy.rs
+++ b/src/test/ui/hygiene/nested_macro_privacy.rs
diff --git a/src/test/ui/hygiene/nested_macro_privacy.stderr b/src/test/ui/hygiene/nested_macro_privacy.stderr
new file mode 100644
index 00000000000..1179065b94c
--- /dev/null
+++ b/src/test/ui/hygiene/nested_macro_privacy.stderr
@@ -0,0 +1,9 @@
+error[E0616]: field `i` of struct `foo::S` is private
+  --> $DIR/nested_macro_privacy.rs:25:5
+   |
+LL |     S::default().i; //~ ERROR field `i` of struct `foo::S` is private
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/compile-fail/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs
index c90c7b3093c..c90c7b3093c 100644
--- a/src/test/compile-fail/hygiene/no_implicit_prelude.rs
+++ b/src/test/ui/hygiene/no_implicit_prelude.rs
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
new file mode 100644
index 00000000000..5753d1a32f7
--- /dev/null
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -0,0 +1,30 @@
+error[E0433]: failed to resolve. Use of undeclared type or module `Vec`
+  --> $DIR/no_implicit_prelude.rs:21:9
+   |
+LL |     fn f() { ::bar::m!(); }
+   |              ------------ in this macro invocation
+...
+LL |         Vec::new(); //~ ERROR failed to resolve
+   |         ^^^ Use of undeclared type or module `Vec`
+
+error[E0601]: `main` function not found in crate `no_implicit_prelude`
+   |
+   = note: consider adding a `main` function to `$DIR/no_implicit_prelude.rs`
+
+error[E0599]: no method named `clone` found for type `()` in the current scope
+  --> $DIR/no_implicit_prelude.rs:22:12
+   |
+LL |     fn f() { ::bar::m!(); }
+   |              ------------ in this macro invocation
+...
+LL |         ().clone() //~ ERROR no method named `clone` found
+   |            ^^^^^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           candidate #1: `use std::clone::Clone;`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0433, E0599, E0601.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/compile-fail/pattern-macro-hygiene.rs b/src/test/ui/hygiene/pattern-macro.rs
index 26d411c9154..26d411c9154 100644
--- a/src/test/compile-fail/pattern-macro-hygiene.rs
+++ b/src/test/ui/hygiene/pattern-macro.rs
diff --git a/src/test/ui/hygiene/pattern-macro.stderr b/src/test/ui/hygiene/pattern-macro.stderr
new file mode 100644
index 00000000000..b26084db02e
--- /dev/null
+++ b/src/test/ui/hygiene/pattern-macro.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/pattern-macro.rs:15:5
+   |
+LL |     x + 1; //~ ERROR cannot find value `x` in this scope
+   |     ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/compile-fail/hygiene/privacy.rs b/src/test/ui/hygiene/privacy.rs
index 987cad187d4..987cad187d4 100644
--- a/src/test/compile-fail/hygiene/privacy.rs
+++ b/src/test/ui/hygiene/privacy.rs
diff --git a/src/test/ui/hygiene/privacy.stderr b/src/test/ui/hygiene/privacy.stderr
new file mode 100644
index 00000000000..808d244e9cd
--- /dev/null
+++ b/src/test/ui/hygiene/privacy.stderr
@@ -0,0 +1,9 @@
+error[E0603]: function `f` is private
+  --> $DIR/privacy.rs:26:9
+   |
+LL |         foo::f() //~ ERROR `f` is private
+   |         ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/compile-fail/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs
index 3bd19cbc0ac..3bd19cbc0ac 100644
--- a/src/test/compile-fail/hygiene/trait_items.rs
+++ b/src/test/ui/hygiene/trait_items.rs
diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr
new file mode 100644
index 00000000000..56d9c585d6f
--- /dev/null
+++ b/src/test/ui/hygiene/trait_items.stderr
@@ -0,0 +1,16 @@
+error[E0599]: no method named `f` found for type `()` in the current scope
+  --> $DIR/trait_items.rs:27:24
+   |
+LL |     fn f() { ::baz::m!(); }
+   |              ------------ in this macro invocation
+...
+LL |     pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
+   |                        ^
+   |
+   = help: items from traits can only be used if the trait is in scope
+   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
+           candidate #1: `use foo::T;`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
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
new file mode 100644
index 00000000000..34ee39c7164
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/dyn-trait.rs:33:16
+   |
+LL |     static_val(x); //~ ERROR cannot infer
+   |                ^
+
+error: free region `'a` does not outlive free region `'static`
+  --> $DIR/dyn-trait.rs:33:5
+   |
+LL |     static_val(x); //~ ERROR cannot infer
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/in-band-lifetimes/mismatched.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched.nll.stderr
new file mode 100644
index 00000000000..0930583a7ee
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched.nll.stderr
@@ -0,0 +1,32 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/mismatched.rs:14:42
+   |
+LL | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y } //~ ERROR explicit lifetime required
+   |                                          ^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/mismatched.rs:16:46
+   |
+LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatch
+   |                                              ^
+
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/mismatched.rs:14:42
+   |
+LL | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y } //~ ERROR explicit lifetime required
+   |                    -                     ^ lifetime `'a` required
+   |                    |
+   |                    consider changing the type of `y` to `&'a u32`
+
+error[E0623]: lifetime mismatch
+  --> $DIR/mismatched.rs:16:46
+   |
+LL | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y } //~ ERROR lifetime mismatch
+   |                        -------     -------   ^ ...but data from `y` is returned here
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0621, E0623.
+For more information about an error, try `rustc --explain E0621`.
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr
new file mode 100644
index 00000000000..5e42cab9974
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/mismatched_trait.rs:16:9
+   |
+LL |         y //~ ERROR explicit lifetime required
+   |         ^
+
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/mismatched_trait.rs:16:9
+   |
+LL |     fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 {
+   |                               - consider changing the type of `y` to `&'a u32`
+LL |         y //~ ERROR explicit lifetime required
+   |         ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr b/src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr
new file mode 100644
index 00000000000..546d7b0ed5c
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/mut_while_borrow.nll.stderr
@@ -0,0 +1,13 @@
+error[E0506]: cannot assign to `p` because it is borrowed
+  --> $DIR/mut_while_borrow.rs:19:5
+   |
+LL |     let r = foo(&p);
+   |                 -- borrow of `p` occurs here
+LL |     p += 1; //~ ERROR cannot assign to `p` because it is borrowed
+   |     ^^^^^^ assignment to borrowed `p` occurs here
+LL |     println!("{}", r);
+   |                    - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/issue-13058.nll.stderr b/src/test/ui/issue-13058.nll.stderr
new file mode 100644
index 00000000000..604ad38ad23
--- /dev/null
+++ b/src/test/ui/issue-13058.nll.stderr
@@ -0,0 +1,27 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/issue-13058.rs:24:21
+   |
+LL |     let cont_iter = cont.iter();
+   |                     ^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/issue-13058.rs:24:26
+   |
+LL |     let cont_iter = cont.iter();
+   |                          ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13058.rs:36:11
+   |
+LL |     check((3, 5));
+   |           ^^^^^^
+   |           |
+   |           expected reference, found tuple
+   |           help: consider borrowing here: `&(3, 5)`
+   |
+   = note: expected type `&_`
+              found type `({integer}, {integer})`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issue-17263.nll.stderr b/src/test/ui/issue-17263.nll.stderr
new file mode 100644
index 00000000000..d6009e8078d
--- /dev/null
+++ b/src/test/ui/issue-17263.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-17263.rs:15:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut x: Box<_> = box Foo { a: 1, b: 2 };
+LL | |     let (a, b) = (&mut x.a, &mut x.b);
+LL | |     //~^ ERROR cannot borrow `x` (via `x.b`) as mutable more than once at a time
+...  |
+LL | |     //~^ ERROR cannot borrow `foo` (via `foo.b`) as immutable
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-17263.rs b/src/test/ui/issue-17263.rs
index 242327e93ce..b251f9a4152 100644
--- a/src/test/ui/issue-17263.rs
+++ b/src/test/ui/issue-17263.rs
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(box_syntax)]
+#![feature(box_syntax, rustc_attrs)]
 
 struct Foo { a: isize, b: isize }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut x: Box<_> = box Foo { a: 1, b: 2 };
     let (a, b) = (&mut x.a, &mut x.b);
     //~^ ERROR cannot borrow `x` (via `x.b`) as mutable more than once at a time
diff --git a/src/test/ui/issue-21600.nll.stderr b/src/test/ui/issue-21600.nll.stderr
new file mode 100644
index 00000000000..b5b9cefb706
--- /dev/null
+++ b/src/test/ui/issue-21600.nll.stderr
@@ -0,0 +1,15 @@
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/issue-21600.rs:24:20
+   |
+LL |         call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
+   |                    ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/issue-21600.rs:24:17
+   |
+LL |         call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
+   |                 ^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issue-25793.nll.stderr b/src/test/ui/issue-25793.nll.stderr
new file mode 100644
index 00000000000..05ba186c6bb
--- /dev/null
+++ b/src/test/ui/issue-25793.nll.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/issue-25793.rs:32:1
+   |
+LL | fn main() { #![rustc_error] } // rust-lang/rust#49855
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-25793.rs b/src/test/ui/issue-25793.rs
index 4f3d29216e4..8624527145c 100644
--- a/src/test/ui/issue-25793.rs
+++ b/src/test/ui/issue-25793.rs
@@ -7,7 +7,7 @@
 // <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)]
 macro_rules! width(
     ($this:expr) => {
         $this.width.unwrap()
@@ -29,4 +29,4 @@ impl HasInfo {
     }
 }
 
-fn main() {}
+fn main() { #![rustc_error] } // rust-lang/rust#49855
diff --git a/src/test/ui/issue-36400.nll.stderr b/src/test/ui/issue-36400.nll.stderr
new file mode 100644
index 00000000000..040e6300af6
--- /dev/null
+++ b/src/test/ui/issue-36400.nll.stderr
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/issue-36400.rs:15:7
+   |
+LL |     f(&mut *x); //~ ERROR cannot borrow immutable
+   |       ^^^^^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.nll.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.nll.stderr
new file mode 100644
index 00000000000..48e27014792
--- /dev/null
+++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.nll.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-40402-1.rs:19:13
+   |
+LL |     let e = f.v[0]; //~ ERROR cannot move out of indexed content
+   |             ^^^^^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-2.nll.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-2.nll.stderr
new file mode 100644
index 00000000000..0b907c5acf1
--- /dev/null
+++ b/src/test/ui/issue-40402-ref-hints/issue-40402-2.nll.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-40402-2.rs:15:10
+   |
+LL |     let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
+   |          ^ cannot move out of borrowed content
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-40402-2.rs:15:13
+   |
+LL |     let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
+   |             ^ cannot move out of borrowed content
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issue-42106.nll.stderr b/src/test/ui/issue-42106.nll.stderr
new file mode 100644
index 00000000000..cae04aaedfd
--- /dev/null
+++ b/src/test/ui/issue-42106.nll.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/issue-42106.rs:16:1
+   |
+LL | fn main() { #![rustc_error] } // rust-lang/rust#49855
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-42106.rs b/src/test/ui/issue-42106.rs
index f35eee186a2..96f410578ce 100644
--- a/src/test/ui/issue-42106.rs
+++ b/src/test/ui/issue-42106.rs
@@ -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.
-
+#![feature(rustc_attrs)]
 fn do_something<T>(collection: &mut Vec<T>) {
     let _a = &collection;
     collection.swap(1, 2); //~ ERROR also borrowed as immutable
 }
 
-fn main() {}
+fn main() { #![rustc_error] } // rust-lang/rust#49855
diff --git a/src/test/ui/issue-4335.nll.stderr b/src/test/ui/issue-4335.nll.stderr
new file mode 100644
index 00000000000..7f4273bc8c7
--- /dev/null
+++ b/src/test/ui/issue-4335.nll.stderr
@@ -0,0 +1,25 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/issue-4335.rs:16:20
+   |
+LL |     id(Box::new(|| *v))
+   |                    ^^ cannot move out of borrowed content
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/issue-4335.rs:16:17
+   |
+LL |     id(Box::new(|| *v))
+   |                 ^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'r as defined on the function body at 15:1...
+  --> $DIR/issue-4335.rs:15:1
+   |
+LL | fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0507, E0597.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issue-45697-1.nll.stderr b/src/test/ui/issue-45697-1.nll.stderr
new file mode 100644
index 00000000000..cf108691a0e
--- /dev/null
+++ b/src/test/ui/issue-45697-1.nll.stderr
@@ -0,0 +1,34 @@
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
+  --> $DIR/issue-45697-1.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                        - borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+
+error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
+  --> $DIR/issue-45697-1.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `y` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
+  --> $DIR/issue-45697-1.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0503, E0506.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issue-45697.nll.stderr b/src/test/ui/issue-45697.nll.stderr
new file mode 100644
index 00000000000..a85972fcd7a
--- /dev/null
+++ b/src/test/ui/issue-45697.nll.stderr
@@ -0,0 +1,34 @@
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
+  --> $DIR/issue-45697.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                        - borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+
+error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
+  --> $DIR/issue-45697.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `y` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
+  --> $DIR/issue-45697.rs:30:9
+   |
+LL |         let z = copy_borrowed_ptr(&mut y);
+   |                                   ------ borrow of `*y.pointer` occurs here
+LL |         *y.pointer += 1;
+   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+...
+LL |         *z.pointer += 1;
+   |         --------------- borrow later used here
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0503, E0506.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/issue-46471-1.nll.stderr b/src/test/ui/issue-46471-1.nll.stderr
new file mode 100644
index 00000000000..0108056bc72
--- /dev/null
+++ b/src/test/ui/issue-46471-1.nll.stderr
@@ -0,0 +1,28 @@
+error[E0597]: `z` does not live long enough (Ast)
+  --> $DIR/issue-46471-1.rs:16:14
+   |
+LL |         &mut z
+   |              ^ borrowed value does not live long enough
+LL |     };
+   |     - `z` dropped here while still borrowed
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error[E0597]: `z` does not live long enough (Mir)
+  --> $DIR/issue-46471-1.rs:16:9
+   |
+LL |       let y = {
+   |  _____________-
+LL | |         let mut z = 0;
+LL | |         &mut z
+   | |         ^^^^^^ borrowed value does not live long enough
+LL | |     };
+   | |     -
+   | |     |
+   | |_____borrowed value only lives until here
+   |       borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs
index e339716289c..c59a9bc4170 100644
--- a/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs
+++ b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.rs
@@ -16,7 +16,7 @@ struct Verdict(Guilty, Option<FineDollars>);
 fn main() {
     let justice = Verdict(true, Some(2718));
     let _condemned = justice.00;
-    //~^ ERROR invalid tuple or struct index
+    //~^ ERROR no field `00` on type `Verdict`
     let _punishment = justice.001;
-    //~^ ERROR invalid tuple or struct index
+    //~^ ERROR no field `001` on type `Verdict`
 }
diff --git a/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr
index 9603ac01fef..4a1c9b554a9 100644
--- a/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr
+++ b/src/test/ui/issue-47073-zero-padded-tuple-struct-indices.stderr
@@ -1,14 +1,17 @@
-error: invalid tuple or struct index
+error[E0609]: no field `00` on type `Verdict`
   --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:18:30
    |
 LL |     let _condemned = justice.00;
-   |                              ^^ help: try simplifying the index: `0`
+   |                              ^^ did you mean `0`?
 
-error: invalid tuple or struct index
+error[E0609]: no field `001` on type `Verdict`
   --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:20:31
    |
 LL |     let _punishment = justice.001;
-   |                               ^^^ help: try simplifying the index: `1`
+   |                               ^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr
new file mode 100644
index 00000000000..62ccea36bd3
--- /dev/null
+++ b/src/test/ui/lifetime-errors/42701_one_named_and_one_anonymous.nll.stderr
@@ -0,0 +1,22 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/42701_one_named_and_one_anonymous.rs:20:9
+   |
+LL |         &*x //~ ERROR explicit lifetime
+   |         ^^^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/42701_one_named_and_one_anonymous.rs:16:5
+   |
+LL |   fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 {
+   |                           - consider changing the type of `x` to `&'a i32`
+LL | /     if true {
+LL | |         let p: &i32 = &a.field;
+LL | |         &*p
+LL | |     } else {
+LL | |         &*x //~ ERROR explicit lifetime
+LL | |     }
+   | |_____^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
new file mode 100644
index 00000000000..78546594ef0
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.nll.stderr
@@ -0,0 +1,23 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21
+   |
+LL |                     other //~ ERROR explicit lifetime
+   |                     ^^^^^
+
+error[E0621]: explicit lifetime required in the type of `other`
+  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:18:9
+   |
+LL |       fn bar(&self, other: Foo) -> Foo<'a> {
+   |                     ----- consider changing the type of `other` to `Foo<'a>`
+LL | /         match *self {
+LL | |             Foo::Bar(s) => {
+LL | |                 if s == "test" {
+LL | |                     other //~ ERROR explicit lifetime
+...  |
+LL | |             }
+LL | |         }
+   | |_________^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr
new file mode 100644
index 00000000000..11bb1df3c78
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
+   |
+LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
+   |                ^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:8
+   |
+LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |            - consider changing the type of `x` to `&'a i32`
+LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
+   |        ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr
new file mode 100644
index 00000000000..a619e6ca964
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.nll.stderr
@@ -0,0 +1,18 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
+   |
+LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
+   |                           ^
+
+error[E0621]: explicit lifetime required in parameter type
+  --> $DIR/ex1-return-one-existing-name-if-else-3.rs:11:13
+   |
+LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
+   |            -^----
+   |            ||
+   |            |lifetime `'a` required
+   |            consider changing type to `(&'a i32, &'a i32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr
new file mode 100644
index 00000000000..92245173ce8
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
+   |
+LL |    if x > y { x } else { y } //~ ERROR explicit lifetime
+   |               ^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:7
+   |
+LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |            - consider changing the type of `x` to `&'a i32`
+LL |    if x > y { x } else { y } //~ ERROR explicit lifetime
+   |       ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr
new file mode 100644
index 00000000000..32ef068b8b9
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.nll.stderr
@@ -0,0 +1,18 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
+   |
+LL |     if true { &self.field } else { x } //~ ERROR explicit lifetime
+   |                                    ^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:5
+   |
+LL |   fn foo<'a>(&'a self, x: &i32) -> &i32 {
+   |                        - consider changing the type of `x` to `&'a i32`
+LL | 
+LL |     if true { &self.field } else { x } //~ ERROR explicit lifetime
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
new file mode 100644
index 00000000000..fd10b0d338c
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr
@@ -0,0 +1,20 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
+   |
+LL |         if x > y { x } else { y } //~ ERROR lifetime mismatch
+   |                    ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:12
+   |
+LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |                   ----                 -------
+   |                   |
+   |                   this parameter and the return type are declared with different lifetimes...
+LL | 
+LL |         if x > y { x } else { y } //~ ERROR lifetime mismatch
+   |            ^^^^^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr
new file mode 100644
index 00000000000..f17b24a0aca
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
+   |
+LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
+   |                           ^
+
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex1-return-one-existing-name-if-else.rs:12:8
+   |
+LL | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
+   |                        - consider changing the type of `y` to `&'a i32`
+LL |     if x > y { x } else { y } //~ ERROR explicit lifetime
+   |        ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
new file mode 100644
index 00000000000..b1663fe5eb6
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr
@@ -0,0 +1,20 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
+   |
+LL |     x //~ ERROR lifetime mismatch
+   |     ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
+   |
+LL |   fn foo<'a>(&self, x: &'a i32) -> &i32 {
+   |                        -------     ----
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+LL | 
+LL |     x //~ ERROR lifetime mismatch
+   |     ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
new file mode 100644
index 00000000000..19b8bd2f780
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr
@@ -0,0 +1,20 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
+   |
+LL |         if true { x } else { self } //~ ERROR lifetime mismatch
+   |                              ^^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:9
+   |
+LL |     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+   |                -----                 -------
+   |                |
+   |                this parameter and the return type are declared with different lifetimes...
+LL | 
+LL |         if true { x } else { self } //~ ERROR lifetime mismatch
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...but data from `self` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr
new file mode 100644
index 00000000000..0b34e464b4b
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2a-push-one-existing-name-2.rs:16:12
+   |
+LL |     y.push(x); //~ ERROR explicit lifetime
+   |            ^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex2a-push-one-existing-name-2.rs:16:5
+   |
+LL | fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
+   |            - consider changing the type of `x` to `Ref<'a, i32>`
+LL |     y.push(x); //~ ERROR explicit lifetime
+   |     ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
new file mode 100644
index 00000000000..212b39966aa
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12
+   |
+LL |     x.push(y); //~ ERROR explicit lifetime required
+   |            ^
+
+error[E0282]: type annotations needed
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:20:9
+   |
+LL | let x = baz;
+   |     -   ^^^ cannot infer type for `T`
+   |     |
+   |     consider giving `x` a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr
new file mode 100644
index 00000000000..ad39028154a
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2a-push-one-existing-name.rs:16:12
+   |
+LL |     x.push(y); //~ ERROR explicit lifetime
+   |            ^
+
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name.rs:16:5
+   |
+LL | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
+   |                                       - consider changing the type of `y` to `Ref<'a, i32>`
+LL |     x.push(y); //~ ERROR explicit lifetime
+   |     ^ lifetime `'a` required
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr
new file mode 100644
index 00000000000..34daea7c9f4
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2b-push-no-existing-names.rs:16:12
+   |
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |            ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2b-push-no-existing-names.rs:16:5
+   |
+LL | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
+   |                    --------      -------- these two types are declared with different lifetimes...
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |     ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr
new file mode 100644
index 00000000000..96baa5c8ad2
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2c-push-inference-variable.rs:16:13
+   |
+LL |     let z = Ref { data: y.data };
+   |             ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2c-push-inference-variable.rs:16:9
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+LL |     let z = Ref { data: y.data };
+   |         ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
new file mode 100644
index 00000000000..e5d47689b49
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2d-push-inference-variable-2.rs:17:13
+   |
+LL |     let b = Ref { data: y.data };
+   |             ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2d-push-inference-variable-2.rs:16:9
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+LL |     let a: &mut Vec<Ref<i32>> = x; //~ ERROR lifetime mismatch
+   |         ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
new file mode 100644
index 00000000000..668752f8e02
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex2e-push-inference-variable-3.rs:17:13
+   |
+LL |     let b = Ref { data: y.data };
+   |             ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex2e-push-inference-variable-3.rs:16:9
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
+   |                                   ------------      ------------ these two types are declared with different lifetimes...
+LL |     let a: &mut Vec<Ref<i32>> = x; //~ ERROR lifetime mismatch
+   |         ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
new file mode 100644
index 00000000000..45234249711
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-2.rs:12:9
+   |
+LL |     v = x; //~ ERROR lifetime mismatch
+   |         ^
+
+error[E0384]: cannot assign twice to immutable variable `v`
+  --> $DIR/ex3-both-anon-regions-2.rs:12:5
+   |
+LL | fn foo((v, w): (&u8, &u8), x: &u8) {
+   |         - first assignment to `v`
+LL |     v = x; //~ ERROR lifetime mismatch
+   |     ^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
new file mode 100644
index 00000000000..581088a9258
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.nll.stderr
@@ -0,0 +1,31 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-3.rs:12:13
+   |
+LL |     z.push((x,y)); //~ ERROR lifetime mismatch
+   |             ^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-3.rs:12:15
+   |
+LL |     z.push((x,y)); //~ ERROR lifetime mismatch
+   |               ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-3.rs:11:33
+   |
+LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                     ---         ^       --- these two types are declared with different lifetimes...
+   |                                 |
+   |                                 ...but data flows into `z` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-3.rs:11:33
+   |
+LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                         ---     ^            --- these two types are declared with different lifetimes...
+   |                                 |
+   |                                 ...but data flows into `z` here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
new file mode 100644
index 00000000000..b15f5f4a0fc
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
+   |
+LL |     x.b = y.b; //~ ERROR lifetime mismatch
+   |           ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:5
+   |
+LL | fn foo(mut x: Ref, y: Ref) {
+   |               ---     --- these two types are declared with different lifetimes...
+LL |     x.b = y.b; //~ ERROR lifetime mismatch
+   |     ^^^^^^^^^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
new file mode 100644
index 00000000000..0ec73c2e778
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr
@@ -0,0 +1,19 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
+   |
+LL |     x.a = x.b; //~ ERROR lifetime mismatch
+   |           ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:5
+   |
+LL | fn foo(mut x: Ref) {
+   |               ---
+   |               |
+   |               this type is declared with multiple lifetimes...
+LL |     x.a = x.b; //~ ERROR lifetime mismatch
+   |     ^^^^^^^^^ ...but data with one lifetime flows into the other here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
new file mode 100644
index 00000000000..727a701d3f2
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr
@@ -0,0 +1,19 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:11
+   |
+LL |     x.a = x.b; //~ ERROR lifetime mismatch
+   |           ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:5
+   |
+LL | fn foo(mut x: Ref) {
+   |               ---
+   |               |
+   |               this type is declared with multiple lifetimes...
+LL |     x.a = x.b; //~ ERROR lifetime mismatch
+   |     ^^^^^^^^^ ...but data with one lifetime flows into the other here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
new file mode 100644
index 00000000000..f010c87377e
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.nll.stderr
@@ -0,0 +1,18 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:12
+   |
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |            ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:5
+   |
+LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
+   |                           -------      ------- these two types are declared with different lifetimes...
+...
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |     ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
new file mode 100644
index 00000000000..2b48b176ae8
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:12
+   |
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |            ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:5
+   |
+LL | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
+   |                           -------      ------- these two types are declared with different lifetimes...
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |     ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr
new file mode 100644
index 00000000000..c9ac04cb01e
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
+   |
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |            ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:5
+   |
+LL | fn foo(mut x: Vec<Ref>, y: Ref) {
+   |                   ---      --- these two types are declared with different lifetimes...
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |     ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
new file mode 100644
index 00000000000..9c7fc8ac458
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-latebound-regions.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-latebound-regions.rs:12:12
+   |
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |            ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-latebound-regions.rs:12:5
+   |
+LL | fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) {
+   |                           ------      ------ these two types are declared with different lifetimes...
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |     ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
new file mode 100644
index 00000000000..85a0b7c1345
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr
@@ -0,0 +1,28 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
+   |
+LL |     y = x.b; //~ ERROR lifetime mismatch
+   |         ^^^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
+   |
+LL | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ----
+   |               |
+   |               these two types are declared with different lifetimes...
+LL |     y = x.b; //~ ERROR lifetime mismatch
+   |     ^^^^^^^ ...but data from `x` flows into `y` here
+
+error[E0384]: cannot assign to immutable argument `y`
+  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
+   |
+LL | fn foo(mut x: Ref, y: &u32) {
+   |                    - argument not declared as `mut`
+LL |     y = x.b; //~ ERROR lifetime mismatch
+   |     ^^^^^^^ cannot assign to immutable argument
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0384, E0623.
+For more information about an error, try `rustc --explain E0384`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
new file mode 100644
index 00000000000..4e160001b87
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
+   |
+LL |     y.b = x; //~ ERROR lifetime mismatch
+   |           ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:5
+   |
+LL | fn foo(mut y: Ref, x: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+LL |     y.b = x; //~ ERROR lifetime mismatch
+   |     ^^^^^^^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
new file mode 100644
index 00000000000..7bbc3c4084f
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:11
+   |
+LL |     y.b = x; //~ ERROR lifetime mismatch
+   |           ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:5
+   |
+LL | fn foo(mut y: Ref, x: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+LL |     y.b = x; //~ ERROR lifetime mismatch
+   |     ^^^^^^^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
new file mode 100644
index 00000000000..9fd7bbac247
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
+   |
+LL |     x.b = y; //~ ERROR lifetime mismatch
+   |           ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:5
+   |
+LL | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+LL |     x.b = y; //~ ERROR lifetime mismatch
+   |     ^^^^^^^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
new file mode 100644
index 00000000000..528a846991c
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr
@@ -0,0 +1,19 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
+   |
+LL |     x //~ ERROR lifetime mismatch
+   |     ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
+   |
+LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
+   |                        ----     ----
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+LL |     x //~ ERROR lifetime mismatch
+   |     ^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
new file mode 100644
index 00000000000..f8c0b5940c9
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr
@@ -0,0 +1,19 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
+   |
+LL |         if true { x } else { self } //~ ERROR lifetime mismatch
+   |                   ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:9
+   |
+LL |     fn foo<'a>(&self, x: &Foo) -> &Foo {
+   |                          ----     ----
+   |                          |
+   |                          this parameter and the return type are declared with different lifetimes...
+LL |         if true { x } else { self } //~ ERROR lifetime mismatch
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...but data from `x` is returned here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
new file mode 100644
index 00000000000..284f760435c
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr
@@ -0,0 +1,24 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:10
+   |
+LL |   y.push(z); //~ ERROR lifetime mismatch
+   |          ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3
+   |
+LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
+   |                               ---      --- these two types are declared with different lifetimes...
+LL |   y.push(z); //~ ERROR lifetime mismatch
+   |   ^ ...but data from `z` flows into `y` here
+
+error[E0596]: cannot borrow immutable item `y` as mutable
+  --> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3
+   |
+LL |   y.push(z); //~ ERROR lifetime mismatch
+   |   ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0596, E0623.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
new file mode 100644
index 00000000000..389549a8464
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
+   |
+LL |         x.push(y); //~ ERROR lifetime mismatch
+   |                ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:9
+   |
+LL |     fn foo(x: &mut Vec<&u8>, y: &u8) {
+   |                        ---      --- these two types are declared with different lifetimes...
+LL |         x.push(y); //~ ERROR lifetime mismatch
+   |         ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
new file mode 100644
index 00000000000..185ea89275f
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr
@@ -0,0 +1,24 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:10
+   |
+LL |   y.push(z); //~ ERROR lifetime mismatch
+   |          ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3
+   |
+LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+   |                 ---  --- these two types are declared with different lifetimes...
+LL |   y.push(z); //~ ERROR lifetime mismatch
+   |   ^ ...but data from `z` flows into `y` here
+
+error[E0596]: cannot borrow immutable item `y` as mutable
+  --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3
+   |
+LL |   y.push(z); //~ ERROR lifetime mismatch
+   |   ^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0596, E0623.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr
new file mode 100644
index 00000000000..629a97ab5ca
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.nll.stderr
@@ -0,0 +1,17 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/ex3-both-anon-regions.rs:12:12
+   |
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |            ^
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions.rs:12:5
+   |
+LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
+   |                    ---      --- these two types are declared with different lifetimes...
+LL |     x.push(y); //~ ERROR lifetime mismatch
+   |     ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr
new file mode 100644
index 00000000000..d13f9ccc37d
--- /dev/null
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/borrowck-let-suggestion.rs:15:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     f();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.rs b/src/test/ui/lifetimes/borrowck-let-suggestion.rs
index 1c904648f9e..a7a7d5c5035 100644
--- a/src/test/ui/lifetimes/borrowck-let-suggestion.rs
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.rs
@@ -7,11 +7,11 @@
 // <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)]
 fn f() {
     let x = vec![1].iter();
 }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     f();
 }
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.rs b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
index 58a30e86f22..bff64ad4892 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.rs
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.rs
@@ -24,7 +24,7 @@ macro_rules! fake_field_stmt {
 
 macro_rules! fake_anon_field_stmt {
      () => {
-          (1).0 //~ ERROR no field
+          (1).0 //~ ERROR doesn't have fields
      }
 }
 
@@ -42,7 +42,7 @@ macro_rules! fake_field_expr {
 
 macro_rules! fake_anon_field_expr {
      () => {
-          (1).0 //~ ERROR no field
+          (1).0 //~ ERROR doesn't have fields
      }
 }
 
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
index eab6cd23748..cb7d422b7f3 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
@@ -16,11 +16,11 @@ LL |           1.fake //~ ERROR doesn't have fields
 LL |     fake_field_stmt!();
    |     ------------------- in this macro invocation
 
-error[E0609]: no field `0` on type `{integer}`
-  --> $DIR/macro-backtrace-invalid-internals.rs:27:11
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/macro-backtrace-invalid-internals.rs:27:15
    |
-LL |           (1).0 //~ ERROR no field
-   |           ^^^^^
+LL |           (1).0 //~ ERROR doesn't have fields
+   |               ^
 ...
 LL |     fake_anon_field_stmt!();
    |     ------------------------ in this macro invocation
@@ -56,11 +56,11 @@ LL |           1.fake //~ ERROR doesn't have fields
 LL |     let _ = fake_field_expr!();
    |             ------------------ in this macro invocation
 
-error[E0609]: no field `0` on type `{integer}`
-  --> $DIR/macro-backtrace-invalid-internals.rs:45:11
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/macro-backtrace-invalid-internals.rs:45:15
    |
-LL |           (1).0 //~ ERROR no field
-   |           ^^^^^
+LL |           (1).0 //~ ERROR doesn't have fields
+   |               ^
 ...
 LL |     let _ = fake_anon_field_expr!();
    |             ----------------------- in this macro invocation
@@ -80,5 +80,5 @@ LL |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous n
 
 error: aborting due to 8 previous errors
 
-Some errors occurred: E0599, E0609, E0610, E0689.
+Some errors occurred: E0599, E0610, E0689.
 For more information about an error, try `rustc --explain E0599`.
diff --git a/src/test/ui/macros/span-covering-argument-1.nll.stderr b/src/test/ui/macros/span-covering-argument-1.nll.stderr
new file mode 100644
index 00000000000..a12baab4159
--- /dev/null
+++ b/src/test/ui/macros/span-covering-argument-1.nll.stderr
@@ -0,0 +1,12 @@
+error[E0596]: cannot borrow immutable item `foo` as mutable
+  --> $DIR/span-covering-argument-1.rs:15:14
+   |
+LL |             *&mut $s = 0;
+   |              ^^^^^^^ cannot borrow as mutable
+...
+LL |     bad!(foo whatever);
+   |     ------------------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/moves-based-on-type-block-bad.nll.stderr b/src/test/ui/moves-based-on-type-block-bad.nll.stderr
new file mode 100644
index 00000000000..942d9816c4e
--- /dev/null
+++ b/src/test/ui/moves-based-on-type-block-bad.nll.stderr
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/moves-based-on-type-block-bad.rs:37:28
+   |
+LL |                 box E::Bar(x) => println!("{}", x.to_string()),
+   |                            ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/moves-based-on-type-match-bindings.nll.stderr b/src/test/ui/moves-based-on-type-match-bindings.nll.stderr
new file mode 100644
index 00000000000..6ebbf670acd
--- /dev/null
+++ b/src/test/ui/moves-based-on-type-match-bindings.nll.stderr
@@ -0,0 +1,14 @@
+error[E0382]: borrow of moved value: `x`
+  --> $DIR/moves-based-on-type-match-bindings.rs:26:11
+   |
+LL |         Foo {f} => {}
+   |              - value moved here
+...
+LL |     touch(&x); //~ ERROR use of partially moved value: `x`
+   |           ^^ value borrowed here after move
+   |
+   = note: move occurs because `x` has type `Foo<std::string::String>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/nll/get_default.nll.stderr b/src/test/ui/nll/get_default.nll.stderr
new file mode 100644
index 00000000000..c6f021f8c36
--- /dev/null
+++ b/src/test/ui/nll/get_default.nll.stderr
@@ -0,0 +1,51 @@
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/get_default.rs:33:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+...
+LL |                 map.set(String::new()); // Just AST errors here
+   |                 ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/get_default.rs:44:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+LL |             Some(v) => {
+LL |                 map.set(String::new()); // Both AST and MIR error here
+   |                 ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Ast)
+  --> $DIR/get_default.rs:50:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+...
+LL |                 map.set(String::new()); // Just AST errors here
+   |                 ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
+  --> $DIR/get_default.rs:44:17
+   |
+LL |         match map.get() {
+   |               --- immutable borrow occurs here
+LL |             Some(v) => {
+LL |                 map.set(String::new()); // Both AST and MIR error here
+   |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+...
+LL |                 return v;
+   |                        - borrow later used here
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/nll/issue-16223.rs b/src/test/ui/nll/issue-16223.rs
new file mode 100644
index 00000000000..64fc3df30b9
--- /dev/null
+++ b/src/test/ui/nll/issue-16223.rs
@@ -0,0 +1,63 @@
+// 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.
+
+// Regression test for #16223: without NLL the `if let` construct together with
+// the nested box-structure of `Root` causes an unwanted collateral move.
+
+// The exact error prevented here is:
+//
+// error[E0382]: use of collaterally moved value: `(root.boxed.rhs as SomeVariant::B).0`
+//   --> src/main.rs:55:29
+//    |
+// 56 |         lhs: SomeVariant::A(a),
+//    |                             - value moved here
+// 57 |         rhs: SomeVariant::B(b),
+//    |                             ^ value used here after move
+//    |
+//    = note: move occurs because the value has type `A`, which does not implement the `Copy` trait
+
+// must-compile-successfully
+
+#![feature(nll)]
+#![feature(box_patterns)]
+
+struct Root {
+    boxed: Box<SetOfVariants>,
+}
+
+struct SetOfVariants {
+    lhs: SomeVariant,
+    rhs: SomeVariant,
+}
+
+enum SomeVariant {
+    A(A),
+    B(B),
+}
+
+struct A(String);
+struct B(String);
+
+fn main() {
+    let root = Root {
+        boxed: Box::new(SetOfVariants {
+            lhs: SomeVariant::A(A(String::from("This is A"))),
+            rhs: SomeVariant::B(B(String::from("This is B"))),
+        }),
+    };
+    if let box SetOfVariants {
+        lhs: SomeVariant::A(a),
+        rhs: SomeVariant::B(b),
+    } = root.boxed
+    {
+        println!("a = {}", a.0);
+        println!("b = {}", b.0);
+    }
+}
diff --git a/src/test/ui/nll/issue-47388.rs b/src/test/ui/nll/issue-47388.rs
new file mode 100644
index 00000000000..39feea08aa4
--- /dev/null
+++ b/src/test/ui/nll/issue-47388.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.
+#![feature(nll)]
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; //~ ERROR E0594
+    println!("{}", fancy_ref.num);
+}
diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr
new file mode 100644
index 00000000000..272cb6510aa
--- /dev/null
+++ b/src/test/ui/nll/issue-47388.stderr
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/issue-47388.rs:18:5
+   |
+LL |     let fancy_ref = &(&mut fancy);
+   |                     ------------- help: consider changing this to be a mutable reference: `&mut`
+LL |     fancy_ref.num = 6; //~ ERROR E0594
+   |     ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/order-dependent-cast-inference.rs b/src/test/ui/order-dependent-cast-inference.rs
new file mode 100644
index 00000000000..afcd402343b
--- /dev/null
+++ b/src/test/ui/order-dependent-cast-inference.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.
+
+fn main() {
+    // Tests case where inference fails due to the order in which casts are checked.
+    // Ideally this would compile, see #48270.
+    let x = &"hello";
+    let mut y = 0 as *const _;
+    //~^ ERROR cannot cast to a pointer of an unknown kind
+    y = x as *const _;
+}
diff --git a/src/test/ui/order-dependent-cast-inference.stderr b/src/test/ui/order-dependent-cast-inference.stderr
new file mode 100644
index 00000000000..556acc87cff
--- /dev/null
+++ b/src/test/ui/order-dependent-cast-inference.stderr
@@ -0,0 +1,13 @@
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/order-dependent-cast-inference.rs:15:17
+   |
+LL |     let mut y = 0 as *const _;
+   |                 ^^^^^--------
+   |                      |
+   |                      help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0641`.
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
index a4288f67899..5d8c9326258 100644
--- a/src/test/ui/print_type_sizes/packed.rs
+++ b/src/test/ui/print_type_sizes/packed.rs
@@ -21,10 +21,34 @@
 
 #![allow(dead_code)]
 #![feature(start)]
+#![feature(repr_packed)]
 
 #[derive(Default)]
 #[repr(packed)]
-struct Packed {
+struct Packed1 {
+    a: u8,
+    b: u8,
+    g: i32,
+    c: u8,
+    h: i16,
+    d: u8,
+}
+
+#[derive(Default)]
+#[repr(packed(2))]
+struct Packed2 {
+    a: u8,
+    b: u8,
+    g: i32,
+    c: u8,
+    h: i16,
+    d: u8,
+}
+
+#[derive(Default)]
+#[repr(packed(2))]
+#[repr(C)]
+struct Packed2C {
     a: u8,
     b: u8,
     g: i32,
@@ -45,7 +69,9 @@ struct Padded {
 
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    let _c: Packed = Default::default();
-    let _d: Padded = Default::default();
+    let _c: Packed1 = Default::default();
+    let _d: Packed2 = Default::default();
+    let _e: Packed2C = Default::default();
+    let _f: Padded = Default::default();
     0
 }
diff --git a/src/test/ui/print_type_sizes/packed.stdout b/src/test/ui/print_type_sizes/packed.stdout
index 83fd333c9c7..58e1bac9eb7 100644
--- a/src/test/ui/print_type_sizes/packed.stdout
+++ b/src/test/ui/print_type_sizes/packed.stdout
@@ -1,3 +1,12 @@
+print-type-size type: `Packed2C`: 12 bytes, alignment: 2 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.c`: 1 bytes
+print-type-size     padding: 1 bytes
+print-type-size     field `.h`: 2 bytes
+print-type-size     field `.d`: 1 bytes
+print-type-size     end padding: 1 bytes
 print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
 print-type-size     field `.g`: 4 bytes
 print-type-size     field `.h`: 2 bytes
@@ -6,10 +15,17 @@ print-type-size     field `.b`: 1 bytes
 print-type-size     field `.c`: 1 bytes
 print-type-size     field `.d`: 1 bytes
 print-type-size     end padding: 2 bytes
-print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
+print-type-size type: `Packed1`: 10 bytes, alignment: 1 bytes
 print-type-size     field `.a`: 1 bytes
 print-type-size     field `.b`: 1 bytes
 print-type-size     field `.g`: 4 bytes
 print-type-size     field `.c`: 1 bytes
 print-type-size     field `.h`: 2 bytes
 print-type-size     field `.d`: 1 bytes
+print-type-size type: `Packed2`: 10 bytes, alignment: 2 bytes
+print-type-size     field `.g`: 4 bytes
+print-type-size     field `.h`: 2 bytes
+print-type-size     field `.a`: 1 bytes
+print-type-size     field `.b`: 1 bytes
+print-type-size     field `.c`: 1 bytes
+print-type-size     field `.d`: 1 bytes
diff --git a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr
new file mode 100644
index 00000000000..1a53c033baa
--- /dev/null
+++ b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr
@@ -0,0 +1,279 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:19:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |      - borrowed value only lives until here
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:19:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |      - borrowed value only lives until here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:34:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |      - borrowed value only lives until here
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:34:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |      - borrowed value only lives until here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:65:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 64:5...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:64:5
+   |
+LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:65:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 64:5...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:64:5
+   |
+LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:76:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 75:5...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:75:5
+   |
+LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:76:17
+   |
+LL |         let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 75:5...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:75:5
+   |
+LL |     fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:100:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 99:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:99:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:100:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 99:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:99:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:114:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 113:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:113:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:114:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 113:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:113:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:142:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 141:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:141:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:142:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 141:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:141:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:157:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 156:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:156:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:157:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 156:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:156:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:185:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 184:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:184:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:185:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 184:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:184:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:199:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 198:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:198:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0597]: `y` does not live long enough
+  --> $DIR/region-borrow-params-issue-29793-small.rs:199:21
+   |
+LL |             let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL |         }
+   |         - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the method body at 198:9...
+  --> $DIR/region-borrow-params-issue-29793-small.rs:198:9
+   |
+LL |         fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions-nested-fns-2.nll.stderr b/src/test/ui/regions-nested-fns-2.nll.stderr
new file mode 100644
index 00000000000..2c973f9bdea
--- /dev/null
+++ b/src/test/ui/regions-nested-fns-2.nll.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/regions-nested-fns-2.rs:16:9
+   |
+LL | /         |z| {
+LL | |             //~^ ERROR E0373
+LL | |             if false { &y } else { z }
+LL | |         });
+   | |_________^ borrowed value does not live long enough
+LL |   }
+   |   - borrowed value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
new file mode 100644
index 00000000000..10384e3b7ca
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
@@ -0,0 +1,14 @@
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-issue-49631.rs:30:9
+   |
+LL |     while let Some(Ok(string)) = foo.get() {
+   |                                  --- immutable borrow occurs here
+LL |         foo.mutate();
+   |         ^^^^^^^^^^^^ mutable borrow occurs here
+LL |         //~^ ERROR cannot borrow `foo` as mutable
+LL |         println!("foo={:?}", *string);
+   |                              ------- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr
new file mode 100644
index 00000000000..6ae5f777a93
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/enum.nll.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to immutable item `*x`
+  --> $DIR/enum.rs:19:5
+   |
+LL |     *x += 1; //~ ERROR cannot assign to immutable
+   |     ^^^^^^^ cannot mutate
+
+error[E0594]: cannot assign to immutable item `*x`
+  --> $DIR/enum.rs:23:9
+   |
+LL |         *x += 1; //~ ERROR cannot assign to immutable
+   |         ^^^^^^^ cannot mutate
+
+error[E0594]: cannot assign to immutable item `*x`
+  --> $DIR/enum.rs:29:9
+   |
+LL |         *x += 1; //~ ERROR cannot assign to immutable
+   |         ^^^^^^^ cannot mutate
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr
new file mode 100644
index 00000000000..7138c4ac06e
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/explicit-mut.nll.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to immutable item `*n`
+  --> $DIR/explicit-mut.rs:17:13
+   |
+LL |             *n += 1; //~ ERROR cannot assign to immutable
+   |             ^^^^^^^ cannot mutate
+
+error[E0594]: cannot assign to immutable item `*n`
+  --> $DIR/explicit-mut.rs:25:13
+   |
+LL |             *n += 1; //~ ERROR cannot assign to immutable
+   |             ^^^^^^^ cannot mutate
+
+error[E0594]: cannot assign to immutable item `*n`
+  --> $DIR/explicit-mut.rs:33:13
+   |
+LL |             *n += 1; //~ ERROR cannot assign to immutable
+   |             ^^^^^^^ cannot mutate
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/enum-pass.rs b/src/test/ui/rfc-2093-infer-outlives/enum-pass.rs
new file mode 100644
index 00000000000..8c7275bb1a7
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/enum-pass.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.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+
+// Type T needs to outlive lifetime 'a.
+enum Foo<'a, T> {
+
+    One(Bar<'a, T>)
+}
+
+// Type U needs to outlive lifetime 'b
+struct Bar<'b, U> {
+    field2: &'b U
+}
+
+
+
+// Type K needs to outlive lifetime 'c.
+enum Ying<'c, K> {
+    One(&'c Yang<K>)
+}
+
+struct Yang<V> {
+    field2: V
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/enum.rs b/src/test/ui/rfc-2093-infer-outlives/enum.rs
new file mode 100644
index 00000000000..7d0427adb9f
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/enum.rs
@@ -0,0 +1,37 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type T needs to outlive lifetime 'a.
+enum Foo<'a, T> {
+
+    One(Bar<'a, T>)
+}
+
+// Type U needs to outlive lifetime 'b
+struct Bar<'b, U> {
+    field2: &'b U //~ ERROR 23:5: 23:18: the parameter type `U` may not live long enough [E0309]
+}
+
+
+
+// Type K needs to outlive lifetime 'c.
+enum Ying<'c, K> {
+    One(&'c Yang<K>) //~ ERROR 30:9: 30:21: the parameter type `K` may not live long enough [E0309]
+}
+
+struct Yang<V> {
+    field2: V
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/enum.stderr b/src/test/ui/rfc-2093-infer-outlives/enum.stderr
new file mode 100644
index 00000000000..e6eaf9b4754
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/enum.stderr
@@ -0,0 +1,31 @@
+error[E0309]: the parameter type `U` may not live long enough
+  --> $DIR/enum.rs:23:5
+   |
+LL | struct Bar<'b, U> {
+   |                - help: consider adding an explicit lifetime bound `U: 'b`...
+LL |     field2: &'b U //~ ERROR 23:5: 23:18: the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'b U` does not outlive the data it points at
+  --> $DIR/enum.rs:23:5
+   |
+LL |     field2: &'b U //~ ERROR 23:5: 23:18: the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `K` may not live long enough
+  --> $DIR/enum.rs:30:9
+   |
+LL | enum Ying<'c, K> {
+   |               - help: consider adding an explicit lifetime bound `K: 'c`...
+LL |     One(&'c Yang<K>) //~ ERROR 30:9: 30:21: the parameter type `K` may not live long enough [E0309]
+   |         ^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'c Yang<K>` does not outlive the data it points at
+  --> $DIR/enum.rs:30:9
+   |
+LL |     One(&'c Yang<K>) //~ ERROR 30:9: 30:21: the parameter type `K` may not live long enough [E0309]
+   |         ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-impl-lifetime-pass.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-impl-lifetime-pass.rs
new file mode 100644
index 00000000000..da578386adb
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-impl-lifetime-pass.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// ignore-test
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+trait MakeRef<'a>: 'a {
+    type Type;
+}
+impl<'a, T> MakeRef<'a> for Vec<T>
+where T: 'a,
+{
+    type Type = &'a T;
+}
+// explicit-impl: T: 'a
+struct Foo<'a, T> {
+    foo: <Vec<T> as MakeRef<'a>>::Type,
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-impl-pass.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-impl-pass.rs
new file mode 100644
index 00000000000..fd74fe30bb6
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-impl-pass.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// ignore-test
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+trait MakeRef<'a> {
+    type Type;
+}
+impl<'a, T> MakeRef<'a> for Vec<T>
+where T: 'a,
+{
+    type Type = &'a T;
+}
+// explicit-impl: T: 'a
+struct Foo<'a, T> {
+    foo: <Vec<T> as MakeRef<'a>>::Type,
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-impl.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-impl.rs
new file mode 100644
index 00000000000..3a10087551c
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-impl.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+trait MakeRef<'a> {
+    type Type;
+}
+
+impl<'a, T> MakeRef<'a> for Vec<T>
+  where T: 'a
+{
+    type Type = &'a T;
+}
+
+// Type T needs to outlive lifetime 'a, as stated in impl.
+struct Foo<'a, T> {
+    foo: <Vec<T> as MakeRef<'a>>::Type //~ Error the parameter type `T` may not live long enough [E0309]
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-impl.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-impl.stderr
new file mode 100644
index 00000000000..498d66ef9a5
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-impl.stderr
@@ -0,0 +1,17 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/explicit-impl.rs:27:5
+   |
+LL | struct Foo<'a, T> {
+   |                - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     foo: <Vec<T> as MakeRef<'a>>::Type //~ Error the parameter type `T` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/explicit-impl.rs:27:5
+   |
+LL |     foo: <Vec<T> as MakeRef<'a>>::Type //~ Error the parameter type `T` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-where-pass.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-where-pass.rs
new file mode 100644
index 00000000000..e51b5a16b45
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-where-pass.rs
@@ -0,0 +1,27 @@
+// 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.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+// explicit-where: infer U: 'b
+struct ExFoo<'b, U> {
+    bar: ExBar<'b, U>
+}
+struct ExBar<'a, T> where T: 'a {
+    x: &'a (),
+    y: T,
+}
+
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-where.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-where.rs
new file mode 100644
index 00000000000..81734bf514e
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-where.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type U needs to outlive lifetime 'b.
+struct Foo<'b, U> {
+    bar: Bar<'b, U> //~ Error the parameter type `U` may not live long enough [E0309]
+}
+
+struct Bar<'a, T> where T: 'a {
+    x: &'a (),
+    y: T,
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-where.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-where.stderr
new file mode 100644
index 00000000000..436754c7dc1
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/explicit-where.stderr
@@ -0,0 +1,17 @@
+error[E0309]: the parameter type `U` may not live long enough
+  --> $DIR/explicit-where.rs:15:5
+   |
+LL | struct Foo<'b, U> {
+   |                - help: consider adding an explicit lifetime bound `U: 'b`...
+LL |     bar: Bar<'b, U> //~ Error the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^
+   |
+note: ...so that the type `U` will meet its required lifetime bounds
+  --> $DIR/explicit-where.rs:15:5
+   |
+LL |     bar: Bar<'b, U> //~ Error the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/multiple-regions-pass.rs b/src/test/ui/rfc-2093-infer-outlives/multiple-regions-pass.rs
new file mode 100644
index 00000000000..be686a80048
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/multiple-regions-pass.rs
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+// multiple-regions: infer 'b: 'a
+struct MultiFoo<'a, 'b, T> {
+    x: &'a &'b T
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/multiple-regions.rs b/src/test/ui/rfc-2093-infer-outlives/multiple-regions.rs
new file mode 100644
index 00000000000..7ea1ce2d3dc
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/multiple-regions.rs
@@ -0,0 +1,19 @@
+// 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.
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Lifetime 'b needs to outlive lifetime 'a
+struct Foo<'a,'b,T> {
+    x: &'a &'b T //~ ERROR reference has a longer lifetime than the data it references [E0491]
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/multiple-regions.stderr b/src/test/ui/rfc-2093-infer-outlives/multiple-regions.stderr
new file mode 100644
index 00000000000..3722abd5ad6
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/multiple-regions.stderr
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
+  --> $DIR/multiple-regions.rs:15:5
+   |
+LL |     x: &'a &'b T //~ ERROR reference has a longer lifetime than the data it references [E0491]
+   |     ^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the struct at 14:1
+  --> $DIR/multiple-regions.rs:14:1
+   |
+LL | struct Foo<'a,'b,T> {
+   | ^^^^^^^^^^^^^^^^^^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the struct at 14:1
+  --> $DIR/multiple-regions.rs:14:1
+   |
+LL | struct Foo<'a,'b,T> {
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-structs-pass.rs b/src/test/ui/rfc-2093-infer-outlives/nested-structs-pass.rs
new file mode 100644
index 00000000000..02581457fcc
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-structs-pass.rs
@@ -0,0 +1,25 @@
+// 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.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+// nested-structs: infer U: 'b and therefore T: 'a
+struct NestFoo<'a, T> {
+    field1: NestBar<'a, T>
+}
+struct NestBar<'b, U> {
+    field2: &'b U
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-structs.rs b/src/test/ui/rfc-2093-infer-outlives/nested-structs.rs
new file mode 100644
index 00000000000..7c444dbd3b0
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-structs.rs
@@ -0,0 +1,26 @@
+// 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.
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+
+// Type T needs to outlive lifetime 'a. This is not reported due to
+// a compilation error in Bar.
+struct Foo<'a, T> {
+    field1: Bar<'a, T>
+}
+
+// Type U needs to outlive lifetime 'b
+struct Bar<'b, U> {
+    field2: &'b U //~ ERROR the parameter type `U` may not live long enough [E0309]
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr
new file mode 100644
index 00000000000..94d6cbdb5fe
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr
@@ -0,0 +1,17 @@
+error[E0309]: the parameter type `U` may not live long enough
+  --> $DIR/nested-structs.rs:22:5
+   |
+LL | struct Bar<'b, U> {
+   |                - help: consider adding an explicit lifetime bound `U: 'b`...
+LL |     field2: &'b U //~ ERROR the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'b U` does not outlive the data it points at
+  --> $DIR/nested-structs.rs:22:5
+   |
+LL |     field2: &'b U //~ ERROR the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/projections-pass.rs b/src/test/ui/rfc-2093-infer-outlives/projections-pass.rs
new file mode 100644
index 00000000000..1234e27b866
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/projections-pass.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+// projections: infer <Iterator>::Item: 'a
+struct ProjFoo<'a, T: Iterator> {
+    bar: &'a T::Item
+}
+
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/projections.rs b/src/test/ui/rfc-2093-infer-outlives/projections.rs
new file mode 100644
index 00000000000..f6a557c174c
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/projections.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Needs an explicit where clause stating outlives condition. RFC 2093
+
+// Associated type <Iterator>::Item  needs to outlives lifetime 'a.
+struct Foo<'a, T: Iterator> {
+    bar: &'a T::Item //~ Error the associated type `<T as std::iter::Iterator>::Item` may not live long enough [E0309]
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/projections.stderr b/src/test/ui/rfc-2093-infer-outlives/projections.stderr
new file mode 100644
index 00000000000..9969cf48ecd
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/projections.stderr
@@ -0,0 +1,16 @@
+error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
+  --> $DIR/projections.rs:17:5
+   |
+LL |     bar: &'a T::Item //~ Error the associated type `<T as std::iter::Iterator>::Item` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: 'a`...
+note: ...so that the reference type `&'a <T as std::iter::Iterator>::Item` does not outlive the data it points at
+  --> $DIR/projections.rs:17:5
+   |
+LL |     bar: &'a T::Item //~ Error the associated type `<T as std::iter::Iterator>::Item` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/reference-pass.rs b/src/test/ui/rfc-2093-infer-outlives/reference-pass.rs
new file mode 100644
index 00000000000..f357685e139
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/reference-pass.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+// Outlives requirementes are inferred (RFC 2093)
+
+// reference: infer T: 'a
+struct RefFoo<'a, T> {
+    bar: &'a [T]
+}
+
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/reference.rs b/src/test/ui/rfc-2093-infer-outlives/reference.rs
new file mode 100644
index 00000000000..01ccc50a130
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/reference.rs
@@ -0,0 +1,18 @@
+// 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.
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+// Type T needs to outlive lifetime 'a.
+struct Foo<'a, T> {
+    bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2093-infer-outlives/reference.stderr b/src/test/ui/rfc-2093-infer-outlives/reference.stderr
new file mode 100644
index 00000000000..7236bd535c9
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/reference.stderr
@@ -0,0 +1,17 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/reference.rs:15:5
+   |
+LL | struct Foo<'a, T> {
+   |                - help: consider adding an explicit lifetime bound `T: 'a`...
+LL |     bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a [T]` does not outlive the data it points at
+  --> $DIR/reference.rs:15:5
+   |
+LL |     bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/rfc-2093-infer-outlives/union-pass.rs b/src/test/ui/rfc-2093-infer-outlives/union-pass.rs
new file mode 100644
index 00000000000..b4a61346b01
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/union-pass.rs
@@ -0,0 +1,39 @@
+// 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.
+
+// must-compile-successfully
+
+#![feature(infer_outlives_requirements)]
+#![feature(untagged_unions)]
+#![allow(unions_with_drop_fields)]
+
+// Type T needs to outlive lifetime 'a. This is not reported due to
+// a compilation error in Bar.
+union Foo<'a, T> {
+    field1: Bar<'a, T>
+}
+
+// Type U needs to outlive lifetime 'b
+union Bar<'b, U> {
+    field2: &'b U
+}
+
+
+// Type K needs to outlive lifetime 'c.
+union Ying<'c, K> {
+    field1: &'c Yang<K>
+}
+
+union Yang<V> {
+    field2: V
+}
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/union.rs b/src/test/ui/rfc-2093-infer-outlives/union.rs
new file mode 100644
index 00000000000..36b1dccb13e
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/union.rs
@@ -0,0 +1,40 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Needs an explicit where clause stating outlives condition. (RFC 2093)
+
+#![feature(untagged_unions)]
+
+// Type T needs to outlive lifetime 'a. This is not reported due to
+// a compilation error in Bar.
+union Foo<'a, T> {
+    field1: Bar<'a, T>
+}
+
+// Type U needs to outlive lifetime 'b
+union Bar<'b, U> {
+    field2: &'b U //~ ERROR 25:5: 25:18: the parameter type `U` may not live long enough [E0309]
+}
+
+
+// Type K needs to outlive lifetime 'c.
+union Ying<'c, K> {
+    field1: &'c Yang<K> //~ ERROR 31:5: 31:24: the parameter type `K` may not live long enough [E0309]
+}
+
+union Yang<V> {
+    field2: V
+}
+
+
+fn main() {}
+
diff --git a/src/test/ui/rfc-2093-infer-outlives/union.stderr b/src/test/ui/rfc-2093-infer-outlives/union.stderr
new file mode 100644
index 00000000000..cd13c423293
--- /dev/null
+++ b/src/test/ui/rfc-2093-infer-outlives/union.stderr
@@ -0,0 +1,31 @@
+error[E0309]: the parameter type `U` may not live long enough
+  --> $DIR/union.rs:25:5
+   |
+LL | union Bar<'b, U> {
+   |               - help: consider adding an explicit lifetime bound `U: 'b`...
+LL |     field2: &'b U //~ ERROR 25:5: 25:18: the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'b U` does not outlive the data it points at
+  --> $DIR/union.rs:25:5
+   |
+LL |     field2: &'b U //~ ERROR 25:5: 25:18: the parameter type `U` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^
+
+error[E0309]: the parameter type `K` may not live long enough
+  --> $DIR/union.rs:31:5
+   |
+LL | union Ying<'c, K> {
+   |                - help: consider adding an explicit lifetime bound `K: 'c`...
+LL |     field1: &'c Yang<K> //~ ERROR 31:5: 31:24: the parameter type `K` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'c Yang<K>` does not outlive the data it points at
+  --> $DIR/union.rs:31:5
+   |
+LL |     field1: &'c Yang<K> //~ ERROR 31:5: 31:24: the parameter type `K` may not live long enough [E0309]
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
new file mode 100644
index 00000000000..172828b9a40
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
@@ -0,0 +1,51 @@
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
+   |
+LL |     let __isize = &mut x.y; //~ ERROR cannot borrow
+   |                        ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10
+   |
+LL |     &mut x.y //~ ERROR cannot borrow
+   |          ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
+   |
+LL |     x.y = 3; //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
+   |
+LL |     x.y = 3; //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
+   |
+LL |     x.set(0, 0); //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5
+   |
+LL |     x.y_mut() //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
+   |
+LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
+   |
+LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
+   |      ^ cannot borrow as mutable
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
new file mode 100644
index 00000000000..24abe85de76
--- /dev/null
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
@@ -0,0 +1,27 @@
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
+   |
+LL |     let __isize = &mut *x; //~ ERROR cannot borrow
+   |                         ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
+   |
+LL |     &mut **x //~ ERROR cannot borrow
+   |           ^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
+   |
+LL |     *x = 3; //~ ERROR cannot borrow
+   |      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
+   |
+LL |     **x = 3; //~ ERROR cannot borrow
+   |      ^^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
new file mode 100644
index 00000000000..505ee95088f
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
@@ -0,0 +1,54 @@
+error[E0499]: cannot borrow `f` as mutable more than once at a time
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:22:16
+   |
+LL |       f(Box::new(|| {
+   |       -          ^^ second mutable borrow occurs here
+   |       |
+   |  _____first mutable borrow occurs here
+   | |
+LL | |     //~^ ERROR: cannot borrow `f` as mutable more than once
+LL | |         f((Box::new(|| {})))
+   | |         - borrow occurs due to use of `f` in closure
+LL | |     }));
+   | |_______- borrow later used here
+
+error[E0596]: cannot borrow immutable item `*f` as mutable
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
+   |
+LL |     (*f)();
+   |     ^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*f.f` as mutable
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
+   |
+LL |     f.f.call_mut(())
+   |     ^^^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `*f`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
+   |
+LL |         foo(f);
+   |             ^ cannot move out of borrowed content
+
+error[E0505]: cannot move out of `f` because it is borrowed
+  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16
+   |
+LL |        f(Box::new(|a| {
+   |   _____-__________^
+   |  |     |
+   |  |_____borrow of `f` occurs here
+   | ||
+LL | ||         foo(f);
+LL | ||         //~^ ERROR cannot move `f` into closure because it is borrowed
+LL | ||         //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
+LL | ||     }), 3);
+   | ||_____^____- borrow later used here
+   |  |_____|
+   |        move out of `f` occurs here
+
+error: aborting due to 5 previous errors
+
+Some errors occurred: E0499, E0505, E0507, E0596.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
new file mode 100644
index 00000000000..43934bf4aee
--- /dev/null
+++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5
+   |
+LL |     x.h(); //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
new file mode 100644
index 00000000000..d3c6fd66599
--- /dev/null
+++ b/src/test/ui/span/borrowck-fn-in-const-b.nll.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-fn-in-const-b.rs:17:9
+   |
+LL |         x.push(format!("this is broken"));
+   |         ^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr
new file mode 100644
index 00000000000..d02f70ea292
--- /dev/null
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.nll.stderr
@@ -0,0 +1,10 @@
+error: compilation successful
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:61:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     f();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
index 8a27af0119a..60e6c6e2989 100644
--- a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
@@ -7,7 +7,7 @@
 // <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)]
 fn id<T>(x: T) -> T { x }
 
 fn f() {
@@ -58,6 +58,6 @@ fn f() {
 //~| NOTE temporary value needs to live until here
 //~| NOTE temporary value needs to live until here
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     f();
 }
diff --git a/src/test/ui/span/borrowck-object-mutability.nll.stderr b/src/test/ui/span/borrowck-object-mutability.nll.stderr
new file mode 100644
index 00000000000..100b5ae150a
--- /dev/null
+++ b/src/test/ui/span/borrowck-object-mutability.nll.stderr
@@ -0,0 +1,17 @@
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-object-mutability.rs:19:5
+   |
+LL |     x.borrowed_mut(); //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*x` as mutable
+  --> $DIR/borrowck-object-mutability.rs:29:5
+   |
+LL |     x.borrowed_mut(); //~ ERROR cannot borrow
+   |     ^ cannot borrow as mutable
+   |
+   = note: Value not mutable causing this error: `x`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr
new file mode 100644
index 00000000000..171bb3dda66
--- /dev/null
+++ b/src/test/ui/span/borrowck-ref-into-rvalue.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/borrowck-ref-into-rvalue.rs:13:11
+   |
+LL |     match Some("Hello".to_string()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL |     }
+   |     - temporary value only lives until here
+LL |     println!("{}", *msg);
+   |                    ---- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/destructor-restrictions.nll.stderr b/src/test/ui/span/destructor-restrictions.nll.stderr
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/ui/span/destructor-restrictions.nll.stderr
diff --git a/src/test/ui/span/dropck-object-cycle.nll.stderr b/src/test/ui/span/dropck-object-cycle.nll.stderr
new file mode 100644
index 00000000000..64a76399da3
--- /dev/null
+++ b/src/test/ui/span/dropck-object-cycle.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `*m` does not live long enough
+  --> $DIR/dropck-object-cycle.rs:37:31
+   |
+LL |     assert_eq!(object_invoke1(&*m), (4,5));
+   |                               ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `m` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr
new file mode 100644
index 00000000000..fee0d7feb6d
--- /dev/null
+++ b/src/test/ui/span/dropck_arr_cycle_checked.nll.stderr
@@ -0,0 +1,39 @@
+error[E0597]: `b1` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:111:24
+   |
+LL |     b3.a[0].v.set(Some(&b1));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `b1` is dropped
+
+error[E0597]: `b2` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:103:24
+   |
+LL |     b1.a[0].v.set(Some(&b2));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `b1` is dropped
+
+error[E0597]: `b3` does not live long enough
+  --> $DIR/dropck_arr_cycle_checked.rs:105:24
+   |
+LL |     b1.a[1].v.set(Some(&b3));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `b1` is dropped
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr
new file mode 100644
index 00000000000..2a8ef24307d
--- /dev/null
+++ b/src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr
@@ -0,0 +1,27 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:48:19
+   |
+LL |     d2.p.set(Some(&d1));
+   |                   ^^^ borrowed value does not live long enough
+LL |     //~^ ERROR `d1` does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `d1` is dropped
+
+error[E0597]: `d2` does not live long enough
+  --> $DIR/dropck_direct_cycle_with_drop.rs:46:19
+   |
+LL |     d1.p.set(Some(&d2));
+   |                   ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `d1` 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/span/dropck_misc_variants.nll.stderr b/src/test/ui/span/dropck_misc_variants.nll.stderr
new file mode 100644
index 00000000000..0eeec8e51be
--- /dev/null
+++ b/src/test/ui/span/dropck_misc_variants.nll.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `bomb` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:33:36
+   |
+LL |     _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
+   |                                    ^^^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `_w` is dropped
+
+error[E0597]: `v` does not live long enough
+  --> $DIR/dropck_misc_variants.rs:41:27
+   |
+LL |         let u = NoisyDrop(&v);
+   |                           ^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `_w` 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/span/dropck_vec_cycle_checked.nll.stderr b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
new file mode 100644
index 00000000000..41edd04c92e
--- /dev/null
+++ b/src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
@@ -0,0 +1,39 @@
+error[E0597]: `c1` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:118:24
+   |
+LL |     c3.v[0].v.set(Some(&c1));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `c1` is dropped
+
+error[E0597]: `c2` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:110:24
+   |
+LL |     c1.v[0].v.set(Some(&c2));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `c1` is dropped
+
+error[E0597]: `c3` does not live long enough
+  --> $DIR/dropck_vec_cycle_checked.rs:112:24
+   |
+LL |     c1.v[1].v.set(Some(&c3));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `c1` is dropped
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-11925.nll.stderr b/src/test/ui/span/issue-11925.nll.stderr
new file mode 100644
index 00000000000..68a4d5d25f4
--- /dev/null
+++ b/src/test/ui/span/issue-11925.nll.stderr
@@ -0,0 +1,12 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-11925.rs:18:35
+   |
+LL |         let f = to_fn_once(move|| &x); //~ ERROR does not live long enough
+   |                                   ^-
+   |                                   ||
+   |                                   |borrowed value only lives until here
+   |                                   borrowed value does not live long enough
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-15480.nll.stderr b/src/test/ui/span/issue-15480.nll.stderr
new file mode 100644
index 00000000000..2f3f6c5efa2
--- /dev/null
+++ b/src/test/ui/span/issue-15480.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-15480.rs:15:10
+   |
+LL |         &id(3)
+   |          ^^^^^ temporary value does not live long enough
+LL |     ];
+   |      - temporary value only lives until here
+...
+LL |     for &&x in &v {
+   |                -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr
new file mode 100644
index 00000000000..3f18f4d025a
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:38:18
+   |
+LL |     _d = D_Child(&d1);
+   |                  ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `_d` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr
new file mode 100644
index 00000000000..79e607bb392
--- /dev/null
+++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr
@@ -0,0 +1,36 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:47:26
+   |
+LL |     _d = D_HasSelfMethod(&d1);
+   |                          ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `_d` is dropped
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:53:33
+   |
+LL |     _d = D_HasMethodWithSelfArg(&d1);
+   |                                 ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `_d` is dropped
+
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24805-dropck-trait-has-items.rs:59:20
+   |
+LL |     _d = D_HasType(&d1);
+   |                    ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `_d` is dropped
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr
new file mode 100644
index 00000000000..550f9d8b60d
--- /dev/null
+++ b/src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `d1` does not live long enough
+  --> $DIR/issue-24895-copy-clone-dropck.rs:37:14
+   |
+LL |     d2 = D(S(&d1, "inner"), "d2");
+   |              ^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `d2` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-25199.nll.stderr b/src/test/ui/span/issue-25199.nll.stderr
new file mode 100644
index 00000000000..770fed8cd9c
--- /dev/null
+++ b/src/test/ui/span/issue-25199.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `container` does not live long enough
+  --> $DIR/issue-25199.rs:80:27
+   |
+LL |     let test = Test{test: &container};
+   |                           ^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `container` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-26656.nll.stderr b/src/test/ui/span/issue-26656.nll.stderr
new file mode 100644
index 00000000000..64bb83fc782
--- /dev/null
+++ b/src/test/ui/span/issue-26656.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `ticking` does not live long enough
+  --> $DIR/issue-26656.rs:50:35
+   |
+LL |     zook.button = B::BigRedButton(&ticking);
+   |                                   ^^^^^^^^ borrowed value does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `zook` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue-29106.nll.stderr b/src/test/ui/span/issue-29106.nll.stderr
new file mode 100644
index 00000000000..80a7421f4bd
--- /dev/null
+++ b/src/test/ui/span/issue-29106.nll.stderr
@@ -0,0 +1,25 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-29106.rs:26:26
+   |
+LL |         y = Arc::new(Foo(&x));
+   |                          ^^ borrowed value does not live long enough
+LL |     }
+   |     -
+   |     |
+   |     borrowed value only lives until here
+   |     borrow later used here, when `y` is dropped
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-29106.rs:33:25
+   |
+LL |         y = Rc::new(Foo(&x));
+   |                         ^^ borrowed value does not live long enough
+LL |     }
+   |     -
+   |     |
+   |     borrowed value only lives until here
+   |     borrow later used here, when `y` 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/span/issue-36537.nll.stderr b/src/test/ui/span/issue-36537.nll.stderr
new file mode 100644
index 00000000000..5802bac04b1
--- /dev/null
+++ b/src/test/ui/span/issue-36537.nll.stderr
@@ -0,0 +1,13 @@
+error: compilation successful
+  --> $DIR/issue-36537.rs:11:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let p;
+LL | |     let a = 42;
+LL | |     p = &a;
+LL | |     //~^ ERROR `a` does not live long enough
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-36537.rs b/src/test/ui/span/issue-36537.rs
index 3eac0106b18..ca04101cf56 100644
--- a/src/test/ui/span/issue-36537.rs
+++ b/src/test/ui/span/issue-36537.rs
@@ -7,8 +7,8 @@
 // <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() {
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let p;
     let a = 42;
     p = &a;
diff --git a/src/test/ui/span/issue-40157.nll.stderr b/src/test/ui/span/issue-40157.nll.stderr
new file mode 100644
index 00000000000..d9608f3a896
--- /dev/null
+++ b/src/test/ui/span/issue-40157.nll.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `foo` does not live long enough
+  --> $DIR/issue-40157.rs:12:53
+   |
+LL |     {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
+   |                       ------------------------------^^^--------------------
+   |                       |                             |          |
+   |                       |                             |          borrowed value only lives until here
+   |                       |                             borrowed value does not live long enough
+   |                       borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-ex1.nll.stderr b/src/test/ui/span/issue28498-reject-ex1.nll.stderr
new file mode 100644
index 00000000000..c5e7a93c763
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-ex1.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `foo.data` does not live long enough
+  --> $DIR/issue28498-reject-ex1.rs:44:29
+   |
+LL |     foo.data[0].1.set(Some(&foo.data[1]));
+   |                             ^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `foo` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr
new file mode 100644
index 00000000000..25708219bd1
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-lifetime-param.rs:44:19
+   |
+LL |     foo1 = Foo(1, &first_dropped);
+   |                   ^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `foo1` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr
new file mode 100644
index 00000000000..66157096394
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-passed-to-fn.rs:46:19
+   |
+LL |     foo1 = Foo(1, &first_dropped, Box::new(callback));
+   |                   ^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `foo1` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr
new file mode 100644
index 00000000000..bb9d67983de
--- /dev/null
+++ b/src/test/ui/span/issue28498-reject-trait-bound.nll.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `first_dropped` does not live long enough
+  --> $DIR/issue28498-reject-trait-bound.rs:46:19
+   |
+LL |     foo1 = Foo(1, &first_dropped);
+   |                   ^^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `foo1` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/mut-arg-hint.nll.stderr b/src/test/ui/span/mut-arg-hint.nll.stderr
new file mode 100644
index 00000000000..8e1cb9720e2
--- /dev/null
+++ b/src/test/ui/span/mut-arg-hint.nll.stderr
@@ -0,0 +1,21 @@
+error[E0596]: cannot borrow immutable item `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:13:9
+   |
+LL |         a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content
+   |         ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:18:5
+   |
+LL |     a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
+   |     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow immutable item `*a` as mutable
+  --> $DIR/mut-arg-hint.rs:25:9
+   |
+LL |         a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
+   |         ^ cannot borrow as mutable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr
new file mode 100644
index 00000000000..3cad23a3c03
--- /dev/null
+++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/mut-ptr-cant-outlive-ref.rs:13:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let m = RefCell::new(0);
+LL | |     let p;
+LL | |     {
+...  |
+LL | |     //~^^ ERROR `b` does not live long enough
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.rs b/src/test/ui/span/mut-ptr-cant-outlive-ref.rs
index 9dc0836c5e0..9774303197c 100644
--- a/src/test/ui/span/mut-ptr-cant-outlive-ref.rs
+++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.rs
@@ -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.
-
+#![feature(rustc_attrs)]
 use std::cell::RefCell;
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let m = RefCell::new(0);
     let p;
     {
diff --git a/src/test/ui/span/range-2.nll.stderr b/src/test/ui/span/range-2.nll.stderr
new file mode 100644
index 00000000000..afb319b57d4
--- /dev/null
+++ b/src/test/ui/span/range-2.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/range-2.rs:13:1
+   |
+LL | / pub fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let r = {
+LL | |         let a = 42;
+LL | |         let b = 42;
+...  |
+LL | |     //~| ERROR `b` does not live long enough
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/range-2.rs b/src/test/ui/span/range-2.rs
index d69b3ea098c..a1ed9bc6aa8 100644
--- a/src/test/ui/span/range-2.rs
+++ b/src/test/ui/span/range-2.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 // Test range syntax - borrow errors.
-
-pub fn main() {
+#![feature(rustc_attrs)]
+pub fn main() { #![rustc_error] // rust-lang/rust#49855
     let r = {
         let a = 42;
         let b = 42;
diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr
new file mode 100644
index 00000000000..3c918fdb147
--- /dev/null
+++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/regionck-unboxed-closure-lifetimes.rs:13:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut f;
+LL | |     {
+LL | |         let c = 1;
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs b/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs
index 93b3d673359..c814941c811 100644
--- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs
+++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.rs
@@ -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.
-
+#![feature(rustc_attrs)]
 use std::ops::FnMut;
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut f;
     {
         let c = 1;
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr
new file mode 100644
index 00000000000..651296dbeaf
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:22:27
+   |
+LL |         let ss: &isize = &id(1);
+   |                           ^^^^^ temporary value does not live long enough
+...
+LL |     }
+   |     - temporary value only lives until here
+LL | }
+   | - borrow later used here, when `blah` is dropped
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr
new file mode 100644
index 00000000000..c8a1f801201
--- /dev/null
+++ b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr
@@ -0,0 +1,18 @@
+error[E0597]: `tmp0` does not live long enough
+  --> $DIR/regions-close-over-type-parameter-2.rs:33:20
+   |
+LL |       let _ = {
+   |  _____________-
+LL | |         let tmp0 = 3;
+LL | |         let tmp1 = &tmp0;
+   | |                    ^^^^^ borrowed value does not live long enough
+LL | |         repeater3(tmp1)
+LL | |     };
+   | |     -
+   | |     |
+   | |_____borrowed value only lives until here
+   |       borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr
new file mode 100644
index 00000000000..7fd2bfbdd8f
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-variable.nll.stderr
@@ -0,0 +1,13 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/regions-escape-loop-via-variable.rs:21:13
+   |
+LL |         let x = 1 + *p;
+   |                     -- borrow later used here
+LL |         p = &x;
+   |             ^^ borrowed value does not live long enough
+LL |     }
+   |     - borrowed value only lives until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr
new file mode 100644
index 00000000000..c7aa40f18e3
--- /dev/null
+++ b/src/test/ui/span/regions-escape-loop-via-vec.nll.stderr
@@ -0,0 +1,49 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:15:11
+   |
+LL |     let mut _y = vec![&mut x];
+   |                       ------ borrow of `x` occurs here
+LL |     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
+   |           ^ use of borrowed `x`
+LL |         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
+LL |         _y.push(&mut z);
+   |         -- borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:16:21
+   |
+LL |     let mut _y = vec![&mut x];
+   |                       ------ borrow of `x` occurs here
+LL |     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
+LL |         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
+   |                     ^ use of borrowed `x`
+LL |         _y.push(&mut z);
+   |         -- borrow later used here
+
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/regions-escape-loop-via-vec.rs:19:9
+   |
+LL |     let mut _y = vec![&mut x];
+   |                       ------ borrow of `x` occurs here
+...
+LL |         _y.push(&mut z);
+   |         -- borrow later used here
+LL |         //~^ ERROR `z` does not live long enough
+LL |         x += 1; //~ ERROR cannot assign
+   |         ^^^^^^ use of borrowed `x`
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/regions-escape-loop-via-vec.rs:17:17
+   |
+LL |         _y.push(&mut z);
+   |         --      ^^^^^^ borrowed value does not live long enough
+   |         |
+   |         borrow later used here
+...
+LL |     }
+   |     - borrowed value only lives until here
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0503, E0597.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr
new file mode 100644
index 00000000000..034f80c7d54
--- /dev/null
+++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.nll.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `*x` does not live long enough
+  --> $DIR/regions-infer-borrow-scope-within-loop.rs:24:20
+   |
+LL |         y = borrow(&*x);
+   |                    ^^^ borrowed value does not live long enough
+...
+LL |     }
+   |     - borrowed value only lives until here
+LL |     assert!(*y != 0);
+   |             -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
new file mode 100644
index 00000000000..710b19e1932
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr
@@ -0,0 +1,30 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:29:16
+   |
+LL |           scoped(|| {
+   |  ________________^
+LL | |             let _z = y;
+LL | |             //~^ ERROR `y` does not live long enough
+LL | |         })
+   | |_________^ borrowed value does not live long enough
+LL |       };
+   |       - borrowed value only lives until here
+LL | 
+LL |       bad.join();
+   |       --- borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-ensures-scoping.rs:26:17
+   |
+LL |         let y = &x;
+   |                 ^^ borrowed value does not live long enough
+...
+LL |     };
+   |     - borrowed value only lives until here
+LL | 
+LL |     bad.join();
+   |     --- borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
new file mode 100644
index 00000000000..e794f8c27e8
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr
@@ -0,0 +1,37 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:21:20
+   |
+LL |         Mutex::new(&x)
+   |                    ^^ borrowed value does not live long enough
+LL |     };
+   |     - borrowed value only lives until here
+...
+LL |     let _dangling = *lock.lock().unwrap();
+   |                      ---- borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:31:21
+   |
+LL |         RwLock::new(&x)
+   |                     ^^ borrowed value does not live long enough
+LL |     };
+   |     - borrowed value only lives until here
+LL |     //~^^ ERROR `x` does not live long enough
+LL |     let _dangling = *lock.read().unwrap();
+   |                      ---- borrow later used here
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/send-is-not-static-std-sync-2.rs:41:25
+   |
+LL |     let (_tx, rx) = {
+   |          --- borrow later used here
+...
+LL |         let _ = tx.send(&x);
+   |                         ^^ borrowed value does not live long enough
+LL |         (tx, rx)
+LL |     };
+   |     - borrowed value only lives until here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/span/send-is-not-static-std-sync.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr
new file mode 100644
index 00000000000..21143306110
--- /dev/null
+++ b/src/test/ui/span/send-is-not-static-std-sync.nll.stderr
@@ -0,0 +1,48 @@
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:23:10
+   |
+LL |     *lock.lock().unwrap() = &*y;
+   |                             --- borrow of `*y` occurs here
+LL |     drop(y); //~ ERROR cannot move out
+   |          ^ move out of `y` occurs here
+...
+LL |         *lock.lock().unwrap() = &z;
+   |          ---- borrow later used here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:36:10
+   |
+LL |     *lock.write().unwrap() = &*y;
+   |                              --- borrow of `*y` occurs here
+LL |     drop(y); //~ ERROR cannot move out
+   |          ^ move out of `y` occurs here
+...
+LL |         *lock.write().unwrap() = &z;
+   |          ---- borrow later used here
+
+error[E0505]: cannot move out of `y` because it is borrowed
+  --> $DIR/send-is-not-static-std-sync.rs:51:10
+   |
+LL |     tx.send(&*y);
+   |             --- borrow of `*y` occurs here
+LL |     drop(y); //~ ERROR cannot move out
+   |          ^ move out of `y` occurs here
+...
+LL |         tx.send(&z).unwrap();
+   |         -- borrow later used here
+
+error[E0597]: `z` does not live long enough
+  --> $DIR/send-is-not-static-std-sync.rs:54:17
+   |
+LL |         tx.send(&z).unwrap();
+   |                 ^^ borrowed value does not live long enough
+LL |     }
+   |     - borrowed value only lives until here
+LL |     //~^^ ERROR `z` does not live long enough
+LL | }
+   | - borrow later used here, when `tx` is dropped
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0505, E0597.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/span/slice-borrow.nll.stderr b/src/test/ui/span/slice-borrow.nll.stderr
new file mode 100644
index 00000000000..52ca125f8b6
--- /dev/null
+++ b/src/test/ui/span/slice-borrow.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/slice-borrow.rs:13:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let y;
+LL | |     {
+LL | |         let x: &[isize] = &vec![1, 2, 3, 4, 5];
+LL | |         y = &x[1..];
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/slice-borrow.rs b/src/test/ui/span/slice-borrow.rs
index 1b022f23246..45dff62672b 100644
--- a/src/test/ui/span/slice-borrow.rs
+++ b/src/test/ui/span/slice-borrow.rs
@@ -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.
-
+#![feature(rustc_attrs)]
 // Test slicing expressions doesn't defeat the borrow checker.
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let y;
     {
         let x: &[isize] = &vec![1, 2, 3, 4, 5];
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr
new file mode 100644
index 00000000000..389adb231c4
--- /dev/null
+++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr
@@ -0,0 +1,27 @@
+error[E0597]: `c1` does not live long enough
+  --> $DIR/vec-must-not-hide-type-from-dropck.rs:129:24
+   |
+LL |     c2.v[0].v.set(Some(&c1));
+   |                        ^^^ borrowed value does not live long enough
+LL |     //~^ ERROR `c1` does not live long enough
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `c1` is dropped
+
+error[E0597]: `c2` does not live long enough
+  --> $DIR/vec-must-not-hide-type-from-dropck.rs:127:24
+   |
+LL |     c1.v[0].v.set(Some(&c2));
+   |                        ^^^ borrowed value does not live long enough
+...
+LL | }
+   | -
+   | |
+   | borrowed value only lives until here
+   | borrow later used here, when `c1` 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/span/vec_refs_data_with_early_death.nll.stderr b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr
new file mode 100644
index 00000000000..09ecc666cbc
--- /dev/null
+++ b/src/test/ui/span/vec_refs_data_with_early_death.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/vec_refs_data_with_early_death.rs:21:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let mut v = Vec::new();
+LL | |
+LL | |     let x: i8 = 3;
+...  |
+LL | |     assert_eq!(v, [&3, &4]);
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.rs b/src/test/ui/span/vec_refs_data_with_early_death.rs
index 42373a87a6c..a3532d919bc 100644
--- a/src/test/ui/span/vec_refs_data_with_early_death.rs
+++ b/src/test/ui/span/vec_refs_data_with_early_death.rs
@@ -17,8 +17,8 @@
 //  element it owns; thus, for data like this, it seems like we could
 //  loosen the restrictions here if we wanted. But it also is not
 //  clear whether such loosening is terribly important.)
-
-fn main() {
+#![feature(rustc_attrs)]
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let mut v = Vec::new();
 
     let x: i8 = 3;
diff --git a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
new file mode 100644
index 00000000000..a175cf1b38a
--- /dev/null
+++ b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/wf-method-late-bound-regions.rs:25:1
+   |
+LL | / fn main() { #![rustc_error] // rust-lang/rust#49855
+LL | |     let f = Foo(None);
+LL | |     let f2 = f;
+LL | |     let dangling = {
+...  |
+LL | |     println!("{}", dangling);
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/wf-method-late-bound-regions.rs b/src/test/ui/span/wf-method-late-bound-regions.rs
index d58c29d4a32..317cd395d0a 100644
--- a/src/test/ui/span/wf-method-late-bound-regions.rs
+++ b/src/test/ui/span/wf-method-late-bound-regions.rs
@@ -11,7 +11,7 @@
 // A method's receiver must be well-formed, even if it has late-bound regions.
 // Because of this, a method's substs being well-formed does not imply that
 // the method's implied bounds are met.
-
+#![feature(rustc_attrs)]
 struct Foo<'b>(Option<&'b ()>);
 
 trait Bar<'b> {
@@ -22,7 +22,7 @@ impl<'b> Bar<'b> for Foo<'b> {
     fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u }
 }
 
-fn main() {
+fn main() { #![rustc_error] // rust-lang/rust#49855
     let f = Foo(None);
     let f2 = f;
     let dangling = {
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
new file mode 100644
index 00000000000..e4e93ecac8e
--- /dev/null
+++ b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable item `y`
+  --> $DIR/closure-immutable-outer-variable.rs:19:26
+   |
+LL |     foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+   |                          ^^^^^^^^^ cannot mutate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr b/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr
new file mode 100644
index 00000000000..ed691843f9b
--- /dev/null
+++ b/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable item `x`
+  --> $DIR/fn-closure-mutable-capture.rs:15:17
+   |
+LL |     bar(move || x = 1);
+   |                 ^^^^^ cannot mutate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/target-feature-wrong.rs b/src/test/ui/target-feature-wrong.rs
index 56acbed4721..eb83ee724c7 100644
--- a/src/test/ui/target-feature-wrong.rs
+++ b/src/test/ui/target-feature-wrong.rs
@@ -12,6 +12,9 @@
 // ignore-aarch64
 // ignore-wasm
 // ignore-emscripten
+// ignore-mips
+// ignore-powerpc
+// ignore-s390x
 
 #![feature(target_feature)]
 
diff --git a/src/test/ui/target-feature-wrong.stderr b/src/test/ui/target-feature-wrong.stderr
index 8773f8504cb..b5e650eaf9a 100644
--- a/src/test/ui/target-feature-wrong.stderr
+++ b/src/test/ui/target-feature-wrong.stderr
@@ -1,35 +1,35 @@
 warning: #[target_feature = ".."] is deprecated and will eventually be removed, use #[target_feature(enable = "..")] instead
-  --> $DIR/target-feature-wrong.rs:18:1
+  --> $DIR/target-feature-wrong.rs:21:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/target-feature-wrong.rs:20:18
+  --> $DIR/target-feature-wrong.rs:23:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:22:18
+  --> $DIR/target-feature-wrong.rs:25:18
    |
 LL | #[target_feature(bar)]
    |                  ^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:24:18
+  --> $DIR/target-feature-wrong.rs:27:18
    |
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] can only be applied to `unsafe` function
-  --> $DIR/target-feature-wrong.rs:28:1
+  --> $DIR/target-feature-wrong.rs:31:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a function
-  --> $DIR/target-feature-wrong.rs:32:1
+  --> $DIR/target-feature-wrong.rs:35:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL | mod another {}
    | -------------- not a function
 
 error: cannot use #[inline(always)] with #[target_feature]
-  --> $DIR/target-feature-wrong.rs:36:1
+  --> $DIR/target-feature-wrong.rs:39:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
new file mode 100644
index 00000000000..f8ea891914e
--- /dev/null
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/dyn-trait-underscore.rs:20:14
+   |
+LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+   |              ^^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/dyn-trait-underscore.rs:20:20
+   |
+LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+   |                    ^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/dyn-trait-underscore.rs:20:5
+   |
+LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+   |     ^^^^^^^^
+
+warning: not reporting region error due to -Znll
+  --> $DIR/dyn-trait-underscore.rs:20: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
+   |
+LL |   fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+   |  ____________________________________________________^
+LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+LL | |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject b45801ff192e6f1bd3504c05e612a1004f52a24
+Subproject 8ec61a613ad1278b18a4770332b6da128704fdd
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index e48f42705f1..94a6353ad24 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -595,7 +595,7 @@ impl Config {
     fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
         // returns whether this line contains this prefix or not. For prefix
         // "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
-        // "ignore-andorid" etc.
+        // "ignore-android" etc.
         line.starts_with(prefix) && line.as_bytes().get(prefix.len()) == Some(&b'-')
     }
 
diff --git a/src/tools/rls b/src/tools/rls
-Subproject b17d799d1302fd643a3dd19280f64c8ad162a4a
+Subproject faccf0d07cad4c84da20c5c0102a450fca9d0b6
diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs
index e726dea84f1..7aca765cead 100644
--- a/src/tools/rustdoc/main.rs
+++ b/src/tools/rustdoc/main.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #![feature(link_args)]
+
+#[allow(unused_attributes)]
 // Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
 // for the rationale.
 #[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 06eb055f68e..fa227436640 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -13,8 +13,6 @@
 //! This library contains the tidy lints and exposes it
 //! to be used by tools.
 
-#![deny(warnings)]
-
 extern crate serde;
 extern crate serde_json;
 #[macro_use]
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index f7fec2e667a..bda58bc09f7 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -12,14 +12,41 @@
 
 use std::path::Path;
 
+// See rust-lang/rust#48879: In addition to the mapping from `foo.rs`
+// to `foo.stderr`/`foo.stdout`, we also can optionally have
+// `foo.$mode.stderr`, where $mode is one of the strings on this list,
+// as an alternative to use when running under that mode.
+static COMPARE_MODE_NAMES: [&'static str; 1] = ["nll"];
+
 pub fn check(path: &Path, bad: &mut bool) {
     super::walk_many(&[&path.join("test/ui"), &path.join("test/ui-fulldeps")],
                      &mut |_| false,
                      &mut |file_path| {
         if let Some(ext) = file_path.extension() {
             if (ext == "stderr" || ext == "stdout") && !file_path.with_extension("rs").exists() {
-                println!("Stray file with UI testing output: {:?}", file_path);
-                *bad = true;
+
+                // rust-lang/rust#48879: this fn used to be beautful
+                // because Path API special-cases replacing
+                // extensions. That works great for ".stderr" but not
+                // so well for ".nll.stderr". To support the latter,
+                // we explicitly search backwards for mode's starting
+                // point and build corresponding source name.
+                let filename = file_path.file_name().expect("need filename")
+                    .to_str().expect("need UTF-8 filename");
+                let found_matching_prefix = COMPARE_MODE_NAMES.iter().any(|mode| {
+                    if let Some(r_idx) = filename.rfind(&format!(".{}", mode)) {
+                        let source_name = format!("{}.rs", &filename[0..r_idx]);
+                        let source_path = file_path.with_file_name(source_name);
+                        source_path.exists()
+                    } else {
+                        false
+                    }
+                });
+
+                if !found_matching_prefix {
+                    println!("Stray file with UI testing output: {:?}", file_path);
+                    *bad = true;
+                }
             }
         }
     });