diff --git a/cargo b/cargo
index c416fb60b11ec..770512b08fb29 160000
--- a/cargo
+++ b/cargo
@@ -1 +1 @@
-Subproject commit c416fb60b11ecfd2a1ba0fb8567c9a92590b5d28
+Subproject commit 770512b08fb2985aed6f06311f1c58ed587fa259
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 62b853480394f..f4c35719f3631 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -269,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.0.18"
+version = "0.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -425,7 +425,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -922,9 +922,6 @@ dependencies = [
 [[package]]
 name = "tidy"
 version = "0.1.0"
-dependencies = [
- "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "toml"
@@ -1004,7 +1001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
 "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
 "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
-"checksum mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "06a68e8738e42b38a02755d3ce5fa12d559e17acb238e4326cbc3cc056e65280"
+"checksum mdbook 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2598843aeda0c5bb2e8e4d714564f1c3fc40f7844157e34563bf96ae3866b56e"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
 "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index f8f641060c442..a439e79fce538 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -78,14 +78,6 @@ pub fn linkcheck(build: &Build, host: &str) {
 pub fn cargotest(build: &Build, stage: u32, host: &str) {
     let ref compiler = Compiler::new(stage, host);
 
-    // Configure PATH to find the right rustc. NB. we have to use PATH
-    // and not RUSTC because the Cargo test suite has tests that will
-    // fail if rustc is not spelled `rustc`.
-    let path = build.sysroot(compiler).join("bin");
-    let old_path = ::std::env::var("PATH").expect("");
-    let sep = if cfg!(windows) { ";" } else {":" };
-    let ref newpath = format!("{}{}{}", path.display(), sep, old_path);
-
     // Note that this is a short, cryptic, and not scoped directory name. This
     // is currently to minimize the length of path on Windows where we otherwise
     // quickly run into path name limit constraints.
@@ -95,11 +87,49 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
     let _time = util::timeit();
     let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
     build.prepare_tool_cmd(compiler, &mut cmd);
-    build.run(cmd.env("PATH", newpath)
-                 .arg(&build.cargo)
+    build.run(cmd.arg(&build.cargo)
                  .arg(&out_dir));
 }
 
+/// Runs `cargo test` for `cargo` packaged with Rust.
+pub fn cargo(build: &Build, stage: u32, host: &str) {
+    let ref compiler = Compiler::new(stage, host);
+
+    // Configure PATH to find the right rustc. NB. we have to use PATH
+    // and not RUSTC because the Cargo test suite has tests that will
+    // fail if rustc is not spelled `rustc`.
+    let path = build.sysroot(compiler).join("bin");
+    let old_path = ::std::env::var("PATH").expect("");
+    let sep = if cfg!(windows) { ";" } else {":" };
+    let ref newpath = format!("{}{}{}", path.display(), sep, old_path);
+
+    let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
+    cargo.arg("--manifest-path").arg(build.src.join("cargo/Cargo.toml"));
+
+    // Don't build tests dynamically, just a pain to work with
+    cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
+
+    // Don't run cross-compile tests, we may not have cross-compiled libstd libs
+    // available.
+    cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
+
+    // When being tested Cargo will at some point call `nmake.exe` on Windows
+    // MSVC. Unfortunately `nmake` will read these two environment variables
+    // below and try to intepret them. We're likely being run, however, from
+    // MSYS `make` which uses the same variables.
+    //
+    // As a result, to prevent confusion and errors, we remove these variables
+    // from our environment to prevent passing MSYS make flags to nmake, causing
+    // it to blow up.
+    if cfg!(target_env = "msvc") {
+        cargo.env_remove("MAKE");
+        cargo.env_remove("MAKEFLAGS");
+    }
+
+
+    build.run(cargo.env("PATH", newpath));
+}
+
 /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
 ///
 /// This tool in `src/tools` checks up on various bits and pieces of style and
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 457ac825832ce..a5df741e2bfc8 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -55,6 +55,7 @@ check:
 check-aux:
 	$(Q)$(BOOTSTRAP) test \
 		src/tools/cargotest \
+		cargo \
 		src/test/pretty \
 		src/test/run-pass/pretty \
 		src/test/run-fail/pretty \
diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs
index 34705040e8a5e..4e3166acbd67e 100644
--- a/src/bootstrap/step.rs
+++ b/src/bootstrap/step.rs
@@ -468,6 +468,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
          .dep(|s| s.name("librustc"))
          .host(true)
          .run(move |s| check::cargotest(build, s.stage, s.target));
+    rules.test("check-cargo", "cargo")
+         .dep(|s| s.name("tool-cargo"))
+         .host(true)
+         .run(move |s| check::cargo(build, s.stage, s.target));
     rules.test("check-tidy", "src/tools/tidy")
          .dep(|s| s.name("tool-tidy").stage(0))
          .default(true)
diff --git a/src/doc/book b/src/doc/book
index beea82b9230cd..ad7de198561b3 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit beea82b9230cd641dd1ca263cf31025ace4aebb5
+Subproject commit ad7de198561b3a12217ea2da76d796d9c7fc0ed3
diff --git a/src/doc/guide-plugins.md b/src/doc/guide-plugins.md
index 1ba28c0117db5..6c511548789b7 100644
--- a/src/doc/guide-plugins.md
+++ b/src/doc/guide-plugins.md
@@ -1,4 +1,4 @@
 % The (old) Rust Compiler Plugins Guide
 
 This content has moved into
-[the Unstable Book](unstable-book/plugin.html).
+[the Unstable Book](unstable-book/language-features/plugin.html).
diff --git a/src/doc/reference b/src/doc/reference
index b060f732145f2..6b0de90d87dda 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit b060f732145f2fa16df84c74e511df08a3a47c5d
+Subproject commit 6b0de90d87dda15e323ef24cdf7ed873ac5cf4d3
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md
index 36999eb143ff4..2e20eef7d2ab6 100644
--- a/src/doc/unstable-book/src/SUMMARY.md
+++ b/src/doc/unstable-book/src/SUMMARY.md
@@ -1,226 +1,229 @@
 [The Unstable Book](the-unstable-book.md)
 
-- [abi_msp430_interrupt](abi-msp430-interrupt.md)
-- [abi_ptx](abi-ptx.md)
-- [abi_sysv64](abi-sysv64.md)
-- [abi_unadjusted](abi-unadjusted.md)
-- [abi_vectorcall](abi-vectorcall.md)
-- [abi_x86_interrupt](abi-x86-interrupt.md)
-- [advanced_slice_patterns](advanced-slice-patterns.md)
-- [alloc](alloc.md)
-- [alloc_jemalloc](alloc-jemalloc.md)
-- [alloc_system](alloc-system.md)
-- [allocator](allocator.md)
-- [allow_internal_unstable](allow-internal-unstable.md)
-- [as_c_str](as-c-str.md)
-- [as_unsafe_cell](as-unsafe-cell.md)
-- [ascii_ctype](ascii-ctype.md)
-- [asm](asm.md)
-- [associated_consts](associated-consts.md)
-- [associated_type_defaults](associated-type-defaults.md)
-- [attr_literals](attr-literals.md)
-- [binary_heap_extras](binary-heap-extras.md)
-- [binary_heap_peek_mut_pop](binary-heap-peek-mut-pop.md)
-- [borrow_state](borrow-state.md)
-- [box_heap](box-heap.md)
-- [box_patterns](box-patterns.md)
-- [box_syntax](box-syntax.md)
-- [c_void_variant](c-void-variant.md)
-- [catch_expr](catch-expr.md)
-- [cfg_target_feature](cfg-target-feature.md)
-- [cfg_target_has_atomic](cfg-target-has-atomic.md)
-- [cfg_target_thread_local](cfg-target-thread-local.md)
-- [cfg_target_vendor](cfg-target-vendor.md)
-- [char_escape_debug](char-escape-debug.md)
-- [closure_to_fn_coercion](closure-to-fn-coercion.md)
-- [coerce_unsized](coerce-unsized.md)
-- [collection_placement](collection-placement.md)
-- [collections](collections.md)
-- [collections_range](collections-range.md)
-- [command_envs](command-envs.md)
-- [compiler_fences](compiler-fences.md)
-- [compiler_builtins](compiler-builtins.md)
-- [compiler_builtins_lib](compiler-builtins-lib.md)
-- [concat_idents](concat-idents.md)
-- [concat_idents_macro](concat-idents-macro.md)
-- [conservative_impl_trait](conservative-impl-trait.md)
-- [const_fn](const-fn.md)
-- [const_indexing](const-indexing.md)
-- [core_char_ext](core-char-ext.md)
-- [core_float](core-float.md)
-- [core_intrinsics](core-intrinsics.md)
-- [core_panic](core-panic.md)
-- [core_private_bignum](core-private-bignum.md)
-- [core_private_diy_float](core-private-diy-float.md)
-- [core_slice_ext](core-slice-ext.md)
-- [core_str_ext](core-str-ext.md)
-- [custom_attribute](custom-attribute.md)
-- [custom_derive](custom-derive.md)
-- [dec2flt](dec2flt.md)
-- [decode_utf8](decode-utf8.md)
-- [default_type_parameter_fallback](default-type-parameter-fallback.md)
-- [derive_clone_copy](derive-clone-copy.md)
-- [derive_eq](derive-eq.md)
-- [discriminant_value](discriminant-value.md)
-- [drop_types_in_const](drop-types-in-const.md)
-- [dropck_eyepatch](dropck-eyepatch.md)
-- [dropck_parametricity](dropck-parametricity.md)
-- [enumset](enumset.md)
-- [error_type_id](error-type-id.md)
-- [exact_size_is_empty](exact-size-is-empty.md)
-- [exclusive_range_pattern](exclusive-range-pattern.md)
-- [fd](fd.md)
-- [fd_read](fd-read.md)
-- [fixed_size_array](fixed-size-array.md)
-- [float_bits_conv](float-bits-conv.md)
-- [float_extras](float-extras.md)
-- [flt2dec](flt2dec.md)
-- [fmt_flags_align](fmt-flags-align.md)
-- [fmt_internals](fmt-internals.md)
-- [fn_traits](fn-traits.md)
-- [fnbox](fnbox.md)
-- [from_utf8_error_as_bytes](from_utf8_error_as_bytes.md)
-- [fundamental](fundamental.md)
-- [fused](fused.md)
-- [future_atomic_orderings](future-atomic-orderings.md)
-- [generic_param_attrs](generic-param-attrs.md)
-- [get_type_id](get-type-id.md)
-- [global_asm](global_asm.md)
-- [heap_api](heap-api.md)
-- [i128](i128.md)
-- [i128_type](i128-type.md)
-- [inclusive_range](inclusive-range.md)
-- [inclusive_range_syntax](inclusive-range-syntax.md)
-- [int_error_internals](int-error-internals.md)
-- [integer_atomics](integer-atomics.md)
-- [into_boxed_c_str](into-boxed-c-str.md)
-- [into_boxed_os_str](into-boxed-os-str.md)
-- [into_boxed_path](into-boxed-path.md)
-- [intrinsics](intrinsics.md)
-- [io](io.md)
-- [io_error_internals](io-error-internals.md)
-- [ip](ip.md)
-- [is_unique](is-unique.md)
-- [iter_rfind](iter-rfind.md)
-- [lang_items](lang-items.md)
-- [libstd_io_internals](libstd-io-internals.md)
-- [libstd_sys_internals](libstd-sys-internals.md)
-- [libstd_thread_internals](libstd-thread-internals.md)
-- [link_args](link-args.md)
-- [link_cfg](link-cfg.md)
-- [link_llvm_intrinsics](link-llvm-intrinsics.md)
-- [linkage](linkage.md)
-- [linked_list_extras](linked-list-extras.md)
-- [linker_flavor](linker-flavor.md)
-- [log_syntax](log-syntax.md)
-- [lookup_host](lookup-host.md)
-- [loop_break_value](loop-break-value.md)
-- [macro_reexport](macro-reexport.md)
-- [macro_vis_matcher](macro-vis-matcher.md)
-- [main](main.md)
-- [manually_drop](manually-drop.md)
-- [map_entry_recover_keys](map-entry-recover-keys.md)
-- [mpsc_select](mpsc-select.md)
-- [n16](n16.md)
-- [naked_functions](naked-functions.md)
-- [needs_allocator](needs-allocator.md)
-- [needs_panic_runtime](needs-panic-runtime.md)
-- [never_type](never-type.md)
-- [never_type_impls](never-type-impls.md)
-- [no_core](no-core.md)
-- [no_debug](no-debug.md)
-- [non_ascii_idents](non-ascii-idents.md)
-- [nonzero](nonzero.md)
-- [offset_to](offset-to.md)
-- [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md)
-- [on_unimplemented](on-unimplemented.md)
-- [once_poison](once-poison.md)
-- [oom](oom.md)
-- [optin_builtin_traits](optin-builtin-traits.md)
-- [option_entry](option-entry.md)
-- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
-- [overlapping_marker_traits](overlapping-marker-traits.md)
-- [panic_abort](panic-abort.md)
-- [panic_runtime](panic-runtime.md)
-- [panic_unwind](panic-unwind.md)
-- [pattern](pattern.md)
-- [peek](peek.md)
-- [placement_in](placement-in.md)
-- [placement_in_syntax](placement-in-syntax.md)
-- [placement_new_protocol](placement-new-protocol.md)
-- [platform_intrinsics](platform-intrinsics.md)
-- [plugin](plugin.md)
-- [plugin_registrar](plugin-registrar.md)
-- [prelude_import](prelude-import.md)
-- [print](print.md)
-- [proc_macro](proc-macro.md)
-- [proc_macro_internals](proc-macro-internals.md)
-- [process_try_wait](process-try-wait.md)
-- [question_mark_carrier](question-mark-carrier.md)
-- [quote](quote.md)
-- [rand](rand.md)
-- [range_contains](range-contains.md)
-- [raw](raw.md)
-- [rc_would_unwrap](rc-would-unwrap.md)
-- [relaxed_adts](relaxed-adts.md)
-- [repr_simd](repr-simd.md)
-- [retain_hash_collection](retain-hash-collection.md)
-- [reverse_cmp_key](reverse-cmp-key.md)
-- [rt](rt.md)
-- [rustc_attrs](rustc-attrs.md)
-- [rustc_diagnostic_macros](rustc-diagnostic-macros.md)
-- [rustc_private](rustc-private.md)
-- [rvalue_static_promotion](rvalue-static-promotion.md)
-- [sanitizer_runtime](sanitizer-runtime.md)
-- [sanitizer_runtime_lib](sanitizer-runtime-lib.md)
-- [set_stdio](set-stdio.md)
-- [shared](shared.md)
-- [simd](simd.md)
-- [simd_ffi](simd-ffi.md)
-- [sip_hash_13](sip-hash-13.md)
-- [slice_concat_ext](slice-concat-ext.md)
-- [slice_get_slice](slice-get-slice.md)
-- [slice_patterns](slice-patterns.md)
-- [slice_rsplit](slice-rsplit.md)
-- [sort_internals](sort-internals.md)
-- [sort_unstable](sort-unstable.md)
-- [specialization](specialization.md)
-- [staged_api](staged-api.md)
-- [start](start.md)
-- [static_nobundle](static-nobundle.md)
-- [step_by](step-by.md)
-- [step_trait](step-trait.md)
-- [stmt_expr_attributes](stmt-expr-attributes.md)
-- [str_checked_slicing](str-checked-slicing.md)
-- [str_escape](str-escape.md)
-- [str_internals](str-internals.md)
-- [str_mut_extras](str-mut-extras.md)
-- [struct_field_attributes](struct-field-attributes.md)
-- [structural_match](structural-match.md)
-- [target_feature](target-feature.md)
-- [test](test.md)
-- [thread_id](thread-id.md)
-- [thread_local](thread-local.md)
-- [thread_local_internals](thread-local-internals.md)
-- [thread_local_state](thread-local-state.md)
-- [toowned_clone_into](toowned-clone-into.md)
-- [trace_macros](trace-macros.md)
-- [trusted_len](trusted-len.md)
-- [try_from](try-from.md)
-- [type_ascription](type-ascription.md)
-- [unboxed_closures](unboxed-closures.md)
-- [unicode](unicode.md)
-- [unique](unique.md)
-- [unsize](unsize.md)
-- [untagged_unions](untagged-unions.md)
-- [unwind_attributes](unwind-attributes.md)
-- [update_panic_count](update-panic-count.md)
-- [use_extern_macros](use-extern-macros.md)
-- [used](used.md)
-- [utf8_error_error_len](utf8-error-error-len.md)
-- [vec_remove_item](vec-remove-item.md)
-- [windows_c](windows-c.md)
-- [windows_handle](windows-handle.md)
-- [windows_net](windows-net.md)
-- [windows_stdio](windows-stdio.md)
-- [zero_one](zero-one.md)
+- [Compiler flags](compiler-flags.md)
+    - [linker_flavor](compiler-flags/linker-flavor.md)
+- [Language features](language-features.md)
+    - [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md)
+    - [abi_ptx](language-features/abi-ptx.md)
+    - [abi_sysv64](language-features/abi-sysv64.md)
+    - [abi_unadjusted](language-features/abi-unadjusted.md)
+    - [abi_vectorcall](language-features/abi-vectorcall.md)
+    - [abi_x86_interrupt](language-features/abi-x86-interrupt.md)
+    - [advanced_slice_patterns](language-features/advanced-slice-patterns.md)
+    - [allocator](language-features/allocator.md)
+    - [allow_internal_unstable](language-features/allow-internal-unstable.md)
+    - [asm](language-features/asm.md)
+    - [associated_consts](language-features/associated-consts.md)
+    - [associated_type_defaults](language-features/associated-type-defaults.md)
+    - [attr_literals](language-features/attr-literals.md)
+    - [box_patterns](language-features/box-patterns.md)
+    - [box_syntax](language-features/box-syntax.md)
+    - [catch_expr](language-features/catch-expr.md)
+    - [cfg_target_feature](language-features/cfg-target-feature.md)
+    - [cfg_target_has_atomic](language-features/cfg-target-has-atomic.md)
+    - [cfg_target_thread_local](language-features/cfg-target-thread-local.md)
+    - [cfg_target_vendor](language-features/cfg-target-vendor.md)
+    - [closure_to_fn_coercion](language-features/closure-to-fn-coercion.md)
+    - [compiler_builtins](language-features/compiler-builtins.md)
+    - [concat_idents](language-features/concat-idents.md)
+    - [conservative_impl_trait](language-features/conservative-impl-trait.md)
+    - [const_fn](language-features/const-fn.md)
+    - [const_indexing](language-features/const-indexing.md)
+    - [custom_attribute](language-features/custom-attribute.md)
+    - [custom_derive](language-features/custom-derive.md)
+    - [default_type_parameter_fallback](language-features/default-type-parameter-fallback.md)
+    - [drop_types_in_const](language-features/drop-types-in-const.md)
+    - [dropck_eyepatch](language-features/dropck-eyepatch.md)
+    - [dropck_parametricity](language-features/dropck-parametricity.md)
+    - [exclusive_range_pattern](language-features/exclusive-range-pattern.md)
+    - [fundamental](language-features/fundamental.md)
+    - [generic_param_attrs](language-features/generic-param-attrs.md)
+    - [global_asm](language-features/global_asm.md)
+    - [i128_type](language-features/i128-type.md)
+    - [inclusive_range_syntax](language-features/inclusive-range-syntax.md)
+    - [intrinsics](language-features/intrinsics.md)
+    - [lang_items](language-features/lang-items.md)
+    - [link_args](language-features/link-args.md)
+    - [link_cfg](language-features/link-cfg.md)
+    - [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md)
+    - [linkage](language-features/linkage.md)
+    - [log_syntax](language-features/log-syntax.md)
+    - [loop_break_value](language-features/loop-break-value.md)
+    - [macro_reexport](language-features/macro-reexport.md)
+    - [macro_vis_matcher](language-features/macro-vis-matcher.md)
+    - [main](language-features/main.md)
+    - [naked_functions](language-features/naked-functions.md)
+    - [needs_allocator](language-features/needs-allocator.md)
+    - [needs_panic_runtime](language-features/needs-panic-runtime.md)
+    - [never_type](language-features/never-type.md)
+    - [no_core](language-features/no-core.md)
+    - [no_debug](language-features/no-debug.md)
+    - [non_ascii_idents](language-features/non-ascii-idents.md)
+    - [omit_gdb_pretty_printer_section](language-features/omit-gdb-pretty-printer-section.md)
+    - [on_unimplemented](language-features/on-unimplemented.md)
+    - [optin_builtin_traits](language-features/optin-builtin-traits.md)
+    - [overlapping_marker_traits](language-features/overlapping-marker-traits.md)
+    - [panic_runtime](language-features/panic-runtime.md)
+    - [placement_in_syntax](language-features/placement-in-syntax.md)
+    - [platform_intrinsics](language-features/platform-intrinsics.md)
+    - [plugin](language-features/plugin.md)
+    - [plugin_registrar](language-features/plugin-registrar.md)
+    - [prelude_import](language-features/prelude-import.md)
+    - [proc_macro](language-features/proc-macro.md)
+    - [quote](language-features/quote.md)
+    - [relaxed_adts](language-features/relaxed-adts.md)
+    - [repr_simd](language-features/repr-simd.md)
+    - [rustc_attrs](language-features/rustc-attrs.md)
+    - [rustc_diagnostic_macros](language-features/rustc-diagnostic-macros.md)
+    - [rvalue_static_promotion](language-features/rvalue-static-promotion.md)
+    - [sanitizer_runtime](language-features/sanitizer-runtime.md)
+    - [simd](language-features/simd.md)
+    - [simd_ffi](language-features/simd-ffi.md)
+    - [slice_patterns](language-features/slice-patterns.md)
+    - [specialization](language-features/specialization.md)
+    - [staged_api](language-features/staged-api.md)
+    - [start](language-features/start.md)
+    - [static_nobundle](language-features/static-nobundle.md)
+    - [stmt_expr_attributes](language-features/stmt-expr-attributes.md)
+    - [struct_field_attributes](language-features/struct-field-attributes.md)
+    - [structural_match](language-features/structural-match.md)
+    - [target_feature](language-features/target-feature.md)
+    - [thread_local](language-features/thread-local.md)
+    - [trace_macros](language-features/trace-macros.md)
+    - [type_ascription](language-features/type-ascription.md)
+    - [unboxed_closures](language-features/unboxed-closures.md)
+    - [untagged_unions](language-features/untagged-unions.md)
+    - [unwind_attributes](language-features/unwind-attributes.md)
+    - [use_extern_macros](language-features/use-extern-macros.md)
+    - [used](language-features/used.md)
+- [Library Features](library-features.md)
+    - [alloc_jemalloc](library-features/alloc-jemalloc.md)
+    - [alloc_system](library-features/alloc-system.md)
+    - [alloc](library-features/alloc.md)
+    - [as_c_str](library-features/as-c-str.md)
+    - [as_unsafe_cell](library-features/as-unsafe-cell.md)
+    - [ascii_ctype](library-features/ascii-ctype.md)
+    - [binary_heap_extras](library-features/binary-heap-extras.md)
+    - [binary_heap_peek_mut_pop](library-features/binary-heap-peek-mut-pop.md)
+    - [borrow_state](library-features/borrow-state.md)
+    - [box_heap](library-features/box-heap.md)
+    - [c_void_variant](library-features/c-void-variant.md)
+    - [char_escape_debug](library-features/char-escape-debug.md)
+    - [coerce_unsized](library-features/coerce-unsized.md)
+    - [collection_placement](library-features/collection-placement.md)
+    - [collections_range](library-features/collections-range.md)
+    - [collections](library-features/collections.md)
+    - [command_envs](library-features/command-envs.md)
+    - [compiler_barriers](library-features/compiler-barriers.md)
+    - [compiler_builtins_lib](library-features/compiler-builtins-lib.md)
+    - [compiler_fences](library-features/compiler-fences.md)
+    - [concat_idents_macro](library-features/concat-idents-macro.md)
+    - [core_char_ext](library-features/core-char-ext.md)
+    - [core_float](library-features/core-float.md)
+    - [core_intrinsics](library-features/core-intrinsics.md)
+    - [core_panic](library-features/core-panic.md)
+    - [core_private_bignum](library-features/core-private-bignum.md)
+    - [core_private_diy_float](library-features/core-private-diy-float.md)
+    - [core_slice_ext](library-features/core-slice-ext.md)
+    - [core_str_ext](library-features/core-str-ext.md)
+    - [dec2flt](library-features/dec2flt.md)
+    - [decode_utf8](library-features/decode-utf8.md)
+    - [derive_clone_copy](library-features/derive-clone-copy.md)
+    - [derive_eq](library-features/derive-eq.md)
+    - [discriminant_value](library-features/discriminant-value.md)
+    - [enumset](library-features/enumset.md)
+    - [error_type_id](library-features/error-type-id.md)
+    - [exact_size_is_empty](library-features/exact-size-is-empty.md)
+    - [fd](library-features/fd.md)
+    - [fd_read](library-features/fd-read.md)
+    - [fixed_size_array](library-features/fixed-size-array.md)
+    - [float_bits_conv](library-features/float_bits_conv.md)
+    - [float_extras](library-features/float-extras.md)
+    - [flt2dec](library-features/flt2dec.md)
+    - [fmt_flags_align](library-features/fmt-flags-align.md)
+    - [fmt_internals](library-features/fmt-internals.md)
+    - [fn_traits](library-features/fn-traits.md)
+    - [fnbox](library-features/fnbox.md)
+    - [from_utf8_error_as_bytes](library-features/from_utf8_error_as_bytes.md)
+    - [fused](library-features/fused.md)
+    - [future_atomic_orderings](library-features/future-atomic-orderings.md)
+    - [get_type_id](library-features/get-type-id.md)
+    - [heap_api](library-features/heap-api.md)
+    - [i128](library-features/i128.md)
+    - [inclusive_range](library-features/inclusive-range.md)
+    - [integer_atomics](library-features/integer-atomics.md)
+    - [into_boxed_c_str](library-features/into-boxed-c-str.md)
+    - [into_boxed_os_str](library-features/into-boxed-os-str.md)
+    - [into_boxed_path](library-features/into-boxed-path.md)
+    - [io_error_internals](library-features/io-error-internals.md)
+    - [io](library-features/io.md)
+    - [ip](library-features/ip.md)
+    - [is_unique](library-features/is-unique.md)
+    - [iter_rfind](library-features/iter-rfind.md)
+    - [libstd_io_internals](library-features/libstd-io-internals.md)
+    - [libstd_sys_internals](library-features/libstd-sys-internals.md)
+    - [libstd_thread_internals](library-features/libstd-thread-internals.md)
+    - [linked_list_extras](library-features/linked-list-extras.md)
+    - [lookup_host](library-features/lookup-host.md)
+    - [manually_drop](library-features/manually-drop.md)
+    - [map_entry_recover_keys](library-features/map-entry-recover-keys.md)
+    - [mpsc_select](library-features/mpsc-select.md)
+    - [n16](library-features/n16.md)
+    - [never_type_impls](library-features/never-type-impls.md)
+    - [nonzero](library-features/nonzero.md)
+    - [offset_to](library-features/offset-to.md)
+    - [once_poison](library-features/once-poison.md)
+    - [oom](library-features/oom.md)
+    - [option_entry](library-features/option-entry.md)
+    - [osstring_shrink_to_fit](library-features/osstring-shrink-to-fit.md)
+    - [panic_abort](library-features/panic-abort.md)
+    - [panic_unwind](library-features/panic-unwind.md)
+    - [pattern](library-features/pattern.md)
+    - [peek](library-features/peek.md)
+    - [placement_in](library-features/placement-in.md)
+    - [placement_new_protocol](library-features/placement-new-protocol.md)
+    - [print](library-features/print.md)
+    - [proc_macro_internals](library-features/proc-macro-internals.md)
+    - [process_try_wait](library-features/process-try-wait.md)
+    - [question_mark_carrier](library-features/question-mark-carrier.md)
+    - [rand](library-features/rand.md)
+    - [range_contains](library-features/range-contains.md)
+    - [raw](library-features/raw.md)
+    - [rc_would_unwrap](library-features/rc-would-unwrap.md)
+    - [retain_hash_collection](library-features/retain-hash-collection.md)
+    - [reverse_cmp_key](library-features/reverse-cmp-key.md)
+    - [rt](library-features/rt.md)
+    - [rustc_private](library-features/rustc-private.md)
+    - [sanitizer_runtime_lib](library-features/sanitizer-runtime-lib.md)
+    - [set_stdio](library-features/set-stdio.md)
+    - [shared](library-features/shared.md)
+    - [sip_hash_13](library-features/sip-hash-13.md)
+    - [slice_concat_ext](library-features/slice-concat-ext.md)
+    - [slice_get_slice](library-features/slice-get-slice.md)
+    - [slice_rsplit](library-features/slice-rsplit.md)
+    - [sort_internals](library-features/sort-internals.md)
+    - [sort_unstable](library-features/sort-unstable.md)
+    - [step_by](library-features/step-by.md)
+    - [step_trait](library-features/step-trait.md)
+    - [str_checked_slicing](library-features/str-checked-slicing.md)
+    - [str_escape](library-features/str-escape.md)
+    - [str_internals](library-features/str-internals.md)
+    - [str_mut_extras](library-features/str-mut-extras.md)
+    - [test](library-features/test.md)
+    - [thread_id](library-features/thread-id.md)
+    - [thread_local_internals](library-features/thread-local-internals.md)
+    - [thread_local_state](library-features/thread-local-state.md)
+    - [toowned_clone_into](library-features/toowned-clone-into.md)
+    - [trusted_len](library-features/trusted-len.md)
+    - [try_from](library-features/try-from.md)
+    - [unicode](library-features/unicode.md)
+    - [unique](library-features/unique.md)
+    - [unsize](library-features/unsize.md)
+    - [utf8_error_error_len](library-features/utf8-error-error-len.md)
+    - [vec_remove_item](library-features/vec-remove-item.md)
+    - [windows_c](library-features/windows-c.md)
+    - [windows_handle](library-features/windows-handle.md)
+    - [windows_net](library-features/windows-net.md)
+    - [windows_stdio](library-features/windows-stdio.md)
+    - [zero_one](library-features/zero-one.md)
+>>>>>> Add top level sections to the Unstable Book.
diff --git a/src/doc/unstable-book/src/compiler-flags.md b/src/doc/unstable-book/src/compiler-flags.md
new file mode 100644
index 0000000000000..43eadb351016d
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags.md
@@ -0,0 +1 @@
+# Compiler flags
diff --git a/src/doc/unstable-book/src/linker-flavor.md b/src/doc/unstable-book/src/compiler-flags/linker-flavor.md
similarity index 100%
rename from src/doc/unstable-book/src/linker-flavor.md
rename to src/doc/unstable-book/src/compiler-flags/linker-flavor.md
diff --git a/src/doc/unstable-book/src/language-features.md b/src/doc/unstable-book/src/language-features.md
new file mode 100644
index 0000000000000..a27514df97d69
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features.md
@@ -0,0 +1 @@
+# Language features
diff --git a/src/doc/unstable-book/src/abi-msp430-interrupt.md b/src/doc/unstable-book/src/language-features/abi-msp430-interrupt.md
similarity index 100%
rename from src/doc/unstable-book/src/abi-msp430-interrupt.md
rename to src/doc/unstable-book/src/language-features/abi-msp430-interrupt.md
diff --git a/src/doc/unstable-book/src/abi-ptx.md b/src/doc/unstable-book/src/language-features/abi-ptx.md
similarity index 100%
rename from src/doc/unstable-book/src/abi-ptx.md
rename to src/doc/unstable-book/src/language-features/abi-ptx.md
diff --git a/src/doc/unstable-book/src/abi-sysv64.md b/src/doc/unstable-book/src/language-features/abi-sysv64.md
similarity index 100%
rename from src/doc/unstable-book/src/abi-sysv64.md
rename to src/doc/unstable-book/src/language-features/abi-sysv64.md
diff --git a/src/doc/unstable-book/src/abi-unadjusted.md b/src/doc/unstable-book/src/language-features/abi-unadjusted.md
similarity index 100%
rename from src/doc/unstable-book/src/abi-unadjusted.md
rename to src/doc/unstable-book/src/language-features/abi-unadjusted.md
diff --git a/src/doc/unstable-book/src/abi-vectorcall.md b/src/doc/unstable-book/src/language-features/abi-vectorcall.md
similarity index 100%
rename from src/doc/unstable-book/src/abi-vectorcall.md
rename to src/doc/unstable-book/src/language-features/abi-vectorcall.md
diff --git a/src/doc/unstable-book/src/abi-x86-interrupt.md b/src/doc/unstable-book/src/language-features/abi-x86-interrupt.md
similarity index 100%
rename from src/doc/unstable-book/src/abi-x86-interrupt.md
rename to src/doc/unstable-book/src/language-features/abi-x86-interrupt.md
diff --git a/src/doc/unstable-book/src/advanced-slice-patterns.md b/src/doc/unstable-book/src/language-features/advanced-slice-patterns.md
similarity index 100%
rename from src/doc/unstable-book/src/advanced-slice-patterns.md
rename to src/doc/unstable-book/src/language-features/advanced-slice-patterns.md
diff --git a/src/doc/unstable-book/src/allocator.md b/src/doc/unstable-book/src/language-features/allocator.md
similarity index 100%
rename from src/doc/unstable-book/src/allocator.md
rename to src/doc/unstable-book/src/language-features/allocator.md
diff --git a/src/doc/unstable-book/src/allow-internal-unstable.md b/src/doc/unstable-book/src/language-features/allow-internal-unstable.md
similarity index 100%
rename from src/doc/unstable-book/src/allow-internal-unstable.md
rename to src/doc/unstable-book/src/language-features/allow-internal-unstable.md
diff --git a/src/doc/unstable-book/src/asm.md b/src/doc/unstable-book/src/language-features/asm.md
similarity index 100%
rename from src/doc/unstable-book/src/asm.md
rename to src/doc/unstable-book/src/language-features/asm.md
diff --git a/src/doc/unstable-book/src/associated-consts.md b/src/doc/unstable-book/src/language-features/associated-consts.md
similarity index 100%
rename from src/doc/unstable-book/src/associated-consts.md
rename to src/doc/unstable-book/src/language-features/associated-consts.md
diff --git a/src/doc/unstable-book/src/associated-type-defaults.md b/src/doc/unstable-book/src/language-features/associated-type-defaults.md
similarity index 100%
rename from src/doc/unstable-book/src/associated-type-defaults.md
rename to src/doc/unstable-book/src/language-features/associated-type-defaults.md
diff --git a/src/doc/unstable-book/src/attr-literals.md b/src/doc/unstable-book/src/language-features/attr-literals.md
similarity index 100%
rename from src/doc/unstable-book/src/attr-literals.md
rename to src/doc/unstable-book/src/language-features/attr-literals.md
diff --git a/src/doc/unstable-book/src/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md
similarity index 100%
rename from src/doc/unstable-book/src/box-patterns.md
rename to src/doc/unstable-book/src/language-features/box-patterns.md
diff --git a/src/doc/unstable-book/src/box-syntax.md b/src/doc/unstable-book/src/language-features/box-syntax.md
similarity index 100%
rename from src/doc/unstable-book/src/box-syntax.md
rename to src/doc/unstable-book/src/language-features/box-syntax.md
diff --git a/src/doc/unstable-book/src/catch-expr.md b/src/doc/unstable-book/src/language-features/catch-expr.md
similarity index 100%
rename from src/doc/unstable-book/src/catch-expr.md
rename to src/doc/unstable-book/src/language-features/catch-expr.md
diff --git a/src/doc/unstable-book/src/cfg-target-feature.md b/src/doc/unstable-book/src/language-features/cfg-target-feature.md
similarity index 100%
rename from src/doc/unstable-book/src/cfg-target-feature.md
rename to src/doc/unstable-book/src/language-features/cfg-target-feature.md
diff --git a/src/doc/unstable-book/src/cfg-target-has-atomic.md b/src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md
similarity index 100%
rename from src/doc/unstable-book/src/cfg-target-has-atomic.md
rename to src/doc/unstable-book/src/language-features/cfg-target-has-atomic.md
diff --git a/src/doc/unstable-book/src/cfg-target-thread-local.md b/src/doc/unstable-book/src/language-features/cfg-target-thread-local.md
similarity index 100%
rename from src/doc/unstable-book/src/cfg-target-thread-local.md
rename to src/doc/unstable-book/src/language-features/cfg-target-thread-local.md
diff --git a/src/doc/unstable-book/src/cfg-target-vendor.md b/src/doc/unstable-book/src/language-features/cfg-target-vendor.md
similarity index 100%
rename from src/doc/unstable-book/src/cfg-target-vendor.md
rename to src/doc/unstable-book/src/language-features/cfg-target-vendor.md
diff --git a/src/doc/unstable-book/src/closure-to-fn-coercion.md b/src/doc/unstable-book/src/language-features/closure-to-fn-coercion.md
similarity index 100%
rename from src/doc/unstable-book/src/closure-to-fn-coercion.md
rename to src/doc/unstable-book/src/language-features/closure-to-fn-coercion.md
diff --git a/src/doc/unstable-book/src/compiler-builtins.md b/src/doc/unstable-book/src/language-features/compiler-builtins.md
similarity index 100%
rename from src/doc/unstable-book/src/compiler-builtins.md
rename to src/doc/unstable-book/src/language-features/compiler-builtins.md
diff --git a/src/doc/unstable-book/src/concat-idents.md b/src/doc/unstable-book/src/language-features/concat-idents.md
similarity index 100%
rename from src/doc/unstable-book/src/concat-idents.md
rename to src/doc/unstable-book/src/language-features/concat-idents.md
diff --git a/src/doc/unstable-book/src/conservative-impl-trait.md b/src/doc/unstable-book/src/language-features/conservative-impl-trait.md
similarity index 100%
rename from src/doc/unstable-book/src/conservative-impl-trait.md
rename to src/doc/unstable-book/src/language-features/conservative-impl-trait.md
diff --git a/src/doc/unstable-book/src/const-fn.md b/src/doc/unstable-book/src/language-features/const-fn.md
similarity index 100%
rename from src/doc/unstable-book/src/const-fn.md
rename to src/doc/unstable-book/src/language-features/const-fn.md
diff --git a/src/doc/unstable-book/src/const-indexing.md b/src/doc/unstable-book/src/language-features/const-indexing.md
similarity index 100%
rename from src/doc/unstable-book/src/const-indexing.md
rename to src/doc/unstable-book/src/language-features/const-indexing.md
diff --git a/src/doc/unstable-book/src/custom-attribute.md b/src/doc/unstable-book/src/language-features/custom-attribute.md
similarity index 100%
rename from src/doc/unstable-book/src/custom-attribute.md
rename to src/doc/unstable-book/src/language-features/custom-attribute.md
diff --git a/src/doc/unstable-book/src/custom-derive.md b/src/doc/unstable-book/src/language-features/custom-derive.md
similarity index 100%
rename from src/doc/unstable-book/src/custom-derive.md
rename to src/doc/unstable-book/src/language-features/custom-derive.md
diff --git a/src/doc/unstable-book/src/default-type-parameter-fallback.md b/src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md
similarity index 100%
rename from src/doc/unstable-book/src/default-type-parameter-fallback.md
rename to src/doc/unstable-book/src/language-features/default-type-parameter-fallback.md
diff --git a/src/doc/unstable-book/src/drop-types-in-const.md b/src/doc/unstable-book/src/language-features/drop-types-in-const.md
similarity index 100%
rename from src/doc/unstable-book/src/drop-types-in-const.md
rename to src/doc/unstable-book/src/language-features/drop-types-in-const.md
diff --git a/src/doc/unstable-book/src/dropck-eyepatch.md b/src/doc/unstable-book/src/language-features/dropck-eyepatch.md
similarity index 100%
rename from src/doc/unstable-book/src/dropck-eyepatch.md
rename to src/doc/unstable-book/src/language-features/dropck-eyepatch.md
diff --git a/src/doc/unstable-book/src/dropck-parametricity.md b/src/doc/unstable-book/src/language-features/dropck-parametricity.md
similarity index 100%
rename from src/doc/unstable-book/src/dropck-parametricity.md
rename to src/doc/unstable-book/src/language-features/dropck-parametricity.md
diff --git a/src/doc/unstable-book/src/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
similarity index 100%
rename from src/doc/unstable-book/src/exclusive-range-pattern.md
rename to src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
diff --git a/src/doc/unstable-book/src/fundamental.md b/src/doc/unstable-book/src/language-features/fundamental.md
similarity index 100%
rename from src/doc/unstable-book/src/fundamental.md
rename to src/doc/unstable-book/src/language-features/fundamental.md
diff --git a/src/doc/unstable-book/src/generic-param-attrs.md b/src/doc/unstable-book/src/language-features/generic-param-attrs.md
similarity index 100%
rename from src/doc/unstable-book/src/generic-param-attrs.md
rename to src/doc/unstable-book/src/language-features/generic-param-attrs.md
diff --git a/src/doc/unstable-book/src/global_asm.md b/src/doc/unstable-book/src/language-features/global_asm.md
similarity index 100%
rename from src/doc/unstable-book/src/global_asm.md
rename to src/doc/unstable-book/src/language-features/global_asm.md
diff --git a/src/doc/unstable-book/src/i128-type.md b/src/doc/unstable-book/src/language-features/i128-type.md
similarity index 100%
rename from src/doc/unstable-book/src/i128-type.md
rename to src/doc/unstable-book/src/language-features/i128-type.md
diff --git a/src/doc/unstable-book/src/inclusive-range-syntax.md b/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md
similarity index 100%
rename from src/doc/unstable-book/src/inclusive-range-syntax.md
rename to src/doc/unstable-book/src/language-features/inclusive-range-syntax.md
diff --git a/src/doc/unstable-book/src/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md
similarity index 100%
rename from src/doc/unstable-book/src/intrinsics.md
rename to src/doc/unstable-book/src/language-features/intrinsics.md
diff --git a/src/doc/unstable-book/src/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
similarity index 100%
rename from src/doc/unstable-book/src/lang-items.md
rename to src/doc/unstable-book/src/language-features/lang-items.md
diff --git a/src/doc/unstable-book/src/link-args.md b/src/doc/unstable-book/src/language-features/link-args.md
similarity index 100%
rename from src/doc/unstable-book/src/link-args.md
rename to src/doc/unstable-book/src/language-features/link-args.md
diff --git a/src/doc/unstable-book/src/link-cfg.md b/src/doc/unstable-book/src/language-features/link-cfg.md
similarity index 100%
rename from src/doc/unstable-book/src/link-cfg.md
rename to src/doc/unstable-book/src/language-features/link-cfg.md
diff --git a/src/doc/unstable-book/src/link-llvm-intrinsics.md b/src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md
similarity index 100%
rename from src/doc/unstable-book/src/link-llvm-intrinsics.md
rename to src/doc/unstable-book/src/language-features/link-llvm-intrinsics.md
diff --git a/src/doc/unstable-book/src/linkage.md b/src/doc/unstable-book/src/language-features/linkage.md
similarity index 100%
rename from src/doc/unstable-book/src/linkage.md
rename to src/doc/unstable-book/src/language-features/linkage.md
diff --git a/src/doc/unstable-book/src/log-syntax.md b/src/doc/unstable-book/src/language-features/log-syntax.md
similarity index 100%
rename from src/doc/unstable-book/src/log-syntax.md
rename to src/doc/unstable-book/src/language-features/log-syntax.md
diff --git a/src/doc/unstable-book/src/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md
similarity index 100%
rename from src/doc/unstable-book/src/loop-break-value.md
rename to src/doc/unstable-book/src/language-features/loop-break-value.md
diff --git a/src/doc/unstable-book/src/macro-reexport.md b/src/doc/unstable-book/src/language-features/macro-reexport.md
similarity index 100%
rename from src/doc/unstable-book/src/macro-reexport.md
rename to src/doc/unstable-book/src/language-features/macro-reexport.md
diff --git a/src/doc/unstable-book/src/macro-vis-matcher.md b/src/doc/unstable-book/src/language-features/macro-vis-matcher.md
similarity index 100%
rename from src/doc/unstable-book/src/macro-vis-matcher.md
rename to src/doc/unstable-book/src/language-features/macro-vis-matcher.md
diff --git a/src/doc/unstable-book/src/main.md b/src/doc/unstable-book/src/language-features/main.md
similarity index 100%
rename from src/doc/unstable-book/src/main.md
rename to src/doc/unstable-book/src/language-features/main.md
diff --git a/src/doc/unstable-book/src/naked-functions.md b/src/doc/unstable-book/src/language-features/naked-functions.md
similarity index 100%
rename from src/doc/unstable-book/src/naked-functions.md
rename to src/doc/unstable-book/src/language-features/naked-functions.md
diff --git a/src/doc/unstable-book/src/needs-allocator.md b/src/doc/unstable-book/src/language-features/needs-allocator.md
similarity index 100%
rename from src/doc/unstable-book/src/needs-allocator.md
rename to src/doc/unstable-book/src/language-features/needs-allocator.md
diff --git a/src/doc/unstable-book/src/needs-panic-runtime.md b/src/doc/unstable-book/src/language-features/needs-panic-runtime.md
similarity index 100%
rename from src/doc/unstable-book/src/needs-panic-runtime.md
rename to src/doc/unstable-book/src/language-features/needs-panic-runtime.md
diff --git a/src/doc/unstable-book/src/never-type.md b/src/doc/unstable-book/src/language-features/never-type.md
similarity index 100%
rename from src/doc/unstable-book/src/never-type.md
rename to src/doc/unstable-book/src/language-features/never-type.md
diff --git a/src/doc/unstable-book/src/no-core.md b/src/doc/unstable-book/src/language-features/no-core.md
similarity index 100%
rename from src/doc/unstable-book/src/no-core.md
rename to src/doc/unstable-book/src/language-features/no-core.md
diff --git a/src/doc/unstable-book/src/no-debug.md b/src/doc/unstable-book/src/language-features/no-debug.md
similarity index 100%
rename from src/doc/unstable-book/src/no-debug.md
rename to src/doc/unstable-book/src/language-features/no-debug.md
diff --git a/src/doc/unstable-book/src/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md
similarity index 100%
rename from src/doc/unstable-book/src/non-ascii-idents.md
rename to src/doc/unstable-book/src/language-features/non-ascii-idents.md
diff --git a/src/doc/unstable-book/src/omit-gdb-pretty-printer-section.md b/src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md
similarity index 100%
rename from src/doc/unstable-book/src/omit-gdb-pretty-printer-section.md
rename to src/doc/unstable-book/src/language-features/omit-gdb-pretty-printer-section.md
diff --git a/src/doc/unstable-book/src/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md
similarity index 100%
rename from src/doc/unstable-book/src/on-unimplemented.md
rename to src/doc/unstable-book/src/language-features/on-unimplemented.md
diff --git a/src/doc/unstable-book/src/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md
similarity index 100%
rename from src/doc/unstable-book/src/optin-builtin-traits.md
rename to src/doc/unstable-book/src/language-features/optin-builtin-traits.md
diff --git a/src/doc/unstable-book/src/overlapping-marker-traits.md b/src/doc/unstable-book/src/language-features/overlapping-marker-traits.md
similarity index 100%
rename from src/doc/unstable-book/src/overlapping-marker-traits.md
rename to src/doc/unstable-book/src/language-features/overlapping-marker-traits.md
diff --git a/src/doc/unstable-book/src/panic-runtime.md b/src/doc/unstable-book/src/language-features/panic-runtime.md
similarity index 100%
rename from src/doc/unstable-book/src/panic-runtime.md
rename to src/doc/unstable-book/src/language-features/panic-runtime.md
diff --git a/src/doc/unstable-book/src/placement-in-syntax.md b/src/doc/unstable-book/src/language-features/placement-in-syntax.md
similarity index 100%
rename from src/doc/unstable-book/src/placement-in-syntax.md
rename to src/doc/unstable-book/src/language-features/placement-in-syntax.md
diff --git a/src/doc/unstable-book/src/platform-intrinsics.md b/src/doc/unstable-book/src/language-features/platform-intrinsics.md
similarity index 100%
rename from src/doc/unstable-book/src/platform-intrinsics.md
rename to src/doc/unstable-book/src/language-features/platform-intrinsics.md
diff --git a/src/doc/unstable-book/src/plugin-registrar.md b/src/doc/unstable-book/src/language-features/plugin-registrar.md
similarity index 100%
rename from src/doc/unstable-book/src/plugin-registrar.md
rename to src/doc/unstable-book/src/language-features/plugin-registrar.md
diff --git a/src/doc/unstable-book/src/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
similarity index 100%
rename from src/doc/unstable-book/src/plugin.md
rename to src/doc/unstable-book/src/language-features/plugin.md
diff --git a/src/doc/unstable-book/src/prelude-import.md b/src/doc/unstable-book/src/language-features/prelude-import.md
similarity index 100%
rename from src/doc/unstable-book/src/prelude-import.md
rename to src/doc/unstable-book/src/language-features/prelude-import.md
diff --git a/src/doc/unstable-book/src/proc-macro.md b/src/doc/unstable-book/src/language-features/proc-macro.md
similarity index 100%
rename from src/doc/unstable-book/src/proc-macro.md
rename to src/doc/unstable-book/src/language-features/proc-macro.md
diff --git a/src/doc/unstable-book/src/quote.md b/src/doc/unstable-book/src/language-features/quote.md
similarity index 100%
rename from src/doc/unstable-book/src/quote.md
rename to src/doc/unstable-book/src/language-features/quote.md
diff --git a/src/doc/unstable-book/src/relaxed-adts.md b/src/doc/unstable-book/src/language-features/relaxed-adts.md
similarity index 100%
rename from src/doc/unstable-book/src/relaxed-adts.md
rename to src/doc/unstable-book/src/language-features/relaxed-adts.md
diff --git a/src/doc/unstable-book/src/repr-simd.md b/src/doc/unstable-book/src/language-features/repr-simd.md
similarity index 100%
rename from src/doc/unstable-book/src/repr-simd.md
rename to src/doc/unstable-book/src/language-features/repr-simd.md
diff --git a/src/doc/unstable-book/src/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md
similarity index 100%
rename from src/doc/unstable-book/src/rustc-attrs.md
rename to src/doc/unstable-book/src/language-features/rustc-attrs.md
diff --git a/src/doc/unstable-book/src/rustc-diagnostic-macros.md b/src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md
similarity index 100%
rename from src/doc/unstable-book/src/rustc-diagnostic-macros.md
rename to src/doc/unstable-book/src/language-features/rustc-diagnostic-macros.md
diff --git a/src/doc/unstable-book/src/rvalue-static-promotion.md b/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md
similarity index 100%
rename from src/doc/unstable-book/src/rvalue-static-promotion.md
rename to src/doc/unstable-book/src/language-features/rvalue-static-promotion.md
diff --git a/src/doc/unstable-book/src/sanitizer-runtime.md b/src/doc/unstable-book/src/language-features/sanitizer-runtime.md
similarity index 100%
rename from src/doc/unstable-book/src/sanitizer-runtime.md
rename to src/doc/unstable-book/src/language-features/sanitizer-runtime.md
diff --git a/src/doc/unstable-book/src/simd-ffi.md b/src/doc/unstable-book/src/language-features/simd-ffi.md
similarity index 100%
rename from src/doc/unstable-book/src/simd-ffi.md
rename to src/doc/unstable-book/src/language-features/simd-ffi.md
diff --git a/src/doc/unstable-book/src/simd.md b/src/doc/unstable-book/src/language-features/simd.md
similarity index 100%
rename from src/doc/unstable-book/src/simd.md
rename to src/doc/unstable-book/src/language-features/simd.md
diff --git a/src/doc/unstable-book/src/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md
similarity index 100%
rename from src/doc/unstable-book/src/slice-patterns.md
rename to src/doc/unstable-book/src/language-features/slice-patterns.md
diff --git a/src/doc/unstable-book/src/specialization.md b/src/doc/unstable-book/src/language-features/specialization.md
similarity index 100%
rename from src/doc/unstable-book/src/specialization.md
rename to src/doc/unstable-book/src/language-features/specialization.md
diff --git a/src/doc/unstable-book/src/staged-api.md b/src/doc/unstable-book/src/language-features/staged-api.md
similarity index 100%
rename from src/doc/unstable-book/src/staged-api.md
rename to src/doc/unstable-book/src/language-features/staged-api.md
diff --git a/src/doc/unstable-book/src/start.md b/src/doc/unstable-book/src/language-features/start.md
similarity index 100%
rename from src/doc/unstable-book/src/start.md
rename to src/doc/unstable-book/src/language-features/start.md
diff --git a/src/doc/unstable-book/src/static-nobundle.md b/src/doc/unstable-book/src/language-features/static-nobundle.md
similarity index 100%
rename from src/doc/unstable-book/src/static-nobundle.md
rename to src/doc/unstable-book/src/language-features/static-nobundle.md
diff --git a/src/doc/unstable-book/src/stmt-expr-attributes.md b/src/doc/unstable-book/src/language-features/stmt-expr-attributes.md
similarity index 100%
rename from src/doc/unstable-book/src/stmt-expr-attributes.md
rename to src/doc/unstable-book/src/language-features/stmt-expr-attributes.md
diff --git a/src/doc/unstable-book/src/struct-field-attributes.md b/src/doc/unstable-book/src/language-features/struct-field-attributes.md
similarity index 100%
rename from src/doc/unstable-book/src/struct-field-attributes.md
rename to src/doc/unstable-book/src/language-features/struct-field-attributes.md
diff --git a/src/doc/unstable-book/src/structural-match.md b/src/doc/unstable-book/src/language-features/structural-match.md
similarity index 100%
rename from src/doc/unstable-book/src/structural-match.md
rename to src/doc/unstable-book/src/language-features/structural-match.md
diff --git a/src/doc/unstable-book/src/target-feature.md b/src/doc/unstable-book/src/language-features/target-feature.md
similarity index 100%
rename from src/doc/unstable-book/src/target-feature.md
rename to src/doc/unstable-book/src/language-features/target-feature.md
diff --git a/src/doc/unstable-book/src/thread-local.md b/src/doc/unstable-book/src/language-features/thread-local.md
similarity index 100%
rename from src/doc/unstable-book/src/thread-local.md
rename to src/doc/unstable-book/src/language-features/thread-local.md
diff --git a/src/doc/unstable-book/src/trace-macros.md b/src/doc/unstable-book/src/language-features/trace-macros.md
similarity index 100%
rename from src/doc/unstable-book/src/trace-macros.md
rename to src/doc/unstable-book/src/language-features/trace-macros.md
diff --git a/src/doc/unstable-book/src/type-ascription.md b/src/doc/unstable-book/src/language-features/type-ascription.md
similarity index 100%
rename from src/doc/unstable-book/src/type-ascription.md
rename to src/doc/unstable-book/src/language-features/type-ascription.md
diff --git a/src/doc/unstable-book/src/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md
similarity index 100%
rename from src/doc/unstable-book/src/unboxed-closures.md
rename to src/doc/unstable-book/src/language-features/unboxed-closures.md
diff --git a/src/doc/unstable-book/src/untagged-unions.md b/src/doc/unstable-book/src/language-features/untagged-unions.md
similarity index 100%
rename from src/doc/unstable-book/src/untagged-unions.md
rename to src/doc/unstable-book/src/language-features/untagged-unions.md
diff --git a/src/doc/unstable-book/src/unwind-attributes.md b/src/doc/unstable-book/src/language-features/unwind-attributes.md
similarity index 100%
rename from src/doc/unstable-book/src/unwind-attributes.md
rename to src/doc/unstable-book/src/language-features/unwind-attributes.md
diff --git a/src/doc/unstable-book/src/use-extern-macros.md b/src/doc/unstable-book/src/language-features/use-extern-macros.md
similarity index 100%
rename from src/doc/unstable-book/src/use-extern-macros.md
rename to src/doc/unstable-book/src/language-features/use-extern-macros.md
diff --git a/src/doc/unstable-book/src/used.md b/src/doc/unstable-book/src/language-features/used.md
similarity index 100%
rename from src/doc/unstable-book/src/used.md
rename to src/doc/unstable-book/src/language-features/used.md
diff --git a/src/doc/unstable-book/src/library-features.md b/src/doc/unstable-book/src/library-features.md
new file mode 100644
index 0000000000000..9f537e26132bc
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features.md
@@ -0,0 +1 @@
+# Library Features
diff --git a/src/doc/unstable-book/src/alloc-jemalloc.md b/src/doc/unstable-book/src/library-features/alloc-jemalloc.md
similarity index 100%
rename from src/doc/unstable-book/src/alloc-jemalloc.md
rename to src/doc/unstable-book/src/library-features/alloc-jemalloc.md
diff --git a/src/doc/unstable-book/src/alloc-system.md b/src/doc/unstable-book/src/library-features/alloc-system.md
similarity index 100%
rename from src/doc/unstable-book/src/alloc-system.md
rename to src/doc/unstable-book/src/library-features/alloc-system.md
diff --git a/src/doc/unstable-book/src/alloc.md b/src/doc/unstable-book/src/library-features/alloc.md
similarity index 100%
rename from src/doc/unstable-book/src/alloc.md
rename to src/doc/unstable-book/src/library-features/alloc.md
diff --git a/src/doc/unstable-book/src/as-c-str.md b/src/doc/unstable-book/src/library-features/as-c-str.md
similarity index 100%
rename from src/doc/unstable-book/src/as-c-str.md
rename to src/doc/unstable-book/src/library-features/as-c-str.md
diff --git a/src/doc/unstable-book/src/as-unsafe-cell.md b/src/doc/unstable-book/src/library-features/as-unsafe-cell.md
similarity index 100%
rename from src/doc/unstable-book/src/as-unsafe-cell.md
rename to src/doc/unstable-book/src/library-features/as-unsafe-cell.md
diff --git a/src/doc/unstable-book/src/ascii-ctype.md b/src/doc/unstable-book/src/library-features/ascii-ctype.md
similarity index 100%
rename from src/doc/unstable-book/src/ascii-ctype.md
rename to src/doc/unstable-book/src/library-features/ascii-ctype.md
diff --git a/src/doc/unstable-book/src/binary-heap-extras.md b/src/doc/unstable-book/src/library-features/binary-heap-extras.md
similarity index 100%
rename from src/doc/unstable-book/src/binary-heap-extras.md
rename to src/doc/unstable-book/src/library-features/binary-heap-extras.md
diff --git a/src/doc/unstable-book/src/binary-heap-peek-mut-pop.md b/src/doc/unstable-book/src/library-features/binary-heap-peek-mut-pop.md
similarity index 100%
rename from src/doc/unstable-book/src/binary-heap-peek-mut-pop.md
rename to src/doc/unstable-book/src/library-features/binary-heap-peek-mut-pop.md
diff --git a/src/doc/unstable-book/src/borrow-state.md b/src/doc/unstable-book/src/library-features/borrow-state.md
similarity index 100%
rename from src/doc/unstable-book/src/borrow-state.md
rename to src/doc/unstable-book/src/library-features/borrow-state.md
diff --git a/src/doc/unstable-book/src/box-heap.md b/src/doc/unstable-book/src/library-features/box-heap.md
similarity index 100%
rename from src/doc/unstable-book/src/box-heap.md
rename to src/doc/unstable-book/src/library-features/box-heap.md
diff --git a/src/doc/unstable-book/src/c-void-variant.md b/src/doc/unstable-book/src/library-features/c-void-variant.md
similarity index 100%
rename from src/doc/unstable-book/src/c-void-variant.md
rename to src/doc/unstable-book/src/library-features/c-void-variant.md
diff --git a/src/doc/unstable-book/src/char-escape-debug.md b/src/doc/unstable-book/src/library-features/char-escape-debug.md
similarity index 100%
rename from src/doc/unstable-book/src/char-escape-debug.md
rename to src/doc/unstable-book/src/library-features/char-escape-debug.md
diff --git a/src/doc/unstable-book/src/coerce-unsized.md b/src/doc/unstable-book/src/library-features/coerce-unsized.md
similarity index 100%
rename from src/doc/unstable-book/src/coerce-unsized.md
rename to src/doc/unstable-book/src/library-features/coerce-unsized.md
diff --git a/src/doc/unstable-book/src/collection-placement.md b/src/doc/unstable-book/src/library-features/collection-placement.md
similarity index 100%
rename from src/doc/unstable-book/src/collection-placement.md
rename to src/doc/unstable-book/src/library-features/collection-placement.md
diff --git a/src/doc/unstable-book/src/collections-range.md b/src/doc/unstable-book/src/library-features/collections-range.md
similarity index 100%
rename from src/doc/unstable-book/src/collections-range.md
rename to src/doc/unstable-book/src/library-features/collections-range.md
diff --git a/src/doc/unstable-book/src/collections.md b/src/doc/unstable-book/src/library-features/collections.md
similarity index 100%
rename from src/doc/unstable-book/src/collections.md
rename to src/doc/unstable-book/src/library-features/collections.md
diff --git a/src/doc/unstable-book/src/command-envs.md b/src/doc/unstable-book/src/library-features/command-envs.md
similarity index 100%
rename from src/doc/unstable-book/src/command-envs.md
rename to src/doc/unstable-book/src/library-features/command-envs.md
diff --git a/src/doc/unstable-book/src/compiler-builtins-lib.md b/src/doc/unstable-book/src/library-features/compiler-builtins-lib.md
similarity index 100%
rename from src/doc/unstable-book/src/compiler-builtins-lib.md
rename to src/doc/unstable-book/src/library-features/compiler-builtins-lib.md
diff --git a/src/doc/unstable-book/src/compiler-fences.md b/src/doc/unstable-book/src/library-features/compiler-fences.md
similarity index 100%
rename from src/doc/unstable-book/src/compiler-fences.md
rename to src/doc/unstable-book/src/library-features/compiler-fences.md
diff --git a/src/doc/unstable-book/src/concat-idents-macro.md b/src/doc/unstable-book/src/library-features/concat-idents-macro.md
similarity index 100%
rename from src/doc/unstable-book/src/concat-idents-macro.md
rename to src/doc/unstable-book/src/library-features/concat-idents-macro.md
diff --git a/src/doc/unstable-book/src/core-char-ext.md b/src/doc/unstable-book/src/library-features/core-char-ext.md
similarity index 100%
rename from src/doc/unstable-book/src/core-char-ext.md
rename to src/doc/unstable-book/src/library-features/core-char-ext.md
diff --git a/src/doc/unstable-book/src/core-float.md b/src/doc/unstable-book/src/library-features/core-float.md
similarity index 100%
rename from src/doc/unstable-book/src/core-float.md
rename to src/doc/unstable-book/src/library-features/core-float.md
diff --git a/src/doc/unstable-book/src/core-intrinsics.md b/src/doc/unstable-book/src/library-features/core-intrinsics.md
similarity index 100%
rename from src/doc/unstable-book/src/core-intrinsics.md
rename to src/doc/unstable-book/src/library-features/core-intrinsics.md
diff --git a/src/doc/unstable-book/src/core-panic.md b/src/doc/unstable-book/src/library-features/core-panic.md
similarity index 100%
rename from src/doc/unstable-book/src/core-panic.md
rename to src/doc/unstable-book/src/library-features/core-panic.md
diff --git a/src/doc/unstable-book/src/core-private-bignum.md b/src/doc/unstable-book/src/library-features/core-private-bignum.md
similarity index 100%
rename from src/doc/unstable-book/src/core-private-bignum.md
rename to src/doc/unstable-book/src/library-features/core-private-bignum.md
diff --git a/src/doc/unstable-book/src/core-private-diy-float.md b/src/doc/unstable-book/src/library-features/core-private-diy-float.md
similarity index 100%
rename from src/doc/unstable-book/src/core-private-diy-float.md
rename to src/doc/unstable-book/src/library-features/core-private-diy-float.md
diff --git a/src/doc/unstable-book/src/core-slice-ext.md b/src/doc/unstable-book/src/library-features/core-slice-ext.md
similarity index 100%
rename from src/doc/unstable-book/src/core-slice-ext.md
rename to src/doc/unstable-book/src/library-features/core-slice-ext.md
diff --git a/src/doc/unstable-book/src/core-str-ext.md b/src/doc/unstable-book/src/library-features/core-str-ext.md
similarity index 100%
rename from src/doc/unstable-book/src/core-str-ext.md
rename to src/doc/unstable-book/src/library-features/core-str-ext.md
diff --git a/src/doc/unstable-book/src/dec2flt.md b/src/doc/unstable-book/src/library-features/dec2flt.md
similarity index 100%
rename from src/doc/unstable-book/src/dec2flt.md
rename to src/doc/unstable-book/src/library-features/dec2flt.md
diff --git a/src/doc/unstable-book/src/decode-utf8.md b/src/doc/unstable-book/src/library-features/decode-utf8.md
similarity index 100%
rename from src/doc/unstable-book/src/decode-utf8.md
rename to src/doc/unstable-book/src/library-features/decode-utf8.md
diff --git a/src/doc/unstable-book/src/derive-clone-copy.md b/src/doc/unstable-book/src/library-features/derive-clone-copy.md
similarity index 100%
rename from src/doc/unstable-book/src/derive-clone-copy.md
rename to src/doc/unstable-book/src/library-features/derive-clone-copy.md
diff --git a/src/doc/unstable-book/src/derive-eq.md b/src/doc/unstable-book/src/library-features/derive-eq.md
similarity index 100%
rename from src/doc/unstable-book/src/derive-eq.md
rename to src/doc/unstable-book/src/library-features/derive-eq.md
diff --git a/src/doc/unstable-book/src/discriminant-value.md b/src/doc/unstable-book/src/library-features/discriminant-value.md
similarity index 100%
rename from src/doc/unstable-book/src/discriminant-value.md
rename to src/doc/unstable-book/src/library-features/discriminant-value.md
diff --git a/src/doc/unstable-book/src/enumset.md b/src/doc/unstable-book/src/library-features/enumset.md
similarity index 100%
rename from src/doc/unstable-book/src/enumset.md
rename to src/doc/unstable-book/src/library-features/enumset.md
diff --git a/src/doc/unstable-book/src/error-type-id.md b/src/doc/unstable-book/src/library-features/error-type-id.md
similarity index 100%
rename from src/doc/unstable-book/src/error-type-id.md
rename to src/doc/unstable-book/src/library-features/error-type-id.md
diff --git a/src/doc/unstable-book/src/exact-size-is-empty.md b/src/doc/unstable-book/src/library-features/exact-size-is-empty.md
similarity index 100%
rename from src/doc/unstable-book/src/exact-size-is-empty.md
rename to src/doc/unstable-book/src/library-features/exact-size-is-empty.md
diff --git a/src/doc/unstable-book/src/fd-read.md b/src/doc/unstable-book/src/library-features/fd-read.md
similarity index 100%
rename from src/doc/unstable-book/src/fd-read.md
rename to src/doc/unstable-book/src/library-features/fd-read.md
diff --git a/src/doc/unstable-book/src/fd.md b/src/doc/unstable-book/src/library-features/fd.md
similarity index 100%
rename from src/doc/unstable-book/src/fd.md
rename to src/doc/unstable-book/src/library-features/fd.md
diff --git a/src/doc/unstable-book/src/fixed-size-array.md b/src/doc/unstable-book/src/library-features/fixed-size-array.md
similarity index 100%
rename from src/doc/unstable-book/src/fixed-size-array.md
rename to src/doc/unstable-book/src/library-features/fixed-size-array.md
diff --git a/src/doc/unstable-book/src/float-bits-conv.md b/src/doc/unstable-book/src/library-features/float-bits-conv.md
similarity index 100%
rename from src/doc/unstable-book/src/float-bits-conv.md
rename to src/doc/unstable-book/src/library-features/float-bits-conv.md
diff --git a/src/doc/unstable-book/src/float-extras.md b/src/doc/unstable-book/src/library-features/float-extras.md
similarity index 100%
rename from src/doc/unstable-book/src/float-extras.md
rename to src/doc/unstable-book/src/library-features/float-extras.md
diff --git a/src/doc/unstable-book/src/flt2dec.md b/src/doc/unstable-book/src/library-features/flt2dec.md
similarity index 100%
rename from src/doc/unstable-book/src/flt2dec.md
rename to src/doc/unstable-book/src/library-features/flt2dec.md
diff --git a/src/doc/unstable-book/src/fmt-flags-align.md b/src/doc/unstable-book/src/library-features/fmt-flags-align.md
similarity index 100%
rename from src/doc/unstable-book/src/fmt-flags-align.md
rename to src/doc/unstable-book/src/library-features/fmt-flags-align.md
diff --git a/src/doc/unstable-book/src/fmt-internals.md b/src/doc/unstable-book/src/library-features/fmt-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/fmt-internals.md
rename to src/doc/unstable-book/src/library-features/fmt-internals.md
diff --git a/src/doc/unstable-book/src/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md
similarity index 100%
rename from src/doc/unstable-book/src/fn-traits.md
rename to src/doc/unstable-book/src/library-features/fn-traits.md
diff --git a/src/doc/unstable-book/src/fnbox.md b/src/doc/unstable-book/src/library-features/fnbox.md
similarity index 100%
rename from src/doc/unstable-book/src/fnbox.md
rename to src/doc/unstable-book/src/library-features/fnbox.md
diff --git a/src/doc/unstable-book/src/from_utf8_error_as_bytes.md b/src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md
similarity index 100%
rename from src/doc/unstable-book/src/from_utf8_error_as_bytes.md
rename to src/doc/unstable-book/src/library-features/from_utf8_error_as_bytes.md
diff --git a/src/doc/unstable-book/src/fused.md b/src/doc/unstable-book/src/library-features/fused.md
similarity index 100%
rename from src/doc/unstable-book/src/fused.md
rename to src/doc/unstable-book/src/library-features/fused.md
diff --git a/src/doc/unstable-book/src/future-atomic-orderings.md b/src/doc/unstable-book/src/library-features/future-atomic-orderings.md
similarity index 100%
rename from src/doc/unstable-book/src/future-atomic-orderings.md
rename to src/doc/unstable-book/src/library-features/future-atomic-orderings.md
diff --git a/src/doc/unstable-book/src/get-type-id.md b/src/doc/unstable-book/src/library-features/get-type-id.md
similarity index 100%
rename from src/doc/unstable-book/src/get-type-id.md
rename to src/doc/unstable-book/src/library-features/get-type-id.md
diff --git a/src/doc/unstable-book/src/heap-api.md b/src/doc/unstable-book/src/library-features/heap-api.md
similarity index 100%
rename from src/doc/unstable-book/src/heap-api.md
rename to src/doc/unstable-book/src/library-features/heap-api.md
diff --git a/src/doc/unstable-book/src/i128.md b/src/doc/unstable-book/src/library-features/i128.md
similarity index 100%
rename from src/doc/unstable-book/src/i128.md
rename to src/doc/unstable-book/src/library-features/i128.md
diff --git a/src/doc/unstable-book/src/inclusive-range.md b/src/doc/unstable-book/src/library-features/inclusive-range.md
similarity index 100%
rename from src/doc/unstable-book/src/inclusive-range.md
rename to src/doc/unstable-book/src/library-features/inclusive-range.md
diff --git a/src/doc/unstable-book/src/int-error-internals.md b/src/doc/unstable-book/src/library-features/int-error-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/int-error-internals.md
rename to src/doc/unstable-book/src/library-features/int-error-internals.md
diff --git a/src/doc/unstable-book/src/integer-atomics.md b/src/doc/unstable-book/src/library-features/integer-atomics.md
similarity index 100%
rename from src/doc/unstable-book/src/integer-atomics.md
rename to src/doc/unstable-book/src/library-features/integer-atomics.md
diff --git a/src/doc/unstable-book/src/into-boxed-c-str.md b/src/doc/unstable-book/src/library-features/into-boxed-c-str.md
similarity index 100%
rename from src/doc/unstable-book/src/into-boxed-c-str.md
rename to src/doc/unstable-book/src/library-features/into-boxed-c-str.md
diff --git a/src/doc/unstable-book/src/into-boxed-os-str.md b/src/doc/unstable-book/src/library-features/into-boxed-os-str.md
similarity index 100%
rename from src/doc/unstable-book/src/into-boxed-os-str.md
rename to src/doc/unstable-book/src/library-features/into-boxed-os-str.md
diff --git a/src/doc/unstable-book/src/into-boxed-path.md b/src/doc/unstable-book/src/library-features/into-boxed-path.md
similarity index 100%
rename from src/doc/unstable-book/src/into-boxed-path.md
rename to src/doc/unstable-book/src/library-features/into-boxed-path.md
diff --git a/src/doc/unstable-book/src/io-error-internals.md b/src/doc/unstable-book/src/library-features/io-error-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/io-error-internals.md
rename to src/doc/unstable-book/src/library-features/io-error-internals.md
diff --git a/src/doc/unstable-book/src/io.md b/src/doc/unstable-book/src/library-features/io.md
similarity index 100%
rename from src/doc/unstable-book/src/io.md
rename to src/doc/unstable-book/src/library-features/io.md
diff --git a/src/doc/unstable-book/src/ip.md b/src/doc/unstable-book/src/library-features/ip.md
similarity index 100%
rename from src/doc/unstable-book/src/ip.md
rename to src/doc/unstable-book/src/library-features/ip.md
diff --git a/src/doc/unstable-book/src/is-unique.md b/src/doc/unstable-book/src/library-features/is-unique.md
similarity index 100%
rename from src/doc/unstable-book/src/is-unique.md
rename to src/doc/unstable-book/src/library-features/is-unique.md
diff --git a/src/doc/unstable-book/src/iter-rfind.md b/src/doc/unstable-book/src/library-features/iter-rfind.md
similarity index 100%
rename from src/doc/unstable-book/src/iter-rfind.md
rename to src/doc/unstable-book/src/library-features/iter-rfind.md
diff --git a/src/doc/unstable-book/src/libstd-io-internals.md b/src/doc/unstable-book/src/library-features/libstd-io-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/libstd-io-internals.md
rename to src/doc/unstable-book/src/library-features/libstd-io-internals.md
diff --git a/src/doc/unstable-book/src/libstd-sys-internals.md b/src/doc/unstable-book/src/library-features/libstd-sys-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/libstd-sys-internals.md
rename to src/doc/unstable-book/src/library-features/libstd-sys-internals.md
diff --git a/src/doc/unstable-book/src/libstd-thread-internals.md b/src/doc/unstable-book/src/library-features/libstd-thread-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/libstd-thread-internals.md
rename to src/doc/unstable-book/src/library-features/libstd-thread-internals.md
diff --git a/src/doc/unstable-book/src/linked-list-extras.md b/src/doc/unstable-book/src/library-features/linked-list-extras.md
similarity index 100%
rename from src/doc/unstable-book/src/linked-list-extras.md
rename to src/doc/unstable-book/src/library-features/linked-list-extras.md
diff --git a/src/doc/unstable-book/src/lookup-host.md b/src/doc/unstable-book/src/library-features/lookup-host.md
similarity index 100%
rename from src/doc/unstable-book/src/lookup-host.md
rename to src/doc/unstable-book/src/library-features/lookup-host.md
diff --git a/src/doc/unstable-book/src/manually-drop.md b/src/doc/unstable-book/src/library-features/manually-drop.md
similarity index 100%
rename from src/doc/unstable-book/src/manually-drop.md
rename to src/doc/unstable-book/src/library-features/manually-drop.md
diff --git a/src/doc/unstable-book/src/map-entry-recover-keys.md b/src/doc/unstable-book/src/library-features/map-entry-recover-keys.md
similarity index 100%
rename from src/doc/unstable-book/src/map-entry-recover-keys.md
rename to src/doc/unstable-book/src/library-features/map-entry-recover-keys.md
diff --git a/src/doc/unstable-book/src/mpsc-select.md b/src/doc/unstable-book/src/library-features/mpsc-select.md
similarity index 100%
rename from src/doc/unstable-book/src/mpsc-select.md
rename to src/doc/unstable-book/src/library-features/mpsc-select.md
diff --git a/src/doc/unstable-book/src/n16.md b/src/doc/unstable-book/src/library-features/n16.md
similarity index 100%
rename from src/doc/unstable-book/src/n16.md
rename to src/doc/unstable-book/src/library-features/n16.md
diff --git a/src/doc/unstable-book/src/never-type-impls.md b/src/doc/unstable-book/src/library-features/never-type-impls.md
similarity index 100%
rename from src/doc/unstable-book/src/never-type-impls.md
rename to src/doc/unstable-book/src/library-features/never-type-impls.md
diff --git a/src/doc/unstable-book/src/nonzero.md b/src/doc/unstable-book/src/library-features/nonzero.md
similarity index 100%
rename from src/doc/unstable-book/src/nonzero.md
rename to src/doc/unstable-book/src/library-features/nonzero.md
diff --git a/src/doc/unstable-book/src/offset-to.md b/src/doc/unstable-book/src/library-features/offset-to.md
similarity index 100%
rename from src/doc/unstable-book/src/offset-to.md
rename to src/doc/unstable-book/src/library-features/offset-to.md
diff --git a/src/doc/unstable-book/src/once-poison.md b/src/doc/unstable-book/src/library-features/once-poison.md
similarity index 100%
rename from src/doc/unstable-book/src/once-poison.md
rename to src/doc/unstable-book/src/library-features/once-poison.md
diff --git a/src/doc/unstable-book/src/oom.md b/src/doc/unstable-book/src/library-features/oom.md
similarity index 100%
rename from src/doc/unstable-book/src/oom.md
rename to src/doc/unstable-book/src/library-features/oom.md
diff --git a/src/doc/unstable-book/src/option-entry.md b/src/doc/unstable-book/src/library-features/option-entry.md
similarity index 100%
rename from src/doc/unstable-book/src/option-entry.md
rename to src/doc/unstable-book/src/library-features/option-entry.md
diff --git a/src/doc/unstable-book/src/osstring-shrink-to-fit.md b/src/doc/unstable-book/src/library-features/osstring-shrink-to-fit.md
similarity index 100%
rename from src/doc/unstable-book/src/osstring-shrink-to-fit.md
rename to src/doc/unstable-book/src/library-features/osstring-shrink-to-fit.md
diff --git a/src/doc/unstable-book/src/panic-abort.md b/src/doc/unstable-book/src/library-features/panic-abort.md
similarity index 100%
rename from src/doc/unstable-book/src/panic-abort.md
rename to src/doc/unstable-book/src/library-features/panic-abort.md
diff --git a/src/doc/unstable-book/src/panic-unwind.md b/src/doc/unstable-book/src/library-features/panic-unwind.md
similarity index 100%
rename from src/doc/unstable-book/src/panic-unwind.md
rename to src/doc/unstable-book/src/library-features/panic-unwind.md
diff --git a/src/doc/unstable-book/src/pattern.md b/src/doc/unstable-book/src/library-features/pattern.md
similarity index 100%
rename from src/doc/unstable-book/src/pattern.md
rename to src/doc/unstable-book/src/library-features/pattern.md
diff --git a/src/doc/unstable-book/src/peek.md b/src/doc/unstable-book/src/library-features/peek.md
similarity index 100%
rename from src/doc/unstable-book/src/peek.md
rename to src/doc/unstable-book/src/library-features/peek.md
diff --git a/src/doc/unstable-book/src/placement-in.md b/src/doc/unstable-book/src/library-features/placement-in.md
similarity index 100%
rename from src/doc/unstable-book/src/placement-in.md
rename to src/doc/unstable-book/src/library-features/placement-in.md
diff --git a/src/doc/unstable-book/src/placement-new-protocol.md b/src/doc/unstable-book/src/library-features/placement-new-protocol.md
similarity index 100%
rename from src/doc/unstable-book/src/placement-new-protocol.md
rename to src/doc/unstable-book/src/library-features/placement-new-protocol.md
diff --git a/src/doc/unstable-book/src/print.md b/src/doc/unstable-book/src/library-features/print.md
similarity index 100%
rename from src/doc/unstable-book/src/print.md
rename to src/doc/unstable-book/src/library-features/print.md
diff --git a/src/doc/unstable-book/src/proc-macro-internals.md b/src/doc/unstable-book/src/library-features/proc-macro-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/proc-macro-internals.md
rename to src/doc/unstable-book/src/library-features/proc-macro-internals.md
diff --git a/src/doc/unstable-book/src/process-try-wait.md b/src/doc/unstable-book/src/library-features/process-try-wait.md
similarity index 100%
rename from src/doc/unstable-book/src/process-try-wait.md
rename to src/doc/unstable-book/src/library-features/process-try-wait.md
diff --git a/src/doc/unstable-book/src/question-mark-carrier.md b/src/doc/unstable-book/src/library-features/question-mark-carrier.md
similarity index 100%
rename from src/doc/unstable-book/src/question-mark-carrier.md
rename to src/doc/unstable-book/src/library-features/question-mark-carrier.md
diff --git a/src/doc/unstable-book/src/rand.md b/src/doc/unstable-book/src/library-features/rand.md
similarity index 100%
rename from src/doc/unstable-book/src/rand.md
rename to src/doc/unstable-book/src/library-features/rand.md
diff --git a/src/doc/unstable-book/src/range-contains.md b/src/doc/unstable-book/src/library-features/range-contains.md
similarity index 100%
rename from src/doc/unstable-book/src/range-contains.md
rename to src/doc/unstable-book/src/library-features/range-contains.md
diff --git a/src/doc/unstable-book/src/raw.md b/src/doc/unstable-book/src/library-features/raw.md
similarity index 100%
rename from src/doc/unstable-book/src/raw.md
rename to src/doc/unstable-book/src/library-features/raw.md
diff --git a/src/doc/unstable-book/src/rc-would-unwrap.md b/src/doc/unstable-book/src/library-features/rc-would-unwrap.md
similarity index 100%
rename from src/doc/unstable-book/src/rc-would-unwrap.md
rename to src/doc/unstable-book/src/library-features/rc-would-unwrap.md
diff --git a/src/doc/unstable-book/src/retain-hash-collection.md b/src/doc/unstable-book/src/library-features/retain-hash-collection.md
similarity index 100%
rename from src/doc/unstable-book/src/retain-hash-collection.md
rename to src/doc/unstable-book/src/library-features/retain-hash-collection.md
diff --git a/src/doc/unstable-book/src/reverse-cmp-key.md b/src/doc/unstable-book/src/library-features/reverse-cmp-key.md
similarity index 100%
rename from src/doc/unstable-book/src/reverse-cmp-key.md
rename to src/doc/unstable-book/src/library-features/reverse-cmp-key.md
diff --git a/src/doc/unstable-book/src/rt.md b/src/doc/unstable-book/src/library-features/rt.md
similarity index 100%
rename from src/doc/unstable-book/src/rt.md
rename to src/doc/unstable-book/src/library-features/rt.md
diff --git a/src/doc/unstable-book/src/rustc-private.md b/src/doc/unstable-book/src/library-features/rustc-private.md
similarity index 100%
rename from src/doc/unstable-book/src/rustc-private.md
rename to src/doc/unstable-book/src/library-features/rustc-private.md
diff --git a/src/doc/unstable-book/src/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
similarity index 100%
rename from src/doc/unstable-book/src/sanitizer-runtime-lib.md
rename to src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md
diff --git a/src/doc/unstable-book/src/set-stdio.md b/src/doc/unstable-book/src/library-features/set-stdio.md
similarity index 100%
rename from src/doc/unstable-book/src/set-stdio.md
rename to src/doc/unstable-book/src/library-features/set-stdio.md
diff --git a/src/doc/unstable-book/src/shared.md b/src/doc/unstable-book/src/library-features/shared.md
similarity index 100%
rename from src/doc/unstable-book/src/shared.md
rename to src/doc/unstable-book/src/library-features/shared.md
diff --git a/src/doc/unstable-book/src/sip-hash-13.md b/src/doc/unstable-book/src/library-features/sip-hash-13.md
similarity index 100%
rename from src/doc/unstable-book/src/sip-hash-13.md
rename to src/doc/unstable-book/src/library-features/sip-hash-13.md
diff --git a/src/doc/unstable-book/src/slice-concat-ext.md b/src/doc/unstable-book/src/library-features/slice-concat-ext.md
similarity index 100%
rename from src/doc/unstable-book/src/slice-concat-ext.md
rename to src/doc/unstable-book/src/library-features/slice-concat-ext.md
diff --git a/src/doc/unstable-book/src/slice-get-slice.md b/src/doc/unstable-book/src/library-features/slice-get-slice.md
similarity index 100%
rename from src/doc/unstable-book/src/slice-get-slice.md
rename to src/doc/unstable-book/src/library-features/slice-get-slice.md
diff --git a/src/doc/unstable-book/src/slice-rsplit.md b/src/doc/unstable-book/src/library-features/slice-rsplit.md
similarity index 100%
rename from src/doc/unstable-book/src/slice-rsplit.md
rename to src/doc/unstable-book/src/library-features/slice-rsplit.md
diff --git a/src/doc/unstable-book/src/sort-internals.md b/src/doc/unstable-book/src/library-features/sort-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/sort-internals.md
rename to src/doc/unstable-book/src/library-features/sort-internals.md
diff --git a/src/doc/unstable-book/src/sort-unstable.md b/src/doc/unstable-book/src/library-features/sort-unstable.md
similarity index 100%
rename from src/doc/unstable-book/src/sort-unstable.md
rename to src/doc/unstable-book/src/library-features/sort-unstable.md
diff --git a/src/doc/unstable-book/src/step-by.md b/src/doc/unstable-book/src/library-features/step-by.md
similarity index 100%
rename from src/doc/unstable-book/src/step-by.md
rename to src/doc/unstable-book/src/library-features/step-by.md
diff --git a/src/doc/unstable-book/src/step-trait.md b/src/doc/unstable-book/src/library-features/step-trait.md
similarity index 100%
rename from src/doc/unstable-book/src/step-trait.md
rename to src/doc/unstable-book/src/library-features/step-trait.md
diff --git a/src/doc/unstable-book/src/str-checked-slicing.md b/src/doc/unstable-book/src/library-features/str-checked-slicing.md
similarity index 100%
rename from src/doc/unstable-book/src/str-checked-slicing.md
rename to src/doc/unstable-book/src/library-features/str-checked-slicing.md
diff --git a/src/doc/unstable-book/src/str-escape.md b/src/doc/unstable-book/src/library-features/str-escape.md
similarity index 100%
rename from src/doc/unstable-book/src/str-escape.md
rename to src/doc/unstable-book/src/library-features/str-escape.md
diff --git a/src/doc/unstable-book/src/str-internals.md b/src/doc/unstable-book/src/library-features/str-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/str-internals.md
rename to src/doc/unstable-book/src/library-features/str-internals.md
diff --git a/src/doc/unstable-book/src/str-mut-extras.md b/src/doc/unstable-book/src/library-features/str-mut-extras.md
similarity index 100%
rename from src/doc/unstable-book/src/str-mut-extras.md
rename to src/doc/unstable-book/src/library-features/str-mut-extras.md
diff --git a/src/doc/unstable-book/src/test.md b/src/doc/unstable-book/src/library-features/test.md
similarity index 100%
rename from src/doc/unstable-book/src/test.md
rename to src/doc/unstable-book/src/library-features/test.md
diff --git a/src/doc/unstable-book/src/thread-id.md b/src/doc/unstable-book/src/library-features/thread-id.md
similarity index 100%
rename from src/doc/unstable-book/src/thread-id.md
rename to src/doc/unstable-book/src/library-features/thread-id.md
diff --git a/src/doc/unstable-book/src/thread-local-internals.md b/src/doc/unstable-book/src/library-features/thread-local-internals.md
similarity index 100%
rename from src/doc/unstable-book/src/thread-local-internals.md
rename to src/doc/unstable-book/src/library-features/thread-local-internals.md
diff --git a/src/doc/unstable-book/src/thread-local-state.md b/src/doc/unstable-book/src/library-features/thread-local-state.md
similarity index 100%
rename from src/doc/unstable-book/src/thread-local-state.md
rename to src/doc/unstable-book/src/library-features/thread-local-state.md
diff --git a/src/doc/unstable-book/src/toowned-clone-into.md b/src/doc/unstable-book/src/library-features/toowned-clone-into.md
similarity index 100%
rename from src/doc/unstable-book/src/toowned-clone-into.md
rename to src/doc/unstable-book/src/library-features/toowned-clone-into.md
diff --git a/src/doc/unstable-book/src/trusted-len.md b/src/doc/unstable-book/src/library-features/trusted-len.md
similarity index 100%
rename from src/doc/unstable-book/src/trusted-len.md
rename to src/doc/unstable-book/src/library-features/trusted-len.md
diff --git a/src/doc/unstable-book/src/try-from.md b/src/doc/unstable-book/src/library-features/try-from.md
similarity index 100%
rename from src/doc/unstable-book/src/try-from.md
rename to src/doc/unstable-book/src/library-features/try-from.md
diff --git a/src/doc/unstable-book/src/unicode.md b/src/doc/unstable-book/src/library-features/unicode.md
similarity index 100%
rename from src/doc/unstable-book/src/unicode.md
rename to src/doc/unstable-book/src/library-features/unicode.md
diff --git a/src/doc/unstable-book/src/unique.md b/src/doc/unstable-book/src/library-features/unique.md
similarity index 100%
rename from src/doc/unstable-book/src/unique.md
rename to src/doc/unstable-book/src/library-features/unique.md
diff --git a/src/doc/unstable-book/src/unsize.md b/src/doc/unstable-book/src/library-features/unsize.md
similarity index 100%
rename from src/doc/unstable-book/src/unsize.md
rename to src/doc/unstable-book/src/library-features/unsize.md
diff --git a/src/doc/unstable-book/src/update-panic-count.md b/src/doc/unstable-book/src/library-features/update-panic-count.md
similarity index 100%
rename from src/doc/unstable-book/src/update-panic-count.md
rename to src/doc/unstable-book/src/library-features/update-panic-count.md
diff --git a/src/doc/unstable-book/src/utf8-error-error-len.md b/src/doc/unstable-book/src/library-features/utf8-error-error-len.md
similarity index 100%
rename from src/doc/unstable-book/src/utf8-error-error-len.md
rename to src/doc/unstable-book/src/library-features/utf8-error-error-len.md
diff --git a/src/doc/unstable-book/src/vec-remove-item.md b/src/doc/unstable-book/src/library-features/vec-remove-item.md
similarity index 100%
rename from src/doc/unstable-book/src/vec-remove-item.md
rename to src/doc/unstable-book/src/library-features/vec-remove-item.md
diff --git a/src/doc/unstable-book/src/windows-c.md b/src/doc/unstable-book/src/library-features/windows-c.md
similarity index 100%
rename from src/doc/unstable-book/src/windows-c.md
rename to src/doc/unstable-book/src/library-features/windows-c.md
diff --git a/src/doc/unstable-book/src/windows-handle.md b/src/doc/unstable-book/src/library-features/windows-handle.md
similarity index 100%
rename from src/doc/unstable-book/src/windows-handle.md
rename to src/doc/unstable-book/src/library-features/windows-handle.md
diff --git a/src/doc/unstable-book/src/windows-net.md b/src/doc/unstable-book/src/library-features/windows-net.md
similarity index 100%
rename from src/doc/unstable-book/src/windows-net.md
rename to src/doc/unstable-book/src/library-features/windows-net.md
diff --git a/src/doc/unstable-book/src/windows-stdio.md b/src/doc/unstable-book/src/library-features/windows-stdio.md
similarity index 100%
rename from src/doc/unstable-book/src/windows-stdio.md
rename to src/doc/unstable-book/src/library-features/windows-stdio.md
diff --git a/src/doc/unstable-book/src/zero-one.md b/src/doc/unstable-book/src/library-features/zero-one.md
similarity index 100%
rename from src/doc/unstable-book/src/zero-one.md
rename to src/doc/unstable-book/src/library-features/zero-one.md
diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md
index dfbfe4cab9738..604b449f16379 100644
--- a/src/doc/unstable-book/src/the-unstable-book.md
+++ b/src/doc/unstable-book/src/the-unstable-book.md
@@ -14,7 +14,7 @@ fn main() {
 
 The `box_syntax` feature [has a chapter][box] describing how to use it.
 
-[box]: box-syntax.html
+[box]: language-features/box-syntax.html
 
 Because this documentation relates to unstable features, we make no guarantees
 that what is contained here is accurate or up to date. It's developed on a
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 8a391f9cde3a3..618561f3b0257 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1812,6 +1812,8 @@ makes a difference in practice.)
 
 register_diagnostics! {
 //  E0006 // merged with E0005
+//  E0101, // replaced with E0282
+//  E0102, // replaced with E0282
 //  E0134,
 //  E0135,
     E0278, // requirement is not satisfied
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index e98792b120de2..a1bafe113e415 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -199,10 +199,8 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // `tained_by_errors`) to avoid reporting certain kinds of errors.
     err_count_on_creation: usize,
 
-    // This flag is used for debugging, and is set to true if there are
-    // any obligations set during the current snapshot. In that case, the
-    // snapshot can't be rolled back.
-    pub obligations_in_snapshot: Cell<bool>,
+    // This flag is true while there is an active snapshot.
+    in_snapshot: Cell<bool>,
 }
 
 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -507,7 +505,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
             projection_mode: Reveal::UserFacing,
             tainted_by_errors_flag: Cell::new(false),
             err_count_on_creation: self.sess.err_count(),
-            obligations_in_snapshot: Cell::new(false),
+            in_snapshot: Cell::new(false),
         }
     }
 }
@@ -545,7 +543,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
             projection_mode: projection_mode,
             tainted_by_errors_flag: Cell::new(false),
             err_count_on_creation: tcx.sess.err_count(),
-            obligations_in_snapshot: Cell::new(false),
+            in_snapshot: Cell::new(false),
         }))
     }
 }
@@ -573,7 +571,7 @@ pub struct CombinedSnapshot {
     int_snapshot: unify::Snapshot<ty::IntVid>,
     float_snapshot: unify::Snapshot<ty::FloatVid>,
     region_vars_snapshot: RegionSnapshot,
-    obligations_in_snapshot: bool,
+    was_in_snapshot: bool,
 }
 
 /// Helper trait for shortening the lifetimes inside a
@@ -734,6 +732,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.projection_mode
     }
 
+    pub fn is_in_snapshot(&self) -> bool {
+        self.in_snapshot.get()
+    }
+
     pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
         t.fold_with(&mut self.freshener())
     }
@@ -861,38 +863,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         result.map(move |t| InferOk { value: t, obligations: fields.obligations })
     }
 
-    // Clear the "obligations in snapshot" flag, invoke the closure,
+    // Clear the "currently in a snapshot" flag, invoke the closure,
     // then restore the flag to its original value. This flag is a
     // debugging measure designed to detect cases where we start a
-    // snapshot, create type variables, register obligations involving
-    // those type variables in the fulfillment cx, and then have to
-    // unroll the snapshot, leaving "dangling type variables" behind.
-    // In such cases, the flag will be set by the fulfillment cx, and
-    // an assertion will fail when rolling the snapshot back.  Very
-    // useful, much better than grovelling through megabytes of
-    // RUST_LOG output.
+    // snapshot, create type variables, and register obligations
+    // which may involve those type variables in the fulfillment cx,
+    // potentially leaving "dangling type variables" behind.
+    // In such cases, an assertion will fail when attempting to
+    // register obligations, within a snapshot. Very useful, much
+    // better than grovelling through megabytes of RUST_LOG output.
     //
-    // HOWEVER, in some cases the flag is wrong. In particular, we
+    // HOWEVER, in some cases the flag is unhelpful. In particular, we
     // sometimes create a "mini-fulfilment-cx" in which we enroll
     // obligations. As long as this fulfillment cx is fully drained
     // before we return, this is not a problem, as there won't be any
     // escaping obligations in the main cx. In those cases, you can
     // use this function.
-    pub fn save_and_restore_obligations_in_snapshot_flag<F, R>(&self, func: F) -> R
+    pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
         where F: FnOnce(&Self) -> R
     {
-        let flag = self.obligations_in_snapshot.get();
-        self.obligations_in_snapshot.set(false);
+        let flag = self.in_snapshot.get();
+        self.in_snapshot.set(false);
         let result = func(self);
-        self.obligations_in_snapshot.set(flag);
+        self.in_snapshot.set(flag);
         result
     }
 
     fn start_snapshot(&self) -> CombinedSnapshot {
         debug!("start_snapshot()");
 
-        let obligations_in_snapshot = self.obligations_in_snapshot.get();
-        self.obligations_in_snapshot.set(false);
+        let in_snapshot = self.in_snapshot.get();
+        self.in_snapshot.set(true);
 
         CombinedSnapshot {
             projection_cache_snapshot: self.projection_cache.borrow_mut().snapshot(),
@@ -900,7 +901,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             int_snapshot: self.int_unification_table.borrow_mut().snapshot(),
             float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
             region_vars_snapshot: self.region_vars.start_snapshot(),
-            obligations_in_snapshot: obligations_in_snapshot,
+            was_in_snapshot: in_snapshot,
         }
     }
 
@@ -911,10 +912,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                int_snapshot,
                                float_snapshot,
                                region_vars_snapshot,
-                               obligations_in_snapshot } = snapshot;
+                               was_in_snapshot } = snapshot;
 
-        assert!(!self.obligations_in_snapshot.get());
-        self.obligations_in_snapshot.set(obligations_in_snapshot);
+        self.in_snapshot.set(was_in_snapshot);
 
         self.projection_cache
             .borrow_mut()
@@ -939,9 +939,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                int_snapshot,
                                float_snapshot,
                                region_vars_snapshot,
-                               obligations_in_snapshot } = snapshot;
+                               was_in_snapshot } = snapshot;
 
-        self.obligations_in_snapshot.set(obligations_in_snapshot);
+        self.in_snapshot.set(was_in_snapshot);
 
         self.projection_cache
             .borrow_mut()
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index f7a7d0e2071f2..71dff3b2bb94d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -25,7 +25,7 @@ use super::{
 
 use errors::DiagnosticBuilder;
 use fmt_macros::{Parser, Piece, Position};
-use hir::{intravisit, Local, Pat};
+use hir::{self, intravisit, Local, Pat, Body};
 use hir::intravisit::{Visitor, NestedVisitorMap};
 use hir::map::NodeExpr;
 use hir::def_id::DefId;
@@ -33,8 +33,8 @@ use infer::{self, InferCtxt};
 use infer::type_variable::TypeVariableOrigin;
 use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
 use std::fmt;
-use syntax::ast;
-use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use syntax::ast::{self, NodeId};
+use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar};
 use ty::error::ExpectedFound;
 use ty::fast_reject;
 use ty::fold::TypeFolder;
@@ -66,37 +66,52 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
 struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     target_ty: &'a Ty<'tcx>,
-    found_pattern: Option<&'a Pat>,
+    hir_map: &'a hir::map::Map<'gcx>,
+    found_local_pattern: Option<&'gcx Pat>,
+    found_arg_pattern: Option<&'gcx Pat>,
 }
 
 impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
-    fn is_match(&self, ty: Ty<'tcx>) -> bool {
-        ty == *self.target_ty || match (&ty.sty, &self.target_ty.sty) {
-            (&ty::TyInfer(ty::TyVar(a_vid)), &ty::TyInfer(ty::TyVar(b_vid))) =>
-                self.infcx.type_variables
-                          .borrow_mut()
-                          .sub_unified(a_vid, b_vid),
-
+    fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool {
+        match self.infcx.tables.borrow().node_types.get(node_id) {
+            Some(&ty) => {
+                let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+                ty.walk().any(|inner_ty| {
+                    inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
+                        (&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => {
+                            self.infcx
+                                .type_variables
+                                .borrow_mut()
+                                .sub_unified(a_vid, b_vid)
+                        }
+                        _ => false,
+                    }
+                })
+            }
             _ => false,
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
-        NestedVisitorMap::None
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
+        NestedVisitorMap::OnlyBodies(&self.hir_map)
     }
 
-    fn visit_local(&mut self, local: &'a Local) {
-        if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
-            let ty = self.infcx.resolve_type_vars_if_possible(&ty);
-            let is_match = ty.walk().any(|t| self.is_match(t));
+    fn visit_local(&mut self, local: &'gcx Local) {
+        if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) {
+            self.found_local_pattern = Some(&*local.pat);
+        }
+        intravisit::walk_local(self, local);
+    }
 
-            if is_match && self.found_pattern.is_none() {
-                self.found_pattern = Some(&*local.pat);
+    fn visit_body(&mut self, body: &'gcx Body) {
+        for argument in &body.arguments {
+            if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) {
+                self.found_arg_pattern = Some(&*argument.pat);
             }
         }
-        intravisit::walk_local(self, local);
+        intravisit::walk_body(self, body);
     }
 }
 
@@ -721,6 +736,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // coherence violation, so we don't report it here.
 
         let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
+        let body_id = hir::BodyId { node_id: obligation.cause.body_id };
+        let span = obligation.cause.span;
 
         debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
                predicate,
@@ -768,10 +785,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                         self.tcx.lang_items.sized_trait()
                         .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                     {
-                        self.need_type_info(obligation, self_ty);
+                        self.need_type_info(body_id, span, self_ty);
                     } else {
                         let mut err = struct_span_err!(self.tcx.sess,
-                                                        obligation.cause.span, E0283,
+                                                        span, E0283,
                                                         "type annotations required: \
                                                         cannot resolve `{}`",
                                                         predicate);
@@ -785,7 +802,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
                 if !ty.references_error() && !self.tcx.sess.has_errors() {
-                    self.need_type_info(obligation, ty);
+                    self.need_type_info(body_id, span, ty);
                 }
             }
 
@@ -796,7 +813,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
                     // both must be type variables, or the other would've been instantiated
                     assert!(a.is_ty_var() && b.is_ty_var());
-                    self.need_type_info(obligation, a);
+                    self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
+                                        obligation.cause.span,
+                                        a);
                 }
             }
 
@@ -874,42 +893,66 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) {
+    pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
         let ty = self.resolve_type_vars_if_possible(&ty);
         let name = self.extract_type_name(&ty);
-        let ref cause = obligation.cause;
 
-        let mut err = struct_span_err!(self.tcx.sess,
-                                       cause.span,
-                                       E0282,
-                                       "type annotations needed");
-
-        err.span_label(cause.span, &format!("cannot infer type for `{}`", name));
+        let mut err_span = span;
+        let mut labels = vec![(span, format!("cannot infer type for `{}`", name))];
 
         let mut local_visitor = FindLocalByTypeVisitor {
             infcx: &self,
             target_ty: &ty,
-            found_pattern: None,
+            hir_map: &self.tcx.hir,
+            found_local_pattern: None,
+            found_arg_pattern: None,
         };
 
         // #40294: cause.body_id can also be a fn declaration.
         // Currently, if it's anything other than NodeExpr, we just ignore it
-        match self.tcx.hir.find(cause.body_id) {
+        match self.tcx.hir.find(body_id.node_id) {
             Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
             _ => ()
         }
 
-        if let Some(pattern) = local_visitor.found_pattern {
-            let pattern_span = pattern.span;
+        if let Some(pattern) = local_visitor.found_arg_pattern {
+            err_span = pattern.span;
+            // We don't want to show the default label for closures.
+            //
+            // So, before clearing, the output would look something like this:
+            // ```
+            // let x = |_| {  };
+            //          -  ^^^^ cannot infer type for `[_; 0]`
+            //          |
+            //          consider giving this closure parameter a type
+            // ```
+            //
+            // After clearing, it looks something like this:
+            // ```
+            // let x = |_| {  };
+            //          ^ consider giving this closure parameter a type
+            // ```
+            labels.clear();
+            labels.push((pattern.span, format!("consider giving this closure parameter a type")));
+        }
+
+        if let Some(pattern) = local_visitor.found_local_pattern {
             if let Some(simple_name) = pattern.simple_name() {
-                err.span_label(pattern_span,
-                               &format!("consider giving `{}` a type",
-                                        simple_name));
+                labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
             } else {
-                err.span_label(pattern_span, &format!("consider giving a type to pattern"));
+                labels.push((pattern.span, format!("consider giving the pattern a type")));
             }
         }
 
+        let mut err = struct_span_err!(self.tcx.sess,
+                                       err_span,
+                                       E0282,
+                                       "type annotations needed");
+
+        for (target_span, label_message) in labels {
+            err.span_label(target_span, &label_message);
+        }
+
         err.emit();
     }
 
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 64453f2983b92..d771be077ae3a 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
 
         debug!("register_predicate_obligation(obligation={:?})", obligation);
 
-        infcx.obligations_in_snapshot.set(true);
+        assert!(!infcx.is_in_snapshot());
 
         if infcx.tcx.fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) {
             debug!("register_predicate_obligation: duplicate");
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 50a4d982832ac..92b7c736d42fd 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -242,7 +242,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     // attempt to prove all of the predicates for impl2 given those for impl1
     // (which are packed up in penv)
 
-    infcx.save_and_restore_obligations_in_snapshot_flag(|infcx| {
+    infcx.save_and_restore_in_snapshot_flag(|infcx| {
         let mut fulfill_cx = FulfillmentContext::new();
         for oblig in obligations.into_iter() {
             fulfill_cx.register_predicate_obligation(&infcx, oblig);
diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs
index 2daebf5cf3d6b..2cfab7df8b30b 100644
--- a/src/librustc_trans/cabi_x86_64.rs
+++ b/src/librustc_trans/cabi_x86_64.rs
@@ -229,12 +229,12 @@ pub fn compute_abi_info<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fty: &mut FnType
         };
 
         if in_mem {
-            // `sret` / `byval` parameter thus one less integer register available
-            int_regs -= 1;
-
             arg.make_indirect(ccx);
             if is_arg {
                 arg.attrs.set(ArgAttribute::ByVal);
+            } else {
+                // `sret` parameter thus one less integer register available
+                int_regs -= 1;
             }
         } else {
             // split into sized chunks passed individually
diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs
deleted file mode 100644
index 9610477d8fd91..0000000000000
--- a/src/librustc_typeck/check/assoc.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::infer::InferCtxt;
-use rustc::traits::{self, FulfillmentContext, Normalized, MiscObligation, SelectionContext,
-                    ObligationCause};
-use rustc::ty::fold::TypeFoldable;
-use syntax::ast;
-use syntax_pos::Span;
-
-// FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
-pub fn normalize_associated_types_in<'a, 'gcx, 'tcx, T>(
-    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    fulfillment_cx: &mut FulfillmentContext<'tcx>,
-    span: Span,
-    body_id: ast::NodeId,
-    value: &T) -> T
-
-    where T : TypeFoldable<'tcx>
-{
-    debug!("normalize_associated_types_in(value={:?})", value);
-    let mut selcx = SelectionContext::new(infcx);
-    let cause = ObligationCause::new(span, body_id, MiscObligation);
-    let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value);
-    debug!("normalize_associated_types_in: result={:?} predicates={:?}",
-           result,
-           obligations);
-    for obligation in obligations {
-        fulfillment_cx.register_predicate_obligation(infcx, obligation);
-    }
-    result
-}
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 647adbbb82f2d..92fb02c6379dc 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -149,22 +149,25 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
         self.fcx.resolve_type_vars_if_possible(&self.cur_ty)
     }
 
-    pub fn finalize<E>(self, pref: LvaluePreference, exprs: &[E])
-        where E: AsCoercionSite
-    {
+    pub fn finalize(self, pref: LvaluePreference, expr: &hir::Expr) {
         let fcx = self.fcx;
-        fcx.register_infer_ok_obligations(self.finalize_as_infer_ok(pref, exprs));
+        fcx.register_infer_ok_obligations(self.finalize_as_infer_ok(pref, &[expr]));
     }
 
     pub fn finalize_as_infer_ok<E>(self, pref: LvaluePreference, exprs: &[E])
                                    -> InferOk<'tcx, ()>
         where E: AsCoercionSite
     {
-        let methods: Vec<_> = self.steps
+        let Autoderef { fcx, span, mut obligations, steps, .. } = self;
+        let methods: Vec<_> = steps
             .iter()
             .map(|&(ty, kind)| {
                 if let AutoderefKind::Overloaded = kind {
-                    self.fcx.try_overloaded_deref(self.span, None, ty, pref)
+                    fcx.try_overloaded_deref(span, None, ty, pref)
+                        .map(|InferOk { value, obligations: o }| {
+                            obligations.extend(o);
+                            value
+                        })
                 } else {
                     None
                 }
@@ -174,7 +177,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
         debug!("finalize({:?}) - {:?},{:?}",
                pref,
                methods,
-               self.obligations);
+               obligations);
 
         for expr in exprs {
             let expr = expr.as_coercion_site();
@@ -182,14 +185,14 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
             for (n, method) in methods.iter().enumerate() {
                 if let &Some(method) = method {
                     let method_call = MethodCall::autoderef(expr.id, n as u32);
-                    self.fcx.tables.borrow_mut().method_map.insert(method_call, method);
+                    fcx.tables.borrow_mut().method_map.insert(method_call, method);
                 }
             }
         }
 
         InferOk {
             value: (),
-            obligations: self.obligations
+            obligations
         }
     }
 }
@@ -211,7 +214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 base_expr: Option<&hir::Expr>,
                                 base_ty: Ty<'tcx>,
                                 lvalue_pref: LvaluePreference)
-                                -> Option<MethodCallee<'tcx>> {
+                                -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("try_overloaded_deref({:?},{:?},{:?},{:?})",
                span,
                base_expr,
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 9c5870c12aad4..32f130aca1cb9 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             })
             .next();
         let callee_ty = autoderef.unambiguous_final_ty();
-        autoderef.finalize(LvaluePreference::NoPreference, &[callee_expr]);
+        autoderef.finalize(LvaluePreference::NoPreference, callee_expr);
 
         let output = match result {
             None => {
@@ -173,7 +173,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                        adjusted_ty,
                                                        None) {
                 None => continue,
-                Some(method_callee) => {
+                Some(ok) => {
+                    let method_callee = self.register_infer_ok_obligations(ok);
                     return Some(method_callee);
                 }
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 2e9057800a54a..c6a1f6cfc0d7f 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -711,16 +711,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
         let coerce = Coerce::new(self, cause);
-        self.commit_if_ok(|_| {
-            let ok = coerce.coerce(&[expr], source, target)?;
-            let adjustment = self.register_infer_ok_obligations(ok);
-            self.apply_adjustment(expr.id, adjustment);
-
-            // We should now have added sufficient adjustments etc to
-            // ensure that the type of expression, post-adjustment, is
-            // a subtype of target.
-            Ok(target)
-        })
+        let ok = self.commit_if_ok(|_| coerce.coerce(&[expr], source, target))?;
+
+        let adjustment = self.register_infer_ok_obligations(ok);
+        self.apply_adjustment(expr.id, adjustment);
+
+        // We should now have added sufficient adjustments etc to
+        // ensure that the type of expression, post-adjustment, is
+        // a subtype of target.
+        Ok(target)
     }
 
     /// Given some expressions, their known unified type and another expression,
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 905d8688ea194..8a6853461a5e8 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -20,7 +20,6 @@ use rustc::util::common::ErrorReported;
 use syntax::ast;
 use syntax_pos::Span;
 
-use super::assoc;
 use super::{Inherited, FnCtxt};
 use astconv::ExplicitSelf;
 
@@ -227,7 +226,6 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
         let inh = Inherited::new(infcx);
         let infcx = &inh.infcx;
-        let fulfillment_cx = &inh.fulfillment_cx;
 
         debug!("compare_impl_method: caller_bounds={:?}",
                infcx.parameter_environment.caller_bounds);
@@ -239,12 +237,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                        infer::HigherRankedType,
                                                        &ty::Binder(impl_m_own_bounds.predicates));
         for predicate in impl_m_own_bounds {
-            let traits::Normalized { value: predicate, .. } =
+            let traits::Normalized { value: predicate, obligations } =
                 traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
 
-            fulfillment_cx.borrow_mut().register_predicate_obligation(
-                &infcx,
-                traits::Obligation::new(cause.clone(), predicate));
+            inh.register_predicates(obligations);
+            inh.register_predicate(traits::Obligation::new(cause.clone(), predicate));
         }
 
         // We now need to check that the signature of the impl method is
@@ -277,11 +274,9 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let impl_sig =
             impl_sig.subst(tcx, impl_to_skol_substs);
         let impl_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &mut fulfillment_cx.borrow_mut(),
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &impl_sig);
+            inh.normalize_associated_types_in(impl_m_span,
+                                              impl_m_body_id,
+                                              &impl_sig);
         let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
@@ -291,11 +286,9 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let trait_sig =
             trait_sig.subst(tcx, trait_to_skol_substs);
         let trait_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &mut fulfillment_cx.borrow_mut(),
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &trait_sig);
+            inh.normalize_associated_types_in(impl_m_span,
+                                              impl_m_body_id,
+                                              &trait_sig);
         let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
@@ -344,7 +337,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
+        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
             infcx.report_fulfillment_errors(errors);
             return Err(ErrorReported);
         }
@@ -731,7 +724,8 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
 
     tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
-        let mut fulfillment_cx = traits::FulfillmentContext::new();
+        let inh = Inherited::new(infcx);
+        let infcx = &inh.infcx;
 
         // The below is for the most part highly similar to the procedure
         // for methods above. It is simpler in many respects, especially
@@ -761,31 +755,21 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let trait_ty = tcx.item_type(trait_c.def_id).subst(tcx, trait_to_skol_substs);
         let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
 
-        let err = infcx.commit_if_ok(|_| {
-            // There is no "body" here, so just pass dummy id.
-            let impl_ty = assoc::normalize_associated_types_in(&infcx,
-                                                               &mut fulfillment_cx,
-                                                               impl_c_span,
-                                                               ast::CRATE_NODE_ID,
-                                                               &impl_ty);
+        // There is no "body" here, so just pass dummy id.
+        let impl_ty = inh.normalize_associated_types_in(impl_c_span,
+                                                        impl_c_node_id,
+                                                        &impl_ty);
 
-            debug!("compare_const_impl: impl_ty={:?}", impl_ty);
+        debug!("compare_const_impl: impl_ty={:?}", impl_ty);
 
-            let trait_ty = assoc::normalize_associated_types_in(&infcx,
-                                                                &mut fulfillment_cx,
-                                                                impl_c_span,
-                                                                ast::CRATE_NODE_ID,
-                                                                &trait_ty);
+        let trait_ty = inh.normalize_associated_types_in(impl_c_span,
+                                                         impl_c_node_id,
+                                                         &trait_ty);
 
-            debug!("compare_const_impl: trait_ty={:?}", trait_ty);
+        debug!("compare_const_impl: trait_ty={:?}", trait_ty);
 
-            infcx.sub_types(false, &cause, impl_ty, trait_ty)
-                 .map(|InferOk { obligations, value: () }| {
-                     for obligation in obligations {
-                         fulfillment_cx.register_predicate_obligation(&infcx, obligation);
-                     }
-                 })
-        });
+        let err = infcx.sub_types(false, &cause, impl_ty, trait_ty)
+            .map(|ok| inh.register_infer_ok_obligations(ok));
 
         if let Err(terr) = err {
             debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
@@ -822,5 +806,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 &terr);
             diag.emit();
         }
+
+        // FIXME(#41323) Check the obligations in the fulfillment context.
     });
 }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 28ac335cf195a..26ba965fe5cc6 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -137,7 +137,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         assert_eq!(n, pick.autoderefs);
 
         autoderef.unambiguous_final_ty();
-        autoderef.finalize(LvaluePreference::NoPreference, &[self.self_expr]);
+        autoderef.finalize(LvaluePreference::NoPreference, self.self_expr);
 
         let target = pick.unsize.unwrap_or(autoderefd_ty);
         let target = target.adjust_for_autoref(self.tcx, autoref);
@@ -445,7 +445,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                                       "expr was deref-able {} times but now isn't?",
                                       autoderefs);
                         });
-                        autoderef.finalize(PreferMutLvalue, &[expr]);
+                        autoderef.finalize(PreferMutLvalue, expr);
                     }
                 }
                 Some(_) | None => {}
@@ -543,7 +543,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                                                                Some(&base_expr),
                                                                self.node_ty(base_expr.id),
                                                                PreferMutLvalue);
-                        let method = method.expect("re-trying deref failed");
+                        let ok = method.expect("re-trying deref failed");
+                        let method = self.register_infer_ok_obligations(ok);
                         self.tables.borrow_mut().method_map.insert(method_call, method);
                     }
                 }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 9ecf0ffa71ebd..7dd2699a6eaf0 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -17,7 +17,8 @@ use rustc::ty::subst::Substs;
 use rustc::traits;
 use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
-use rustc::infer;
+use rustc::ty::subst::Subst;
+use rustc::infer::{self, InferOk};
 
 use syntax::ast;
 use syntax_pos::Span;
@@ -159,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                   trait_def_id: DefId,
                                   self_ty: ty::Ty<'tcx>,
                                   opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
-                                  -> Option<ty::MethodCallee<'tcx>> {
+                                  -> Option<InferOk<'tcx, ty::MethodCallee<'tcx>>> {
         self.lookup_method_in_trait_adjusted(span,
                                              self_expr,
                                              m_name,
@@ -190,7 +191,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                            unsize: bool,
                                            self_ty: ty::Ty<'tcx>,
                                            opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
-                                           -> Option<ty::MethodCallee<'tcx>> {
+                                           -> Option<InferOk<'tcx, ty::MethodCallee<'tcx>>> {
         debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, \
                 m_name={}, trait_def_id={:?})",
                self_ty,
@@ -236,6 +237,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         assert_eq!(generics.regions.len(), 0);
 
         debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
+        let mut obligations = vec![];
 
         // Instantiate late-bound regions and substitute the trait
         // parameters into the method type to get the actual method type.
@@ -248,10 +250,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
                                                                     infer::FnCall,
                                                                     &fn_sig).0;
-        let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
+        let fn_sig = fn_sig.subst(self.tcx, substs);
+        let fn_sig = match self.normalize_associated_types_in_as_infer_ok(span, &fn_sig) {
+            InferOk { value, obligations: o } => {
+                obligations.extend(o);
+                value
+            }
+        };
         let transformed_self_ty = fn_sig.inputs()[0];
-        let method_ty = tcx.mk_fn_def(def_id, trait_ref.substs,
-                                     ty::Binder(fn_sig));
+        let method_ty = tcx.mk_fn_def(def_id, substs, ty::Binder(fn_sig));
 
         debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
                method_ty,
@@ -265,18 +272,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //
         // Note that as the method comes from a trait, it should not have
         // any late-bound regions appearing in its bounds.
-        let method_bounds = self.instantiate_bounds(span, def_id, trait_ref.substs);
-        assert!(!method_bounds.has_escaping_regions());
-        self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id),
-                                            &method_bounds);
+        let bounds = self.tcx.item_predicates(def_id).instantiate(self.tcx, substs);
+        let bounds = match self.normalize_associated_types_in_as_infer_ok(span, &bounds) {
+            InferOk { value, obligations: o } => {
+                obligations.extend(o);
+                value
+            }
+        };
+        assert!(!bounds.has_escaping_regions());
 
-        // Also register an obligation for the method type being well-formed.
-        self.register_wf_obligation(method_ty, span, traits::MiscObligation);
+        let cause = traits::ObligationCause::misc(span, self.body_id);
+        obligations.extend(traits::predicates_for_generics(cause.clone(), &bounds));
 
-        // FIXME(#18653) -- Try to resolve obligations, giving us more
-        // typing information, which can sometimes be needed to avoid
-        // pathological region inference failures.
-        self.select_obligations_where_possible();
+        // Also add an obligation for the method type being well-formed.
+        obligations.push(traits::Obligation::new(cause, ty::Predicate::WellFormed(method_ty)));
 
         // Insert any adjustments needed (always an autoref of some mutability).
         if let Some(self_expr) = self_expr {
@@ -317,7 +326,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         debug!("callee = {:?}", callee);
 
-        Some(callee)
+        Some(InferOk {
+            obligations,
+            value: callee
+        })
     }
 
     pub fn resolve_ufcs(&self,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 32aeeeb110556..902cfb889f8c2 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -128,7 +128,6 @@ use rustc_back::slice;
 use rustc::middle::const_val::eval_length;
 use rustc_const_math::ConstInt;
 
-mod assoc;
 mod autoderef;
 pub mod dropck;
 pub mod _match;
@@ -536,7 +535,7 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
-    pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
+    fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
         Inherited {
             infcx: infcx,
             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
@@ -547,20 +546,55 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
         }
     }
 
+    fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
+        debug!("register_predicate({:?})", obligation);
+        if obligation.has_escaping_regions() {
+            span_bug!(obligation.cause.span, "escaping regions in predicate {:?}",
+                      obligation);
+        }
+        self.fulfillment_cx
+            .borrow_mut()
+            .register_predicate_obligation(self, obligation);
+    }
+
+    fn register_predicates(&self, obligations: Vec<traits::PredicateObligation<'tcx>>) {
+        for obligation in obligations {
+            self.register_predicate(obligation);
+        }
+    }
+
+    fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T {
+        self.register_predicates(infer_ok.obligations);
+        infer_ok.value
+    }
+
     fn normalize_associated_types_in<T>(&self,
                                         span: Span,
                                         body_id: ast::NodeId,
-                                        value: &T)
-                                        -> T
+                                        value: &T) -> T
         where T : TypeFoldable<'tcx>
     {
-        assoc::normalize_associated_types_in(self,
-                                             &mut self.fulfillment_cx.borrow_mut(),
-                                             span,
-                                             body_id,
-                                             value)
+        let ok = self.normalize_associated_types_in_as_infer_ok(span, body_id, value);
+        self.register_infer_ok_obligations(ok)
     }
 
+    fn normalize_associated_types_in_as_infer_ok<T>(&self,
+                                                    span: Span,
+                                                    body_id: ast::NodeId,
+                                                    value: &T)
+                                                    -> InferOk<'tcx, T>
+        where T : TypeFoldable<'tcx>
+    {
+        debug!("normalize_associated_types_in(value={:?})", value);
+        let mut selcx = traits::SelectionContext::new(self);
+        let cause = ObligationCause::misc(span, body_id);
+        let traits::Normalized { value, obligations } =
+            traits::normalize(&mut selcx, cause, value);
+        debug!("normalize_associated_types_in: result={:?} predicates={:?}",
+            value,
+            obligations);
+        InferOk { value, obligations }
+    }
 }
 
 struct CheckItemTypesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
@@ -1713,14 +1747,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                           -> ty::InstantiatedPredicates<'tcx> {
         let bounds = self.tcx.item_predicates(def_id);
         let result = bounds.instantiate(self.tcx, substs);
-        let result = self.normalize_associated_types_in(span, &result.predicates);
+        let result = self.normalize_associated_types_in(span, &result);
         debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
                bounds,
                substs,
                result);
-        ty::InstantiatedPredicates {
-            predicates: result
-        }
+        result
     }
 
     /// Replace all anonymized types with fresh inference variables
@@ -1763,7 +1795,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
         where T : TypeFoldable<'tcx>
     {
-        self.inh.normalize_associated_types_in(span, self.body_id, value)
+        let ok = self.normalize_associated_types_in_as_infer_ok(span, value);
+        self.register_infer_ok_obligations(ok)
+    }
+
+    fn normalize_associated_types_in_as_infer_ok<T>(&self, span: Span, value: &T)
+                                                    -> InferOk<'tcx, T>
+        where T : TypeFoldable<'tcx>
+    {
+        self.inh.normalize_associated_types_in_as_infer_ok(span, self.body_id, value)
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
@@ -1804,32 +1844,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             .register_bound(self, ty, def_id, cause);
     }
 
-    pub fn register_predicate(&self,
-                              obligation: traits::PredicateObligation<'tcx>)
-    {
-        debug!("register_predicate({:?})", obligation);
-        if obligation.has_escaping_regions() {
-            span_bug!(obligation.cause.span, "escaping regions in predicate {:?}",
-                      obligation);
-        }
-        self.fulfillment_cx
-            .borrow_mut()
-            .register_predicate_obligation(self, obligation);
-    }
-
-    pub fn register_predicates(&self,
-                               obligations: Vec<traits::PredicateObligation<'tcx>>)
-    {
-        for obligation in obligations {
-            self.register_predicate(obligation);
-        }
-    }
-
-    pub fn register_infer_ok_obligations<T>(&self, infer_ok: InferOk<'tcx, T>) -> T {
-        self.register_predicates(infer_ok.obligations);
-        infer_ok.value
-    }
-
     pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
         let t = AstConv::ast_ty_to_ty(self, ast_t);
         self.register_wf_obligation(t, ast_t.span, traits::MiscObligation);
@@ -2072,12 +2086,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 expr, base_expr, adj_ty, autoderefs,
                 false, lvalue_pref, idx_ty)
             {
-                autoderef.finalize(lvalue_pref, &[base_expr]);
+                autoderef.finalize(lvalue_pref, base_expr);
                 return Some(final_mt);
             }
 
             if let ty::TyArray(element_ty, _) = adj_ty.sty {
-                autoderef.finalize(lvalue_pref, &[base_expr]);
+                autoderef.finalize(lvalue_pref, base_expr);
                 let adjusted_ty = self.tcx.mk_slice(element_ty);
                 return self.try_index_step(
                     MethodCall::expr(expr.id), expr, base_expr,
@@ -2161,8 +2175,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // If some lookup succeeds, write callee into table and extract index/element
         // type from the method signature.
         // If some lookup succeeded, install method in table
-        method.map(|method| {
+        method.map(|ok| {
             debug!("try_index_step: success, using overloaded indexing");
+            let method = self.register_infer_ok_obligations(ok);
             self.tables.borrow_mut().method_map.insert(method_call, method);
             (input_ty, self.make_overloaded_lvalue_return_type(method).ty)
         })
@@ -2586,7 +2601,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        let result = self.save_and_restore_obligations_in_snapshot_flag(|_| {
+                        let result = self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = FulfillmentContext::new();
                             let ok = ok; // FIXME(#30046)
                             for obligation in ok.obligations {
@@ -2755,7 +2770,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
                         let field_ty = self.field_ty(expr.span, field, substs);
                         if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
-                            autoderef.finalize(lvalue_pref, &[base]);
+                            autoderef.finalize(lvalue_pref, base);
                             self.apply_autoderef_adjustment(base.id, autoderefs, base_t);
 
                             self.tcx.check_stability(field.did, expr.id, expr.span);
@@ -2879,7 +2894,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             };
 
             if let Some(field_ty) = field {
-                autoderef.finalize(lvalue_pref, &[base]);
+                autoderef.finalize(lvalue_pref, base);
                 self.apply_autoderef_adjustment(base.id, autoderefs, base_t);
                 return field_ty;
             }
@@ -3292,8 +3307,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                         if let Some(mt) = oprnd_t.builtin_deref(true, NoPreference) {
                             oprnd_t = mt.ty;
-                        } else if let Some(method) = self.try_overloaded_deref(
+                        } else if let Some(ok) = self.try_overloaded_deref(
                                 expr.span, Some(&oprnd), oprnd_t, lvalue_pref) {
+                            let method = self.register_infer_ok_obligations(ok);
                             oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
                             self.tables.borrow_mut().method_map.insert(MethodCall::expr(expr.id),
                                                                            method);
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index cc33bd8754d9e..42296006b79d1 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -398,20 +398,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let method = match trait_did {
             Some(trait_did) => {
-                self.lookup_method_in_trait_adjusted(expr.span,
-                                                     Some(lhs_expr),
-                                                     opname,
-                                                     trait_did,
-                                                     0,
-                                                     false,
-                                                     lhs_ty,
-                                                     Some(other_tys))
+                self.lookup_method_in_trait(expr.span,
+                                            Some(lhs_expr),
+                                            opname,
+                                            trait_did,
+                                            lhs_ty,
+                                            Some(other_tys))
             }
             None => None
         };
 
         match method {
-            Some(method) => {
+            Some(ok) => {
+                let method = self.register_infer_ok_obligations(ok);
+                self.select_obligations_where_possible();
+
                 let method_ty = method.ty;
 
                 // HACK(eddyb) Fully qualified path to work around a resolve bug.
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 7fffbd14e2160..f196aa82b1ef3 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -11,22 +11,18 @@
 // Type resolution: the phase that finds all the types in the AST with
 // unresolved type variables and replaces "ty_var" types with their
 // substitutions.
-use self::ResolveReason::*;
 
 use check::FnCtxt;
+use rustc::hir;
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use rustc::infer::{InferCtxt};
 use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
 use rustc::ty::adjustment;
 use rustc::ty::fold::{TypeFolder,TypeFoldable};
-use rustc::infer::{InferCtxt, FixupError};
 use rustc::util::nodemap::{DefIdMap, DefIdSet};
-
-use std::mem;
-
 use syntax::ast;
 use syntax_pos::Span;
-
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir;
+use std::mem;
 
 ///////////////////////////////////////////////////////////////////////////
 // Entry point
@@ -37,9 +33,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let item_id = self.tcx.hir.body_owner(body.id());
         let item_def_id = self.tcx.hir.local_def_id(item_id);
 
-        let mut wbcx = WritebackCx::new(self);
+        let mut wbcx = WritebackCx::new(self, body);
         for arg in &body.arguments {
-            wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
+            wbcx.visit_node_id(arg.pat.span, arg.id);
         }
         wbcx.visit_body(body);
         wbcx.visit_upvar_borrow_map();
@@ -80,15 +76,19 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     // early-bound versions of them, visible from the
     // outside of the function. This is needed by, and
     // only populated if there are any `impl Trait`.
-    free_to_bound_regions: DefIdMap<&'gcx ty::Region>
+    free_to_bound_regions: DefIdMap<&'gcx ty::Region>,
+
+    body: &'gcx hir::Body,
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
-    fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
+    fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, body: &'gcx hir::Body)
+        -> WritebackCx<'cx, 'gcx, 'tcx> {
         let mut wbcx = WritebackCx {
             fcx: fcx,
             tables: ty::TypeckTables::empty(),
-            free_to_bound_regions: DefIdMap()
+            free_to_bound_regions: DefIdMap(),
+            body: body
         };
 
         // Only build the reverse mapping if `impl Trait` is used.
@@ -195,21 +195,20 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
     }
 
     fn visit_stmt(&mut self, s: &'gcx hir::Stmt) {
-        self.visit_node_id(ResolvingExpr(s.span), s.node.id());
+        self.visit_node_id(s.span, s.node.id());
         intravisit::walk_stmt(self, s);
     }
 
     fn visit_expr(&mut self, e: &'gcx hir::Expr) {
         self.fix_scalar_builtin_expr(e);
 
-        self.visit_node_id(ResolvingExpr(e.span), e.id);
-        self.visit_method_map_entry(ResolvingExpr(e.span),
-                                    MethodCall::expr(e.id));
+        self.visit_node_id(e.span, e.id);
+        self.visit_method_map_entry(e.span, MethodCall::expr(e.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(ResolvingExpr(e.span), arg.id);
+                self.visit_node_id(e.span, arg.id);
             }
 
             self.visit_body(body);
@@ -219,20 +218,20 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
     }
 
     fn visit_block(&mut self, b: &'gcx hir::Block) {
-        self.visit_node_id(ResolvingExpr(b.span), b.id);
+        self.visit_node_id(b.span, b.id);
         intravisit::walk_block(self, b);
     }
 
     fn visit_pat(&mut self, p: &'gcx hir::Pat) {
-        self.visit_node_id(ResolvingPattern(p.span), p.id);
+        self.visit_node_id(p.span, p.id);
         intravisit::walk_pat(self, p);
     }
 
     fn visit_local(&mut self, l: &'gcx hir::Local) {
+        intravisit::walk_local(self, l);
         let var_ty = self.fcx.local_ty(l.span, l.id);
-        let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
+        let var_ty = self.resolve(&var_ty, &l.span);
         self.write_ty_to_tables(l.id, var_ty);
-        intravisit::walk_local(self, l);
     }
 }
 
@@ -243,7 +242,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
                     let r = upvar_borrow.region;
-                    let r = self.resolve(&r, ResolvingUpvar(*upvar_id));
+                    let r = self.resolve(&r, &upvar_id.var_id);
                     ty::UpvarCapture::ByRef(
                         ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
                 }
@@ -257,7 +256,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
     fn visit_closures(&mut self) {
         for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() {
-            let closure_ty = self.resolve(closure_ty, ResolvingClosure(id));
+            let closure_ty = self.resolve(closure_ty, &id);
             self.tables.closure_tys.insert(id, closure_ty);
         }
 
@@ -282,8 +281,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
     fn visit_anon_types(&mut self) {
         let gcx = self.tcx().global_tcx();
         for (&node_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {
-            let reason = ResolvingAnonTy(node_id);
-            let inside_ty = self.resolve(&concrete_ty, reason);
+            let inside_ty = self.resolve(&concrete_ty, &node_id);
 
             // Convert the type from the function into a type valid outside
             // the function, by replacing free regions with early-bound ones.
@@ -305,7 +303,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                     ty::ReLateBound(..) |
                     ty::ReScope(_) |
                     ty::ReSkolemized(..) => {
-                        let span = reason.span(self.tcx());
+                        let span = node_id.to_span(&self.fcx.tcx);
                         span_err!(self.tcx().sess, span, E0564,
                                   "only named lifetimes are allowed in `impl Trait`, \
                                    but `{}` was found in the type `{}`", r, inside_ty);
@@ -314,7 +312,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
                     ty::ReVar(_) |
                     ty::ReErased => {
-                        let span = reason.span(self.tcx());
+                        let span = node_id.to_span(&self.fcx.tcx);
                         span_bug!(span, "invalid region in impl Trait: {:?}", r);
                     }
                 }
@@ -324,37 +322,37 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         }
     }
 
-    fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) {
+    fn visit_node_id(&mut self, span: Span, node_id: ast::NodeId) {
         // Export associated path extensions.
-        if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) {
-            self.tables.type_relative_path_defs.insert(id, def);
+        if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&node_id) {
+            self.tables.type_relative_path_defs.insert(node_id, def);
         }
 
-        // Resolve any borrowings for the node with id `id`
-        self.visit_adjustments(reason, id);
+        // Resolve any borrowings for the node with id `node_id`
+        self.visit_adjustments(span, node_id);
 
-        // Resolve the type of the node with id `id`
-        let n_ty = self.fcx.node_ty(id);
-        let n_ty = self.resolve(&n_ty, reason);
-        self.write_ty_to_tables(id, n_ty);
-        debug!("Node {} has type {:?}", id, n_ty);
+        // Resolve the type of the node with id `node_id`
+        let n_ty = self.fcx.node_ty(node_id);
+        let n_ty = self.resolve(&n_ty, &span);
+        self.write_ty_to_tables(node_id, n_ty);
+        debug!("Node {} has type {:?}", node_id, n_ty);
 
         // Resolve any substitutions
-        self.fcx.opt_node_ty_substs(id, |item_substs| {
-            let item_substs = self.resolve(item_substs, reason);
+        self.fcx.opt_node_ty_substs(node_id, |item_substs| {
+            let item_substs = self.resolve(item_substs, &span);
             if !item_substs.is_noop() {
-                debug!("write_substs_to_tcx({}, {:?})", id, item_substs);
+                debug!("write_substs_to_tcx({}, {:?})", node_id, item_substs);
                 assert!(!item_substs.substs.needs_infer());
-                self.tables.item_substs.insert(id, item_substs);
+                self.tables.item_substs.insert(node_id, item_substs);
             }
         });
     }
 
-    fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) {
-        let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id);
+    fn visit_adjustments(&mut self, span: Span, node_id: ast::NodeId) {
+        let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&node_id);
         match adjustments {
             None => {
-                debug!("No adjustments for node {}", id);
+                debug!("No adjustments for node {}", node_id);
             }
 
             Some(adjustment) => {
@@ -381,29 +379,29 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
                     adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => {
                         for autoderef in 0..autoderefs {
-                            let method_call = MethodCall::autoderef(id, autoderef as u32);
-                            self.visit_method_map_entry(reason, method_call);
+                            let method_call = MethodCall::autoderef(node_id, autoderef as u32);
+                            self.visit_method_map_entry(span, method_call);
                         }
 
                         adjustment::Adjust::DerefRef {
                             autoderefs: autoderefs,
-                            autoref: self.resolve(&autoref, reason),
+                            autoref: self.resolve(&autoref, &span),
                             unsize: unsize,
                         }
                     }
                 };
                 let resolved_adjustment = adjustment::Adjustment {
                     kind: resolved_adjustment,
-                    target: self.resolve(&adjustment.target, reason)
+                    target: self.resolve(&adjustment.target, &span)
                 };
-                debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
-                self.tables.adjustments.insert(id, resolved_adjustment);
+                debug!("Adjustments for node {}: {:?}", node_id, resolved_adjustment);
+                self.tables.adjustments.insert(node_id, resolved_adjustment);
             }
         }
     }
 
     fn visit_method_map_entry(&mut self,
-                              reason: ResolveReason,
+                              method_span: Span,
                               method_call: MethodCall) {
         // Resolve any method map entry
         let new_method = match self.fcx.tables.borrow_mut().method_map.remove(&method_call) {
@@ -413,8 +411,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                        method);
                 let new_method = MethodCallee {
                     def_id: method.def_id,
-                    ty: self.resolve(&method.ty, reason),
-                    substs: self.resolve(&method.substs, reason),
+                    ty: self.resolve(&method.ty, &method_span),
+                    substs: self.resolve(&method.substs, &method_span),
                 };
 
                 Some(new_method)
@@ -430,72 +428,49 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
     fn visit_liberated_fn_sigs(&mut self) {
         for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() {
-            let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id));
+            let fn_sig = self.resolve(fn_sig, &node_id);
             self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone());
         }
     }
 
     fn visit_fru_field_types(&mut self) {
         for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() {
-            let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id));
+            let ftys = self.resolve(ftys, &node_id);
             self.tables.fru_field_types.insert(node_id, ftys);
         }
     }
 
     fn visit_type_nodes(&self) {
         for (&id, ty) in self.fcx.ast_ty_to_ty_cache.borrow().iter() {
-            let ty = self.resolve(ty, ResolvingTyNode(id));
+            let ty = self.resolve(ty, &id);
             self.fcx.tcx.ast_ty_to_ty_cache.borrow_mut().insert(id, ty);
         }
     }
 
-    fn resolve<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
+    fn resolve<T>(&self, x: &T, span: &Locatable) -> T::Lifted
         where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
     {
-        let x = x.fold_with(&mut Resolver::new(self.fcx, reason));
+        let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
         if let Some(lifted) = self.tcx().lift_to_global(&x) {
             lifted
         } else {
-            span_bug!(reason.span(self.tcx()),
-                      "writeback: `{:?}` missing from the global type context", x);
+            span_bug!(span.to_span(&self.fcx.tcx),
+                      "writeback: `{:?}` missing from the global type context",
+                      x);
         }
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// Resolution reason.
-
-#[derive(Copy, Clone, Debug)]
-enum ResolveReason {
-    ResolvingExpr(Span),
-    ResolvingLocal(Span),
-    ResolvingPattern(Span),
-    ResolvingUpvar(ty::UpvarId),
-    ResolvingClosure(ast::NodeId),
-    ResolvingFnSig(ast::NodeId),
-    ResolvingFieldTypes(ast::NodeId),
-    ResolvingAnonTy(ast::NodeId),
-    ResolvingTyNode(ast::NodeId),
+trait Locatable {
+    fn to_span(&self, tcx: &TyCtxt) -> Span;
 }
 
-impl<'a, 'gcx, 'tcx> ResolveReason {
-    fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
-        match *self {
-            ResolvingExpr(s) => s,
-            ResolvingLocal(s) => s,
-            ResolvingPattern(s) => s,
-            ResolvingUpvar(upvar_id) => {
-                tcx.expr_span(upvar_id.closure_expr_id)
-            }
-            ResolvingClosure(id) |
-            ResolvingFnSig(id) |
-            ResolvingFieldTypes(id) |
-            ResolvingTyNode(id) |
-            ResolvingAnonTy(id) => {
-                tcx.hir.span(id)
-            }
-        }
-    }
+impl Locatable for Span {
+    fn to_span(&self, _: &TyCtxt) -> Span { *self }
+}
+
+impl Locatable for ast::NodeId {
+    fn to_span(&self, tcx: &TyCtxt) -> Span { tcx.hir.span(*self) }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -505,82 +480,25 @@ impl<'a, 'gcx, 'tcx> ResolveReason {
 struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-    reason: ResolveReason,
+    span: &'cx Locatable,
+    body: &'gcx hir::Body,
 }
 
 impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
-    fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
-           reason: ResolveReason)
-           -> Resolver<'cx, 'gcx, 'tcx>
+    fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, span: &'cx Locatable, body: &'gcx hir::Body)
+        -> Resolver<'cx, 'gcx, 'tcx>
     {
-        Resolver::from_infcx(fcx, reason)
-    }
-
-    fn from_infcx(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-                  reason: ResolveReason)
-                  -> Resolver<'cx, 'gcx, 'tcx>
-    {
-        Resolver { infcx: infcx,
-                   tcx: infcx.tcx,
-                   reason: reason }
+        Resolver {
+            tcx: fcx.tcx,
+            infcx: fcx,
+            span: span,
+            body: body,
+        }
     }
 
-    fn report_error(&self, e: FixupError) {
+    fn report_error(&self, t: Ty<'tcx>) {
         if !self.tcx.sess.has_errors() {
-            match self.reason {
-                ResolvingExpr(span) => {
-                    struct_span_err!(
-                        self.tcx.sess, span, E0101,
-                        "cannot determine a type for this expression: {}", e)
-                        .span_label(span, &format!("cannot resolve type of expression"))
-                        .emit();
-                }
-
-                ResolvingLocal(span) => {
-                    struct_span_err!(
-                        self.tcx.sess, span, E0102,
-                        "cannot determine a type for this local variable: {}", e)
-                        .span_label(span, &format!("cannot resolve type of variable"))
-                        .emit();
-                }
-
-                ResolvingPattern(span) => {
-                    span_err!(self.tcx.sess, span, E0103,
-                        "cannot determine a type for this pattern binding: {}", e);
-                }
-
-                ResolvingUpvar(upvar_id) => {
-                    let span = self.reason.span(self.tcx);
-                    span_err!(self.tcx.sess, span, E0104,
-                        "cannot resolve lifetime for captured variable `{}`: {}",
-                        self.tcx.local_var_name_str(upvar_id.var_id), e);
-                }
-
-                ResolvingClosure(_) => {
-                    let span = self.reason.span(self.tcx);
-                    span_err!(self.tcx.sess, span, E0196,
-                              "cannot determine a type for this closure")
-                }
-
-                ResolvingFnSig(_) |
-                ResolvingFieldTypes(_) |
-                ResolvingTyNode(_) => {
-                    // any failures here should also fail when
-                    // resolving the patterns, closure types, or
-                    // something else.
-                    let span = self.reason.span(self.tcx);
-                    self.tcx.sess.delay_span_bug(
-                        span,
-                        &format!("cannot resolve some aspect of data for {:?}: {}",
-                                 self.reason, e));
-                }
-
-                ResolvingAnonTy(_) => {
-                    let span = self.reason.span(self.tcx);
-                    span_err!(self.tcx.sess, span, E0563,
-                              "cannot determine a type for this `impl Trait`: {}", e)
-                }
-            }
+            self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t);
         }
     }
 }
@@ -593,20 +511,21 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> {
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match self.infcx.fully_resolve(&t) {
             Ok(t) => t,
-            Err(e) => {
+            Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable",
                        t);
-                self.report_error(e);
+                self.report_error(t);
                 self.tcx().types.err
             }
         }
     }
 
+    // FIXME This should be carefully checked
+    // We could use `self.report_error` but it doesn't accept a ty::Region, right now.
     fn fold_region(&mut self, r: &'tcx ty::Region) -> &'tcx ty::Region {
         match self.infcx.fully_resolve(&r) {
             Ok(r) => r,
-            Err(e) => {
-                self.report_error(e);
+            Err(_) => {
                 self.tcx.mk_region(ty::ReStatic)
             }
         }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 2d72052f1e5ad..68afcae2b6746 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1351,50 +1351,6 @@ extern "rust-intrinsic" {
 ```
 "##,
 
-E0101: r##"
-You hit this error because the compiler lacks the information to
-determine a type for this expression. Erroneous code example:
-
-```compile_fail,E0101
-let x = |_| {}; // error: cannot determine a type for this expression
-```
-
-You have two possibilities to solve this situation:
-
-* Give an explicit definition of the expression
-* Infer the expression
-
-Examples:
-
-```
-let x = |_ : u32| {}; // ok!
-// or:
-let x = |_| {};
-x(0u32);
-```
-"##,
-
-E0102: r##"
-You hit this error because the compiler lacks the information to
-determine the type of this variable. Erroneous code example:
-
-```compile_fail,E0282
-// could be an array of anything
-let x = []; // error: cannot determine a type for this local variable
-```
-
-To solve this situation, constrain the type of the variable.
-Examples:
-
-```
-#![allow(unused_variables)]
-
-fn main() {
-    let x: [u8; 0] = [];
-}
-```
-"##,
-
 E0107: r##"
 This error means that an incorrect number of lifetime parameters were provided
 for a type (like a struct or enum) or trait:
@@ -4146,8 +4102,8 @@ register_diagnostics! {
 //  E0068,
 //  E0085,
 //  E0086,
-    E0103, // @GuillaumeGomez: I was unable to get this error, try your best!
-    E0104,
+//  E0103,
+//  E0104,
 //  E0123,
 //  E0127,
 //  E0129,
@@ -4164,7 +4120,7 @@ register_diagnostics! {
 //  E0188, // can not cast an immutable reference to a mutable pointer
 //  E0189, // deprecated: can only cast a boxed pointer to a boxed object
 //  E0190, // deprecated: can only cast a &-pointer to an &-object
-    E0196, // cannot determine a type for this closure
+//  E0196, // cannot determine a type for this closure
     E0203, // type parameter has more than one relaxed default bound,
            // and only one is supported
     E0208,
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index db446d88900c1..22889b5de4c2a 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -10,11 +10,18 @@
 
 //! Cross-platform path manipulation.
 //!
-//! This module provides two types, [`PathBuf`] and [`Path`][`Path`] (akin to [`String`]
+//! This module provides two types, [`PathBuf`] and [`Path`] (akin to [`String`]
 //! and [`str`]), for working with paths abstractly. These types are thin wrappers
 //! around [`OsString`] and [`OsStr`] respectively, meaning that they work directly
 //! on strings according to the local platform's path syntax.
 //!
+//! Paths can be parsed into [`Component`]s by iterating over the structure
+//! returned by the [`components`] method on [`Path`]. [`Component`]s roughly
+//! correspond to the substrings between path separators (`/` or `\`). You can
+//! reconstruct an equivalent path from components with the [`push`] method on
+//! [`PathBuf`]; note that the paths may differ syntactically by the
+//! normalization described in the documentation for the [`components`] method.
+//!
 //! ## Simple usage
 //!
 //! Path manipulation includes both parsing components from slices and building
@@ -50,62 +57,11 @@
 //! path.set_extension("dll");
 //! ```
 //!
-//! ## Path components and normalization
-//!
-//! The path APIs are built around the notion of "components", which roughly
-//! correspond to the substrings between path separators (`/` and, on Windows,
-//! `\`). The APIs for path parsing are largely specified in terms of the path's
-//! components, so it's important to clearly understand how those are
-//! determined.
-//!
-//! A path can always be reconstructed into an *equivalent* path by
-//! putting together its components via `push`. Syntactically, the
-//! paths may differ by the normalization described below.
-//!
-//! ### Component types
-//!
-//! Components come in several types:
-//!
-//! * Normal components are the default: standard references to files or
-//! directories. The path `a/b` has two normal components, `a` and `b`.
-//!
-//! * Current directory components represent the `.` character. For example,
-//! `./a` has a current directory component and a normal component `a`.
-//!
-//! * The root directory component represents a separator that designates
-//!   starting from root. For example, `/a/b` has a root directory component
-//!   followed by normal components `a` and `b`.
-//!
-//! On Windows, an additional component type comes into play:
-//!
-//! * Prefix components, of which there is a large variety. For example, `C:`
-//! and `\\server\share` are prefixes. The path `C:windows` has a prefix
-//! component `C:` and a normal component `windows`; the path `C:\windows` has a
-//! prefix component `C:`, a root directory component, and a normal component
-//! `windows`.
-//!
-//! ### Normalization
-//!
-//! Aside from splitting on the separator(s), there is a small amount of
-//! "normalization":
-//!
-//! * Repeated separators are ignored: `a/b` and `a//b` both have components `a`
-//!   and `b`.
-//!
-//! * Occurrences of `.` are normalized away, *except* if they are at
-//! the beginning of the path (in which case they are often meaningful
-//! in terms of path searching). So, for example, `a/./b`, `a/b/`,
-//! `/a/b/.` and `a/b` all have components `a` and `b`, but `./a/b`
-//! has a leading current directory component.
-//!
-//! No other normalization takes place by default. In particular,
-//! `a/c` and `a/b/../c` are distinct, to account for the possibility
-//! that `b` is a symbolic link (so its parent isn't `a`). Further
-//! normalization is possible to build on top of the components APIs,
-//! and will be included in this library in the near future.
-//!
+//! [`Component`]: ../../std/path/enum.Component.html
+//! [`components`]: ../../std/path/struct.Path.html#method.components
 //! [`PathBuf`]: ../../std/path/struct.PathBuf.html
 //! [`Path`]: ../../std/path/struct.Path.html
+//! [`push`]: ../../std/path/struct.PathBuf.html#method.push
 //! [`String`]: ../../std/string/struct.String.html
 //! [`str`]: ../../std/primitive.str.html
 //! [`OsString`]: ../../std/ffi/struct.OsString.html
@@ -143,36 +99,81 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
 // Windows Prefixes
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Path prefixes (Windows only).
+/// Windows path prefixes, e.g. `C:` or `\\server\share`.
 ///
-/// Windows uses a variety of path styles, including references to drive
-/// volumes (like `C:`), network shared folders (like `\\server\share`) and
-/// others. In addition, some path prefixes are "verbatim", in which case
-/// `/` is *not* treated as a separator and essentially no normalization is
-/// performed.
+/// Windows uses a variety of path prefix styles, including references to drive
+/// volumes (like `C:`), network shared folders (like `\\server\share`), and
+/// others. In addition, some path prefixes are "verbatim" (i.e. prefixed with
+/// `\\?\`), in which case `/` is *not* treated as a separator and essentially
+/// no normalization is performed.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::{Component, Path, Prefix};
+/// use std::path::Prefix::*;
+/// use std::ffi::OsStr;
+///
+/// fn get_path_prefix(s: &str) -> Prefix {
+///     let path = Path::new(s);
+///     match path.components().next().unwrap() {
+///         Component::Prefix(prefix_component) => prefix_component.kind(),
+///         _ => panic!(),
+///     }
+/// }
+///
+/// # if cfg!(windows) {
+/// assert_eq!(Verbatim(OsStr::new("pictures")),
+///            get_path_prefix(r"\\?\pictures\kittens"));
+/// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),
+///            get_path_prefix(r"\\?\UNC\server\share"));
+/// assert_eq!(VerbatimDisk('C' as u8), get_path_prefix(r"\\?\c:\"));
+/// assert_eq!(DeviceNS(OsStr::new("BrainInterface")),
+///            get_path_prefix(r"\\.\BrainInterface"));
+/// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),
+///            get_path_prefix(r"\\server\share"));
+/// assert_eq!(Disk('C' as u8), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));
+/// # }
+/// ```
 #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Prefix<'a> {
-    /// Prefix `\\?\`, together with the given component immediately following it.
+    /// Verbatim prefix, e.g. `\\?\cat_pics`.
+    ///
+    /// Verbatim prefixes consist of `\\?\` immediately followed by the given
+    /// component.
     #[stable(feature = "rust1", since = "1.0.0")]
     Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 
-    /// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
+    /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,
+    /// e.g. `\\?\UNC\server\share`.
+    ///
+    /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the
+    /// server's hostname and a share name.
     #[stable(feature = "rust1", since = "1.0.0")]
     VerbatimUNC(
         #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
         #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
     ),
 
-    /// Prefix like `\\?\C:\`, for the given drive letter
+    /// Verbatim disk prefix, e.g. `\\?\C:\`.
+    ///
+    /// Verbatim disk prefixes consist of `\\?\` immediately followed by the
+    /// drive letter and `:\`.
     #[stable(feature = "rust1", since = "1.0.0")]
     VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
 
-    /// Prefix `\\.\`, together with the given component immediately following it.
+    /// Device namespace prefix, e.g. `\\.\COM42`.
+    ///
+    /// Device namespace prefixes consist of `\\.\` immediately followed by the
+    /// device name.
     #[stable(feature = "rust1", since = "1.0.0")]
     DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 
-    /// Prefix `\\server\share`, with the given "server" and "share" components.
+    /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.
+    /// `\\server\share`.
+    ///
+    /// UNC prefixes consist of the server's hostname and a share name.
     #[stable(feature = "rust1", since = "1.0.0")]
     UNC(
         #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
@@ -217,6 +218,20 @@ impl<'a> Prefix<'a> {
     }
 
     /// Determines if the prefix is verbatim, i.e. begins with `\\?\`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Prefix::*;
+    /// use std::ffi::OsStr;
+    ///
+    /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim());
+    /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
+    /// assert!(VerbatimDisk('C' as u8).is_verbatim());
+    /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim());
+    /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
+    /// assert!(!Disk('C' as u8).is_verbatim());
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_verbatim(&self) -> bool {
@@ -356,9 +371,42 @@ enum State {
     Done = 3,
 }
 
-/// A Windows path prefix, e.g. `C:` or `\\server\share`.
+/// A structure wrapping a Windows path prefix as well as its unparsed string
+/// representation.
+///
+/// In addition to the parsed [`Prefix`] information returned by [`kind`],
+/// `PrefixComponent` also holds the raw and unparsed [`OsStr`] slice,
+/// returned by [`as_os_str`].
+///
+/// Instances of this `struct` can be obtained by matching against the
+/// [`Prefix` variant] on [`Component`].
 ///
 /// Does not occur on Unix.
+///
+/// # Examples
+///
+/// ```
+/// # if cfg!(windows) {
+/// use std::path::{Component, Path, Prefix};
+/// use std::ffi::OsStr;
+///
+/// let path = Path::new(r"c:\you\later\");
+/// match path.components().next().unwrap() {
+///     Component::Prefix(prefix_component) => {
+///         assert_eq!(Prefix::Disk('C' as u8), prefix_component.kind());
+///         assert_eq!(OsStr::new("c:"), prefix_component.as_os_str());
+///     }
+///     _ => unreachable!(),
+/// }
+/// # }
+/// ```
+///
+/// [`as_os_str`]: #method.as_os_str
+/// [`Component`]: enum.Component.html
+/// [`kind`]: #method.kind
+/// [`OsStr`]: ../../std/ffi/struct.OsStr.html
+/// [`Prefix` variant]: enum.Component.html#variant.Prefix
+/// [`Prefix`]: enum.Prefix.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone, Eq, Debug)]
 pub struct PrefixComponent<'a> {
@@ -370,13 +418,20 @@ pub struct PrefixComponent<'a> {
 }
 
 impl<'a> PrefixComponent<'a> {
-    /// The parsed prefix data.
+    /// Returns the parsed prefix data.
+    ///
+    /// See [`Prefix`]'s documentation for more information on the different
+    /// kinds of prefixes.
+    ///
+    /// [`Prefix`]: enum.Prefix.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn kind(&self) -> Prefix<'a> {
         self.parsed
     }
 
-    /// The raw `OsStr` slice for this prefix.
+    /// Returns the raw [`OsStr`] slice for this prefix.
+    ///
+    /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_os_str(&self) -> &'a OsStr {
         self.raw
@@ -413,11 +468,11 @@ impl<'a> Hash for PrefixComponent<'a> {
 
 /// A single component of a path.
 ///
-/// See the module documentation for an in-depth explanation of components and
-/// their role in the API.
+/// A `Component` roughtly corresponds to a substring between path separators
+/// (`/` or `\`).
 ///
-/// This `enum` is created from iterating over the [`path::Components`]
-/// `struct`.
+/// This `enum` is created by iterating over [`Components`], which in turn is
+/// created by the [`components`][`Path::components`] method on [`Path`].
 ///
 /// # Examples
 ///
@@ -434,37 +489,49 @@ impl<'a> Hash for PrefixComponent<'a> {
 /// ]);
 /// ```
 ///
-/// [`path::Components`]: struct.Components.html
+/// [`Components`]: struct.Components.html
+/// [`Path`]: struct.Path.html
+/// [`Path::components`]: struct.Path.html#method.components
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Component<'a> {
     /// A Windows path prefix, e.g. `C:` or `\\server\share`.
     ///
+    /// There is a large variety of prefix types, see [`Prefix`]'s documentation
+    /// for more.
+    ///
     /// Does not occur on Unix.
+    ///
+    /// [`Prefix`]: enum.Prefix.html
     #[stable(feature = "rust1", since = "1.0.0")]
     Prefix(
         #[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>
     ),
 
-    /// The root directory component, appears after any prefix and before anything else
+    /// The root directory component, appears after any prefix and before anything else.
+    ///
+    /// It represents a separator that designates that a path starts from root.
     #[stable(feature = "rust1", since = "1.0.0")]
     RootDir,
 
-    /// A reference to the current directory, i.e. `.`
+    /// A reference to the current directory, i.e. `.`.
     #[stable(feature = "rust1", since = "1.0.0")]
     CurDir,
 
-    /// A reference to the parent directory, i.e. `..`
+    /// A reference to the parent directory, i.e. `..`.
     #[stable(feature = "rust1", since = "1.0.0")]
     ParentDir,
 
-    /// A normal component, i.e. `a` and `b` in `a/b`
+    /// A normal component, e.g. `a` and `b` in `a/b`.
+    ///
+    /// This variant is the most common one, it represents references to files
+    /// or directories.
     #[stable(feature = "rust1", since = "1.0.0")]
     Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 }
 
 impl<'a> Component<'a> {
-    /// Extracts the underlying `OsStr` slice.
+    /// Extracts the underlying [`OsStr`] slice.
     ///
     /// # Examples
     ///
@@ -475,6 +542,8 @@ impl<'a> Component<'a> {
     /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();
     /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
     /// ```
+    ///
+    /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_os_str(self) -> &'a OsStr {
         match self {
@@ -494,12 +563,10 @@ impl<'a> AsRef<OsStr> for Component<'a> {
     }
 }
 
-/// The core iterator giving the components of a path.
-///
-/// See the module documentation for an in-depth explanation of components and
-/// their role in the API.
+/// An interator over the [`Component`]s of a [`Path`].
 ///
-/// This `struct` is created by the [`path::Path::components`] method.
+/// This `struct` is created by the [`components`] method on [`Path`].
+/// See its documentation for more.
 ///
 /// # Examples
 ///
@@ -513,7 +580,9 @@ impl<'a> AsRef<OsStr> for Component<'a> {
 /// }
 /// ```
 ///
-/// [`path::Path::components`]: struct.Path.html#method.components
+/// [`Component`]: enum.Component.html
+/// [`components`]: struct.Path.html#method.components
+/// [`Path`]: struct.Path.html
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Components<'a> {
@@ -534,9 +603,15 @@ pub struct Components<'a> {
     back: State,
 }
 
-/// An iterator over the components of a path, as [`OsStr`] slices.
+/// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices.
 ///
+/// This `struct` is created by the [`iter`] method on [`Path`].
+/// See its documentation for more.
+///
+/// [`Component`]: enum.Component.html
+/// [`iter`]: struct.Path.html#method.iter
 /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
+/// [`Path`]: struct.Path.html
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a> {
@@ -762,6 +837,18 @@ impl<'a> fmt::Debug for Iter<'a> {
 
 impl<'a> Iter<'a> {
     /// Extracts a slice corresponding to the portion of the path remaining for iteration.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();
+    /// iter.next();
+    /// iter.next();
+    ///
+    /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_path(&self) -> &'a Path {
         self.inner.as_path()
@@ -1067,9 +1154,10 @@ impl PathBuf {
 
     /// Truncate `self` to [`self.parent`].
     ///
-    /// Returns false and does nothing if [`self.file_name`] is `None`.
+    /// Returns `false` and does nothing if [`self.file_name`] is [`None`].
     /// Otherwise, returns `true`.
     ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     /// [`self.parent`]: struct.PathBuf.html#method.parent
     /// [`self.file_name`]: struct.PathBuf.html#method.file_name
     ///
@@ -1132,10 +1220,11 @@ impl PathBuf {
 
     /// Updates [`self.extension`] to `extension`.
     ///
-    /// If [`self.file_name`] is `None`, does nothing and returns `false`.
+    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
+    /// returns `true` and updates the extension otherwise.
     ///
-    /// Otherwise, returns `true`; if [`self.extension`] is [`None`], the
-    /// extension is added; otherwise it is replaced.
+    /// If [`self.extension`] is [`None`], the extension is added; otherwise
+    /// it is replaced.
     ///
     /// [`self.file_name`]: struct.PathBuf.html#method.file_name
     /// [`self.extension`]: struct.PathBuf.html#method.extension
@@ -1195,7 +1284,10 @@ impl PathBuf {
         self.inner
     }
 
-    /// Converts this `PathBuf` into a boxed `Path`.
+    /// Converts this `PathBuf` into a [boxed][`Box`] [`Path`].
+    ///
+    /// [`Box`]: ../../std/boxed/struct.Box.html
+    /// [`Path`]: struct.Path.html
     #[unstable(feature = "into_boxed_path", issue = "40380")]
     pub fn into_boxed_path(self) -> Box<Path> {
         unsafe { mem::transmute(self.inner.into_boxed_os_str()) }
@@ -1402,10 +1494,14 @@ pub struct Path {
     inner: OsStr,
 }
 
-/// An error returned from the [`Path::strip_prefix`] method indicating that the
-/// prefix was not found in `self`.
+/// An error returned from [`Path::strip_prefix`][`strip_prefix`] if the prefix
+/// was not found.
+///
+/// This `struct` is created by the [`strip_prefix`] method on [`Path`].
+/// See its documentation for more.
 ///
-/// [`Path::strip_prefix`]: struct.Path.html#method.strip_prefix
+/// [`strip_prefix`]: struct.Path.html#method.strip_prefix
+/// [`Path`]: struct.Path.html
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(since = "1.7.0", feature = "strip_prefix")]
 pub struct StripPrefixError(());
@@ -1421,7 +1517,7 @@ impl Path {
         os_str_as_u8_slice(&self.inner)
     }
 
-    /// Directly wrap a string slice as a `Path` slice.
+    /// Directly wraps a string slice as a `Path` slice.
     ///
     /// This is a cost-free conversion.
     ///
@@ -1525,10 +1621,11 @@ impl Path {
         PathBuf::from(self.inner.to_os_string())
     }
 
-    /// A path is *absolute* if it is independent of the current directory.
+    /// Returns `true` if the `Path` is absolute, i.e. if it is independent of
+    /// the current directory.
     ///
     /// * On Unix, a path is absolute if it starts with the root, so
-    /// `is_absolute` and `has_root` are equivalent.
+    /// `is_absolute` and [`has_root`] are equivalent.
     ///
     /// * On Windows, a path is absolute if it has a prefix and starts with the
     /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
@@ -1540,6 +1637,8 @@ impl Path {
     ///
     /// assert!(!Path::new("foo.txt").is_absolute());
     /// ```
+    ///
+    /// [`has_root`]: #method.has_root
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     pub fn is_absolute(&self) -> bool {
@@ -1547,7 +1646,9 @@ impl Path {
         self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some())
     }
 
-    /// A path is *relative* if it is not absolute.
+    /// Return `false` if the `Path` is relative, i.e. not absolute.
+    ///
+    /// See [`is_absolute`]'s documentation for more details.
     ///
     /// # Examples
     ///
@@ -1556,6 +1657,8 @@ impl Path {
     ///
     /// assert!(Path::new("foo.txt").is_relative());
     /// ```
+    ///
+    /// [`is_absolute`]: #method.is_absolute
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_relative(&self) -> bool {
         !self.is_absolute()
@@ -1565,7 +1668,7 @@ impl Path {
         self.components().prefix
     }
 
-    /// A path has a root if the body of the path begins with the directory separator.
+    /// Returns `true` if the `Path` has a root.
     ///
     /// * On Unix, a path has a root if it begins with `/`.
     ///
@@ -1586,7 +1689,7 @@ impl Path {
         self.components().has_root()
     }
 
-    /// The path without its final component, if any.
+    /// Returns the `Path` without its final component, if there is one.
     ///
     /// Returns [`None`] if the path terminates in a root or prefix.
     ///
@@ -1619,9 +1722,9 @@ impl Path {
         })
     }
 
-    /// The final component of the path, if it is a normal file.
+    /// Returns the final component of the `Path`, if it is a normal file.
     ///
-    /// If the path terminates in `..`, `file_name` will return [`None`].
+    /// Returns [`None`] If the path terminates in `..`.
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
@@ -1631,18 +1734,7 @@ impl Path {
     /// use std::path::Path;
     /// use std::ffi::OsStr;
     ///
-    /// let path = Path::new("foo.txt");
-    /// let os_str = OsStr::new("foo.txt");
-    ///
-    /// assert_eq!(Some(os_str), path.file_name());
-    /// ```
-    ///
-    /// # Other examples
-    ///
-    /// ```
-    /// use std::path::Path;
-    /// use std::ffi::OsStr;
-    ///
+    /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt").file_name());
     /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
     /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
     /// assert_eq!(None, Path::new("foo.txt/..").file_name());
@@ -1869,7 +1961,21 @@ impl Path {
         buf
     }
 
-    /// Produce an iterator over the components of the path.
+    /// Produces an iterator over the [`Component`]s of the path.
+    ///
+    /// When parsing the path, there is a small amount of normalization:
+    ///
+    /// * Repeated separators are ignored, so `a/b` and `a//b` both have
+    ///   `a` and `b` as components.
+    ///
+    /// * Occurentces of `.` are normalized away, exept if they are at the
+    ///   beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
+    ///   `a/b` all have `a` and `b` as components, but `./a/b` starts with
+    ///   an additional [`CurDir`] component.
+    ///
+    /// Note that no other normalization takes place; in particular, `a/c`
+    /// and `a/b/../c` are distinct, to account for the possibility that `b`
+    /// is a symbolic link (so its parent isn't `a`).
     ///
     /// # Examples
     ///
@@ -1884,6 +1990,9 @@ impl Path {
     /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
     /// assert_eq!(components.next(), None)
     /// ```
+    ///
+    /// [`Component`]: enum.Component.html
+    /// [`CurDir`]: enum.Component.html#variant.CurDir
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn components(&self) -> Components {
         let prefix = parse_prefix(self.as_os_str());
@@ -1896,8 +2005,13 @@ impl Path {
         }
     }
 
-    /// Produce an iterator over the path's components viewed as [`OsStr`] slices.
+    /// Produces an iterator over the path's components viewed as [`OsStr`]
+    /// slices.
+    ///
+    /// For more information about the particulars of how the path is separated
+    /// into components, see [`components`].
     ///
+    /// [`components`]: #method.components
     /// [`OsStr`]: ../ffi/struct.OsStr.html
     ///
     /// # Examples
@@ -1936,7 +2050,7 @@ impl Path {
         Display { path: self }
     }
 
-    /// Query the file system to get information about a file, directory, etc.
+    /// Queries the file system to get information about a file, directory, etc.
     ///
     /// This function will traverse symbolic links to query information about the
     /// destination file.
@@ -1959,7 +2073,7 @@ impl Path {
         fs::metadata(self)
     }
 
-    /// Query the metadata about a file without following symlinks.
+    /// Queries the metadata about a file without following symlinks.
     ///
     /// This is an alias to [`fs::symlink_metadata`].
     ///
@@ -2096,7 +2210,11 @@ impl Path {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
     }
 
-    /// Converts a `Box<Path>` into a `PathBuf` without copying or allocating.
+    /// Converts a [`Box<Path>`][`Box`] into a [`PathBuf`] without copying or
+    /// allocating.
+    ///
+    /// [`Box`]: ../../std/boxed/struct.Box.html
+    /// [`PathBuf`]: struct.PathBuf.html
     #[unstable(feature = "into_boxed_path", issue = "40380")]
     pub fn into_path_buf(self: Box<Path>) -> PathBuf {
         let inner: Box<OsStr> = unsafe { mem::transmute(self) };
@@ -2118,7 +2236,26 @@ impl fmt::Debug for Path {
     }
 }
 
-/// Helper struct for safely printing paths with `format!()` and `{}`
+/// Helper struct for safely printing paths with [`format!`] and `{}`.
+///
+/// A [`Path`] might contain non-Unicode data. This `struct` implements the
+/// [`Display`] trait in a way that mitigates that. It is created by the
+/// [`display`][`Path::display`] method on [`Path`].
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// let path = Path::new("/tmp/foo.rs");
+///
+/// println!("{}", path.display());
+/// ```
+///
+/// [`Display`]: ../../std/fmt/trait.Display.html
+/// [`format!`]: ../../std/macro.format.html
+/// [`Path`]: struct.Path.html
+/// [`Path::display`]: struct.Path.html#method.display
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Display<'a> {
     path: &'a Path,
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 129674b74769c..175447e111270 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -344,9 +344,6 @@ declare_features! (
     // Used to preserve symbols (see llvm.used)
     (active, used, "1.18.0", Some(40289)),
 
-    // Hack to document `-Z linker-flavor` in The Unstable Book
-    (active, linker_flavor, "1.18.0", Some(41142)),
-
     // Allows module-level inline assembly by way of global_asm!()
     (active, global_asm, "1.18.0", Some(35119)),
 
diff --git a/src/stage0.txt b/src/stage0.txt
index 60fbcadf49157..dc6931c1d0bdd 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,4 +12,4 @@
 # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was
 # released on `$date`
 
-rustc: beta-2017-03-21
+rustc: beta-2017-04-05
diff --git a/src/test/compile-fail/issue-12187-1.rs b/src/test/compile-fail/issue-12187-1.rs
index 6aeb9442c40ed..a79021d3cd5d2 100644
--- a/src/test/compile-fail/issue-12187-1.rs
+++ b/src/test/compile-fail/issue-12187-1.rs
@@ -16,5 +16,5 @@ fn main() {
     let &v = new();
     //~^ ERROR type annotations needed [E0282]
     //~| NOTE cannot infer type for `_`
-    //~| NOTE consider giving a type to pattern
+    //~| NOTE consider giving the pattern a type
 }
diff --git a/src/test/compile-fail/issue-12187-2.rs b/src/test/compile-fail/issue-12187-2.rs
index d52ed06c4085d..38b3c5d4e9a64 100644
--- a/src/test/compile-fail/issue-12187-2.rs
+++ b/src/test/compile-fail/issue-12187-2.rs
@@ -16,5 +16,5 @@ fn main() {
     let &v = new();
     //~^ ERROR type annotations needed [E0282]
     //~| NOTE cannot infer type for `_`
-    //~| NOTE consider giving a type to pattern
+    //~| NOTE consider giving the pattern a type
 }
diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.c b/src/test/run-make/extern-fn-struct-passing-abi/test.c
index 4e09928edc6d1..44a940a17a98a 100644
--- a/src/test/run-make/extern-fn-struct-passing-abi/test.c
+++ b/src/test/run-make/extern-fn-struct-passing-abi/test.c
@@ -137,6 +137,21 @@ void byval_rect_with_float(int32_t a, int32_t b, float c, int32_t d,
     assert(s.d == 556);
 }
 
+// System V x86_64 ABI:
+// a, b, d, e, f should be byval pointer (on the stack)
+// g passed via register (fixes #41375)
+//
+// Win64 ABI:
+// a, b, d, e, f, g should be byval pointer
+void byval_rect_with_many_huge(struct Huge a, struct Huge b, struct Huge c,
+                               struct Huge d, struct Huge e, struct Huge f,
+                               struct Rect g) {
+    assert(g.a == 123);
+    assert(g.b == 456);
+    assert(g.c == 789);
+    assert(g.d == 420);
+}
+
 // System V x86_64 & Win64 ABI:
 // a, b should be in registers
 // s should be split across 2 integer registers
diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.rs b/src/test/run-make/extern-fn-struct-passing-abi/test.rs
index ff845a644b114..aaae7ae4fb49b 100644
--- a/src/test/run-make/extern-fn-struct-passing-abi/test.rs
+++ b/src/test/run-make/extern-fn-struct-passing-abi/test.rs
@@ -64,6 +64,8 @@ extern {
 
     fn byval_rect_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect);
 
+    fn byval_rect_with_many_huge(a: Huge, b: Huge, c: Huge, d: Huge, e: Huge, f: Huge, g: Rect);
+
     fn split_rect(a: i32, b: i32, s: Rect);
 
     fn split_rect_floats(a: f32, b: f32, s: FloatRect);
@@ -95,6 +97,12 @@ fn main() {
         byval_many_rect(1, 2, 3, 4, 5, 6, s);
         byval_rect_floats(1., 2., 3., 4., 5., 6., 7., s, u);
         byval_rect_with_float(1, 2, 3.0, 4, 5, 6, s);
+        byval_rect_with_many_huge(v, v, v, v, v, v, Rect {
+            a: 123,
+            b: 456,
+            c: 789,
+            d: 420
+        });
         split_rect(1, 2, s);
         split_rect_floats(1., 2., u);
         split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s);
diff --git a/src/test/run-pass/coerce-overloaded-autoderef.rs b/src/test/run-pass/coerce-overloaded-autoderef.rs
index a053311a0403e..091e29dd18a6b 100644
--- a/src/test/run-pass/coerce-overloaded-autoderef.rs
+++ b/src/test/run-pass/coerce-overloaded-autoderef.rs
@@ -68,4 +68,8 @@ fn use_vec_ref(v: &Vec<u8>) {
     use_slice(&&&mut &&&v);
 }
 
+fn use_op_rhs(s: &mut String) {
+    *s += {&String::from(" ")};
+}
+
 pub fn main() {}
diff --git a/src/test/ui/type-check/issue-38812-2.rs b/src/test/ui/type-check/cannot_infer_local_or_array.rs
similarity index 94%
rename from src/test/ui/type-check/issue-38812-2.rs
rename to src/test/ui/type-check/cannot_infer_local_or_array.rs
index c476657d20796..0b35a9c3dbebc 100644
--- a/src/test/ui/type-check/issue-38812-2.rs
+++ b/src/test/ui/type-check/cannot_infer_local_or_array.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let (x,) = (vec![],);
+    let x = [];
 }
diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr
new file mode 100644
index 0000000000000..8c52bb5a1d3a5
--- /dev/null
+++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr
@@ -0,0 +1,10 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot_infer_local_or_array.rs:12:13
+   |
+12 |     let x = [];
+   |         -   ^^ cannot infer type for `_`
+   |         |
+   |         consider giving `x` a type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-check/issue-38812.rs b/src/test/ui/type-check/cannot_infer_local_or_vec.rs
similarity index 100%
rename from src/test/ui/type-check/issue-38812.rs
rename to src/test/ui/type-check/cannot_infer_local_or_vec.rs
diff --git a/src/test/ui/type-check/issue-38812.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr
similarity index 86%
rename from src/test/ui/type-check/issue-38812.stderr
rename to src/test/ui/type-check/cannot_infer_local_or_vec.stderr
index 6365e761453f9..4788fad20889e 100644
--- a/src/test/ui/type-check/issue-38812.stderr
+++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/issue-38812.rs:12:13
+  --> $DIR/cannot_infer_local_or_vec.rs:12:13
    |
 12 |     let x = vec![];
    |         -   ^^^^^^ cannot infer type for `T`
diff --git a/src/test/compile-fail/E0101.rs b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs
similarity index 73%
rename from src/test/compile-fail/E0101.rs
rename to src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs
index 0005da048e4a5..8d32c1ff683bb 100644
--- a/src/test/compile-fail/E0101.rs
+++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -9,7 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let x = |_| {};
-    //~^ ERROR E0101
-    //~| NOTE cannot resolve type of expression
+    let (x, ) = (vec![], );
 }
diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr
new file mode 100644
index 0000000000000..ccffadebe9ee2
--- /dev/null
+++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:12:18
+   |
+12 |     let (x, ) = (vec![], );
+   |         -----    ^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving the pattern a type
+   |
+   = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/issue-22897.rs b/src/test/ui/type-check/issue-22897.rs
similarity index 63%
rename from src/test/compile-fail/issue-22897.rs
rename to src/test/ui/type-check/issue-22897.rs
index c6bbf2d4abcc0..296dc81a89bcf 100644
--- a/src/test/compile-fail/issue-22897.rs
+++ b/src/test/ui/type-check/issue-22897.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -10,10 +10,6 @@
 
 fn main() { }
 
-// Before these errors would ICE as "cat_expr Errd" because the errors
-// were unknown when the bug was triggered.
-
 fn unconstrained_type() {
     [];
-    //~^ ERROR cannot determine a type for this expression: unconstrained type
 }
diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr
new file mode 100644
index 0000000000000..9568411885192
--- /dev/null
+++ b/src/test/ui/type-check/issue-22897.stderr
@@ -0,0 +1,8 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-22897.rs:14:5
+   |
+14 |     [];
+   |     ^^ cannot infer type for `[_; 0]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-check/issue-38812-2.stderr b/src/test/ui/type-check/issue-38812-2.stderr
deleted file mode 100644
index 156a6bdee9979..0000000000000
--- a/src/test/ui/type-check/issue-38812-2.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/issue-38812-2.rs:12:17
-   |
-12 |     let (x,) = (vec![],);
-   |         ----    ^^^^^^ cannot infer type for `T`
-   |         |
-   |         consider giving a type to pattern
-   |
-   = note: this error originates in a macro outside of the current crate
-
-error: aborting due to previous error
-
diff --git a/src/test/compile-fail/E0102.rs b/src/test/ui/type-check/unknown_type_for_closure.rs
similarity index 67%
rename from src/test/compile-fail/E0102.rs
rename to src/test/ui/type-check/unknown_type_for_closure.rs
index 6a17ddebd1dc1..f1d357df12c43 100644
--- a/src/test/compile-fail/E0102.rs
+++ b/src/test/ui/type-check/unknown_type_for_closure.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -9,8 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let x = [];
-    //~^ ERROR type annotations needed
-    //~| NOTE consider giving `x` a type
-    //~| NOTE cannot infer type for `_`
+    let x = |_| {    };
 }
diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr
new file mode 100644
index 0000000000000..afbd15ca486bd
--- /dev/null
+++ b/src/test/ui/type-check/unknown_type_for_closure.stderr
@@ -0,0 +1,8 @@
+error[E0282]: type annotations needed
+  --> $DIR/unknown_type_for_closure.rs:12:14
+   |
+12 |     let x = |_| {    };
+   |              ^ consider giving this closure parameter a type
+
+error: aborting due to previous error
+
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index c7113edbf9e68..012ee835494e8 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -22,12 +22,6 @@ struct Test {
 }
 
 const TEST_REPOS: &'static [Test] = &[
-    Test {
-        name: "cargo",
-        repo: "https://github.com/rust-lang/cargo",
-        sha: "0e1e34be7540bdaed4918457654fbf028cf69e56",
-        lock: None,
-    },
     Test {
         name: "iron",
         repo: "https://github.com/iron/iron",
@@ -61,20 +55,6 @@ const TEST_REPOS: &'static [Test] = &[
 ];
 
 fn main() {
-    // One of the projects being tested here is Cargo, and when being tested
-    // Cargo will at some point call `nmake.exe` on Windows MSVC. Unfortunately
-    // `nmake` will read these two environment variables below and try to
-    // intepret them. We're likely being run, however, from MSYS `make` which
-    // uses the same variables.
-    //
-    // As a result, to prevent confusion and errors, we remove these variables
-    // from our environment to prevent passing MSYS make flags to nmake, causing
-    // it to blow up.
-    if cfg!(target_env = "msvc") {
-        env::remove_var("MAKE");
-        env::remove_var("MAKEFLAGS");
-    }
-
     let args = env::args().collect::<Vec<_>>();
     let ref cargo = args[1];
     let out_dir = Path::new(&args[2]);
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 137de561c76c9..531c148de2619 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -147,6 +147,12 @@ fn check(cache: &mut Cache,
         return None;
     }
 
+    // mdbook uses the HTML <base> tag to handle links for subdirectories, which
+    // linkchecker doesn't support
+    if file.to_str().unwrap().contains("unstable-book/") {
+        return None;
+    }
+
     let res = load_file(cache, root, PathBuf::from(file), SkipRedirect);
     let (pretty_file, contents) = match res {
         Ok(res) => res,
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index d5b95c08306b2..e320933067226 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
 clap = "2.19.3"
 
 [dependencies.mdbook]
-version = "0.0.18"
+version = "0.0.19"
 default-features = false
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 371922c9e6bb2..664aecfcbdb9d 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -2,6 +2,3 @@
 name = "tidy"
 version = "0.1.0"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
-
-[dependencies]
-regex = "0.2"
\ No newline at end of file
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 44063e627a362..3e7046d05f490 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -14,8 +14,6 @@
 //! etc. This is run by default on `make check` and as part of the auto
 //! builders.
 
-extern crate regex;
-
 use std::env;
 use std::fs;
 use std::io::{self, Write};
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 2d3d9e80257f9..5a6524b3e88e5 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -10,35 +10,36 @@
 
 use std::collections::HashSet;
 use std::fs;
-use std::io::{self, BufRead};
 use std::path;
 use features::{collect_lang_features, collect_lib_features, Status};
 
 const PATH_STR: &'static str = "doc/unstable-book/src";
 
-const SUMMARY_FILE_NAME: &'static str = "SUMMARY.md";
+const LANG_FEATURES_DIR: &'static str = "language-features";
 
-static EXCLUDE: &'static [&'static str; 2] = &[SUMMARY_FILE_NAME, "the-unstable-book.md"];
+const LIB_FEATURES_DIR: &'static str = "library-features";
 
 /// Build the path to the Unstable Book source directory from the Rust 'src' directory
 fn unstable_book_path(base_src_path: &path::Path) -> path::PathBuf {
     base_src_path.join(PATH_STR)
 }
 
-/// Build the path to the Unstable Book SUMMARY file from the Rust 'src' directory
-fn unstable_book_summary_path(base_src_path: &path::Path) -> path::PathBuf {
-    unstable_book_path(base_src_path).join(SUMMARY_FILE_NAME)
+/// Directory where the features are documented within the Unstable Book source directory
+fn unstable_book_lang_features_path(base_src_path: &path::Path) -> path::PathBuf {
+    unstable_book_path(base_src_path).join(LANG_FEATURES_DIR)
 }
 
-/// Open the Unstable Book SUMMARY file
-fn open_unstable_book_summary_file(base_src_path: &path::Path) -> fs::File {
-    fs::File::open(unstable_book_summary_path(base_src_path))
-        .expect("could not open Unstable Book SUMMARY.md")
+/// Directory where the features are documented within the Unstable Book source directory
+fn unstable_book_lib_features_path(base_src_path: &path::Path) -> path::PathBuf {
+    unstable_book_path(base_src_path).join(LIB_FEATURES_DIR)
 }
 
 /// Test to determine if DirEntry is a file
 fn dir_entry_is_file(dir_entry: &fs::DirEntry) -> bool {
-    dir_entry.file_type().expect("could not determine file type of directory entry").is_file()
+    dir_entry
+        .file_type()
+        .expect("could not determine file type of directory entry")
+        .is_file()
 }
 
 /// Retrieve names of all lang-related unstable features
@@ -61,75 +62,81 @@ fn collect_unstable_lib_feature_names(base_src_path: &path::Path) -> HashSet<Str
         .collect()
 }
 
-/// Retrieve names of all unstable features
-fn collect_unstable_feature_names(base_src_path: &path::Path) -> HashSet<String> {
-    collect_unstable_lib_feature_names(base_src_path)
-        .union(&collect_unstable_lang_feature_names(base_src_path))
-        .map(|n| n.to_owned())
-        .collect::<HashSet<_, _>>()
-}
-
-/// Retrieve file names of all sections in the Unstable Book with:
-///
-/// * hyphens replaced by underscores
-/// * the markdown suffix ('.md') removed
-fn collect_unstable_book_section_file_names(base_src_path: &path::Path) -> HashSet<String> {
-    fs::read_dir(unstable_book_path(base_src_path))
+fn collect_unstable_book_section_file_names(dir: &path::Path) -> HashSet<String> {
+    fs::read_dir(dir)
         .expect("could not read directory")
         .into_iter()
         .map(|entry| entry.expect("could not read directory entry"))
         .filter(dir_entry_is_file)
         .map(|entry| entry.file_name().into_string().unwrap())
-        .filter(|n| EXCLUDE.iter().all(|e| n != e))
         .map(|n| n.trim_right_matches(".md").replace('-', "_"))
         .collect()
 }
 
-/// Retrieve unstable feature names that are in the Unstable Book SUMMARY file
-fn collect_unstable_book_summary_links(base_src_path: &path::Path) -> HashSet<String> {
-    let summary_link_regex =
-        ::regex::Regex::new(r"^- \[(\S+)\]\(\S+\.md\)").expect("invalid regex");
-    io::BufReader::new(open_unstable_book_summary_file(base_src_path))
-        .lines()
-        .map(|l| l.expect("could not read line from file"))
-        .filter_map(|line| {
-            summary_link_regex.captures(&line).map(|c| {
-                                                       c.get(1)
-                                                           .unwrap()
-                                                           .as_str()
-                                                           .to_owned()
-                                                   })
-        })
-        .collect()
+/// Retrieve file names of all library feature sections in the Unstable Book with:
+///
+/// * hyphens replaced by underscores
+/// * the markdown suffix ('.md') removed
+fn collect_unstable_book_lang_features_section_file_names(base_src_path: &path::Path)
+                                                          -> HashSet<String> {
+    collect_unstable_book_section_file_names(&unstable_book_lang_features_path(base_src_path))
+}
+
+/// Retrieve file names of all language feature sections in the Unstable Book with:
+///
+/// * hyphens replaced by underscores
+/// * the markdown suffix ('.md') removed
+fn collect_unstable_book_lib_features_section_file_names(base_src_path: &path::Path)
+                                                         -> HashSet<String> {
+    collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path))
 }
 
 pub fn check(path: &path::Path, bad: &mut bool) {
-    let unstable_feature_names = collect_unstable_feature_names(path);
-    let unstable_book_section_file_names = collect_unstable_book_section_file_names(path);
-    let unstable_book_links = collect_unstable_book_summary_links(path);
-
-    // Check for Unstable Book section names with no corresponding SUMMARY.md link
-    for feature_name in &unstable_book_section_file_names - &unstable_book_links {
-        tidy_error!(
-            bad,
-            "The Unstable Book section '{}' needs to have a link in SUMMARY.md",
-            feature_name);
-    }
+
+    // Library features
+
+    let unstable_lib_feature_names = collect_unstable_lib_feature_names(path);
+    let unstable_book_lib_features_section_file_names =
+        collect_unstable_book_lib_features_section_file_names(path);
 
     // Check for unstable features that don't have Unstable Book sections
-    for feature_name in &unstable_feature_names - &unstable_book_section_file_names {
-        tidy_error!(
-            bad,
-            "Unstable feature '{}' needs to have a section in The Unstable Book",
-            feature_name);
+    for feature_name in &unstable_lib_feature_names -
+                        &unstable_book_lib_features_section_file_names {
+        tidy_error!(bad,
+                    "Unstable library feature '{}' needs to have a section within the \
+                     'library features' section of The Unstable Book",
+                    feature_name);
+    }
+
+    // Check for Unstable Book sections that don't have a corresponding unstable feature
+    for feature_name in &unstable_book_lib_features_section_file_names -
+                        &unstable_lib_feature_names {
+        tidy_error!(bad,
+                    "The Unstable Book has a 'library feature' section '{}' which doesn't \
+                     correspond to an unstable library feature",
+                    feature_name)
+    }
+
+    // Language features
+
+    let unstable_lang_feature_names = collect_unstable_lang_feature_names(path);
+    let unstable_book_lang_features_section_file_names =
+        collect_unstable_book_lang_features_section_file_names(path);
+
+    for feature_name in &unstable_lang_feature_names -
+                        &unstable_book_lang_features_section_file_names {
+        tidy_error!(bad,
+                    "Unstable language feature '{}' needs to have a section within the \
+                     'language features' section of The Unstable Book",
+                    feature_name);
     }
 
     // Check for Unstable Book sections that don't have a corresponding unstable feature
-    for feature_name in &unstable_book_section_file_names - &unstable_feature_names {
-        tidy_error!(
-            bad,
-            "The Unstable Book has a section '{}' which doesn't correspond \
-            to an unstable feature",
-            feature_name)
+    for feature_name in &unstable_book_lang_features_section_file_names -
+                        &unstable_lang_feature_names {
+        tidy_error!(bad,
+                    "The Unstable Book has a 'language feature' section '{}' which doesn't \
+                     correspond to an unstable language feature",
+                    feature_name)
     }
 }